Java基础语法
数组操作的2个异常
数组的索引超过范围异常 (索引越界)
程序中访问了不存在的索引, 每个数组的索引范围从0开始,最大的索引=数组的长度-1
public static void main(String[] args) {
//定义存储int类型的数组
int[] arr = {1,2,3,4,5};
//数组中存储5个元素,长度是5个
System.out.println(arr.length);
//索引0-4
//访问不存在的索引
System.out.println(arr[5]);
}
数组的空指针异常
当数组的引用类型变量arr
不保存数组的地址了,再操作数组,就出现空指针异常
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
System.out.println(arr);
arr = null; //数组 = 空 , 不再保存数组在内存中的地址了
//不能操作数组的任何内容
System.out.println(arr.length);
}
数组的内存问题
两个数组在内存中的表现
每个数组,都会在内存中,开辟空间存储数据, 内存之间是相互独立的,没有关联
一个数组就会占用一个内存空间
public static void main(String[] args) {
//定义2个数组
int[] arr1 = new int[]{1,2,3,4,5};
int[] arr2 = new int[]{6,7,8,9,0};
//输出数组,看到不同的地址
System.out.println(arr1);
System.out.println(arr2);
System.out.println(arr1[0]);
System.out.println(arr2[0]);
}
多个变量指向同一个内存空间
public static void main(String[] args) {
//定义数组,存储一些元素
int[] arr1 = {1,2,3,4};
System.out.println(arr1);
//将数组arr1的内存地址,赋值到另一个变量
int[] arr2 = arr1;
System.out.println(arr2);
System.out.println(arr1[0]);
arr2[0] = 100;
System.out.println(arr1[0]);
}
数组的常见操作
数组的遍历 (迭代)
所谓数组的遍历,就是将数组中的每一个元素分别取出的过程.
数组的遍历,是数组其他操作的一个最基础的案例
循环遍历取出数组的元素,循环的次数由长度决定
public static void main(String[] args) {
int[] arr = {2,4,6,8,10};
//循环遍历数组,取出数组中的每个元素,依次取出
//数组的长度是5个,索引0-4 for(知道次数) while(不知道次数)
for(int i = 0 ; i < arr.length ; i++) {
//利用循环中的变量i, 作为索引使用,取出数组的元素
System.out.println(arr[i]);
}
}
数组最值获取
取出数组中的最大值,或者是最小值
实现核心思想 : 遍历中进行比较
/*
* 获取数组的最大值
* 实现步骤 :
* 1.定义变量,保存数组0索引上的元素
* 2.遍历数组,取出数组的每个元素
* 3.数组的元素和变量,进行比较
* 如果数组的元素,大于变量
* 数组的元素,存储在变量中
* 4.数组全部遍历完成,变量保存的就是最大值
*/
public class ArrayDemo06 {
public static void main(String[] args) {
//创建数组
int[] arr = {1,5,10,2,6,9,0,7};
//定义变量,保存数组0索引上的元素
int max = arr[0];
//遍历数组,取出数组的每个元素
for(int i = 1 ; i < arr.length ; i++) {
//数组的元素,和变量max比较
if(arr[i] > max) {
//赋值变量
max = arr[i];
}
}
//数组全部遍历完成,变量保存的就是最大值
System.out.println("最大值是::"+max);
}
}
数组的倒序遍历
public static void main(String[] args) {
int[] arr = {1,3,5,7,9};
//从数组的最大索引开始遍历
for(int i = arr.length-1 ; i >= 0 ; i--) {
System.out.println(arr[i]);
}
}
数组拼接为字符串
任意数组 : int[] arr = {1,2,3,4,5,6,7}, 遍历数组,取出元素,元素拼接为一个字符串
输出的格式 [1,2,3,4,5,6,7]
/*
* 输出的格式 [1,2,3,4,5,6,7]
* 数组遍历,拼接成上面的格式
* 解决最后一个逗号问题 :
* 判断循环变量 i , 如果i的值,到达了数组的最大索引
* 字符串拼接] ,而不是逗号
*
*/
public class ArrayDemo08 {
public static void main(String[] args) {
//创建数组
int[] arr = {1,2,3,4,5,6,7};
//遍历,取出元素,字符串的拼接
String s = "[";
for(int i = 0 ; i < arr.length ;i++) {
//判断i是不是最大索引,如果是拼接]
if(i == arr.length - 1) {
s = s + arr[i]+"]";
}else {
s = s + arr[i]+",";
}
}
System.out.println(s);
}
}
数组元素的查找
已知数组 : 在数组中查找一个元素是否存在
元素存在于数组中 : 返回元素所在的索引
元素不存在数组中 : 返回负数
实现功能的核心思想 :
/*
* 数组元素基本查找
* 已知数组 : 在数组中查找一个元素是否存在
元素存在于数组中 : 返回元素所在的索引
元素不存在数组中 : 返回负数
实现功能的核心思想 : 遍历,进行比较
实现思想 :
1\. 定义数组
2\. 定义要查找的元素
3\. 定义变量,保存查找后的结果 (数组的索引,或者是负数)
4: 遍历数组,取出每个元素,和要查找的元素对比
一旦找到,就不会在进行比较了
*/
public class ArrayDemo09 {
public static void main(String[] args) {
//1\. 定义数组
int[] arr = {1,5,6,7,2,3,8};
//2\. 定义要查找的元素
int key = 1;
//3\. 定义变量,保存查找后的结果 (数组的索引,或者是负数)
int index = -1;
//4: 遍历数组,取出每个元素,和要查找的元素对比
for(int i = 0 ; i < arr.length ; i++) {
//查找的元素 和 数组的元素相等,找到了
if(key == arr[i]) {
//数组的索引,赋值到变量index
index = i;
//不需要再计算了吧,结束循环
break;
}
}
if(index >= 0) {
System.out.println("元素找到了,在"+index+"这个索引");
}else{
System.out.println("抱歉,元素未找到");
}
}
}
数组翻转
所谓数组翻转,就是数组中元素的位置发生了转变 不等于倒序遍历
原始数组 : {1,2,3,4,5}
翻转数据 : {5,4,3,2,1}
/*
* 数组的翻转
*
* 数组最远端的元素换位
*
* 实现思想 :
* 1\. 定义2个变量
* 一个变量,保存数组的最小索引
* 一个变量,保存数组的最大索引
*
* 2: 当最小索引,超过最大的索引,程序结束
*
* 3: 利用循环实现
*
* 4: 第三方变量的位置交换
*/
public class ArrayDemo11 {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,0};
//一个变量,保存数组的最小索引
//一个变量,保存数组的最大索引
int min = 0;
int max = arr.length - 1;
for(; min <= max ;) {
//第三方变量交换位置
int temp = arr[max]; //临时变量,保存数组的最大索引
//最小索引的元素,赋值到最大索引
arr[max] = arr[min];
//临时变量的值,赋值到小索引上
arr[min] = temp;
//位置交换完毕,修改索引
min++;
max--;
}
//数组遍历
for(int i = 0 ; i < arr.length ; i++) {
System.out.println(arr[i]);
}
}
}
以上程序小的优化
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,0};
//一个变量,保存数组的最小索引
//一个变量,保存数组的最大索引
/* int min = 0;
int max = arr.length - 1;*/
for(int min = 0 , max = arr.length - 1; min <= max ;min++ ,max--) {
//第三方变量交换位置
int temp = arr[max]; //临时变量,保存数组的最大索引
//最小索引的元素,赋值到最大索引
arr[max] = arr[min];
//临时变量的值,赋值到小索引上
arr[min] = temp;
}
//数组遍历
for(int i = 0 ; i < arr.length ; i++) {
System.out.println(arr[i]);
}
}
二维数组
一维数组 : 一个数组,存储的是需要的数据 int[] arr = {123}
-
二维数组 : 一个数组,存储的元素,是另一个数组. 理解为数组中的数组
- 定义方式 :
数据类型[][] array = new 数据类型[3][2];
格式解析 : 定义了一个二维数组
[3] : 二维数组的长度, 这个二维数组里面存储了3个一维数组
[2] : 每个一维数组的长度是2
* 二维数组中,存储的是一维数组的内存地址
public static void main(String[] args) {
/*
* 二维数组的长度是3,存储3个一维数组
* 每个一维数组,可以存储2个元素
*/
int[][] array = new int[3][2];
System.out.println(array);// [[I@15db9742
//思考?
System.out.println(array[0]); // [I@6d06d69c
}
* 定义方式:
数据类型[][] array = new 数据类型[][]{}
创建数组直接赋值元素
public static void main(String[] args) {
int[][] array = new int[][] { {1,2},{3,4,5,6},{7,8,9} };
System.out.println(array);
//思考, 输出5
System.out.println(array[1][2]);
//数组的越界异常
System.out.println(array[2][2]);
}
* 定义方式:
数据类型[][] array = {};
public static void main(String[] args) {
int[][] array = { {1,2,3},{4,5},{6,7,8,9,0} };
System.out.println(array);
}
遍历
二维数组的遍历 : 和一维数组遍历几乎是一样的
利用嵌套循环,双for, 外循环,遍历二维数组,内循环,遍历一维数组
public static void main(String[] args) {
int[][] array = { {1,2,3},{4,5},{6,7,8,9,0} };
//外循环,遍历二维数组,取出里面的3个一维数组
for(int i = 0 ; i < array.length; i++) {
//System.out.println(array[i]);
//内循环,遍历每个一维数组
for(int j = 0; j <array[i].length;j++ ) {
System.out.print(array[i][j]);
}
System.out.println();
}
}
方法
方法概念
方法(Method)称为函数(Function)
方法 : 在程序中是一个可以完成某个功能的独立代码片段
某个功能 : 只要可以实现的都是功能 (求和)
独立代码 : 方法是在一个{} 实现的, 不同的方法之间是没有联系的
方法好处 : 可以将重复的代码抽取出来,方便我们反复应用.
方法定义
- 定义格式
修饰符 返回值类型 方法名(参数列表){
方法体,主体
return ;
}
* 修饰符 : 目前我们很多点没有讲解,现在就是固定用法 `public static`
* 返回值类型 : 本质上是数据类型,方法是实现功能的代码,功能实现完毕后应该是有结果的,结果的数据类型
* 方法名 : 标识符,自定义, 见名知意
* 参数列表 : 方法要实现的功能中,是否会有未知的数据,就是参数列表
* 方法体 : 写完成功能的代码
方法定义的练习
- 要求 : 使用方法技术,实现两个整数的求和
/*
* 我们自己定义方法,实现需求 实现两个整数的求和
* 2个分析 :
* 功能计算后的结果是什么,还是整数 返回值
* 功能计算中是否存在未知的数据, 两个整数就是未知的
* 写在方法的参数列表, 定义2个整数类型变量
*/
public static int sum(int a, int b) {
// 方法体 : 写完成功能的代码
return a + b;
}
方法的调用
什么是方法的调用 : 就是让我们写好的方法执行起来
如何调用方法 : call name 叫名字
传递方法的参数, 接收方法的返回值结果
public static void main(String[] args) {
//调用写的方法 sum, 明确方法中的2个未知数
int i = sum(5,6); // 11
System.out.println(i);
}
/*
* 我们自己定义方法,实现需求 实现两个整数的求和
* 2个分析 :
* 功能计算后的结果是什么,还是整数 返回值
* 功能计算中是否存在未知的数据, 两个整数就是未知的
* 写在方法的参数列表, 定义2个整数类型变量
*/
public static int sum(int a, int b) {
// 方法体 : 写完成功能的代码
return a + b;
}
方法调用的内存图
方法的运行,是在方法栈运行.
方法的压栈和方法的弹栈,方法进入内存(栈)到达底部, 栈内存特点是先进去的后出来.
方法定义的注意事项 (匹配)
方法不能定义在另一个方法中,写在类中
方法的定义没有先后顺序的
方法定义的返回值类型,必须和return后面的类型一致
调用方法传递参数也要一致
如果方法定义上,返回值是void, 你却返回了值
方法定义的练习
- 定义方法 : 实现任意整数的乘法表
public static void main(String[] args) {
//调用打印乘法表的方法
printChengFaBiao(7);
}
/*
* 定义方法 : 实现任意整数的乘法表
* 分析:
* 返回值: 功能实现后,结果的数据类型, 没有返回结果 void
* 方法参数: 实现功能的未知数, 任意整数
*
* 方法的返回值没有,void 方法里面可以不写 return
*/
public static void printChengFaBiao(int num) {
//实现乘法表的功能
for(int i = 1 ; i <= num ; i++) {
for(int j = 1; j <= i ; j++) {
System.out.print(j+"*"+i+"="+j*i+"\t");
}
System.out.println();
}
}
- 定义方法 : 实现任意数字的高斯算法 1+2+3...+100
public static void main(String[] args) {
//调用打印乘法表的方法
//printChengFaBiao(7);
//调用高斯算法的方法
int sum = getSum(200);
System.out.println(sum);
}
/*
* 定义方法 : 实现任意数字的高斯算法 1+2+3...+100
* 分析:
* 返回值: 功能实现后,结果的数据类型, 结果是求和的数, 整数int
* 方法参数: 实现功能的未知数, 任意整数
*/
public static int getSum(int num) {
//定义变量,保存求和的结果
int sum = 0;
for(int i = 1 ; i <= num ; i++) {
sum = sum + i;
}
//计算的结果,返回
return sum;
}
/*
* 定义方法 : 实现任意整数的乘法表
* 分析:
* 返回值: 功能实现后,结果的数据类型, 没有返回结果 void
* 方法参数: 实现功能的未知数, 任意整数
*
* 方法的返回值没有,void 方法里面可以不写 return
*/
public static void printChengFaBiao(int num) {
//实现乘法表的功能
for(int i = 1 ; i <= num ; i++) {
for(int j = 1; j <= i ; j++) {
System.out.print(j+"*"+i+"="+j*i+"\t");
}
System.out.println();
}
}
方法调用上的总结 (调用方式)
-
赋值调用
- 接收方法的返回值结果
-
输出语句调用
- 直接将方法的调用,写在输出语句中
直接调用,不接收任何结果
如果方法返回值类型是 void , 不能接收返回值
public static void main(String[] args) {
//1: 赋值调用,方法必须有返回值
int i = sum(1,2);
System.out.println(i);
//2: 输出语句调用,方法直接放在输出语句
System.out.println( sum(7,8) );
//3: 直接调用,不接收任何结果
sum(1,5);
Scanner sc = new Scanner(System.in);
System.out.println( sc.nextInt() );
//System.out.println( print() );
}
public static void print() {
System.out.println("这是一个void方法");
}
public static int sum(int a, int b) {
return a + b;
}
方法的重载
方法的重载(overload) : 在同一个类中,允许方法名字是相同的,只要方法的参数列表不一致,这些方法就是重载现象.
方法的重载 : 和修饰符,返回值无关
参数列表不一致 :
包含参数的个数不同
参数的数据类型不同
参数的顺序的不同
以上三个,只要有一个不同,就是重载
public static void main(String[] args) {
//function();
}
/*
* 写方法,看其他的方法,是否与本方法重载
*/
public static void function() {
}
public static void function(int a) {
}
public static int function(double a) {
return 0;
}
void function(int a, int b) {
}
public static void function(double b,int a) {
}
public static void function(int a, double b) {
}<
- 方法重载调用练习
public static void main(String[] args) {
function((byte)1);
function((short)1);
function(1L);
}
public static void function() {
System.out.println("这是无参数的方法");
}
public static void function(byte b) {
System.out.println("字节型参数的方法: "+b);
}
public static void function(short s) {
System.out.println("短整型参数的方法: "+s);
}
public static void function(int i) {
System.out.println("整型参数的方法: "+i);
}
public static void function(long l) {
System.out.println("长整型参数的方法: "+l);
}
-
方法重载练习
需求 : 方法定义实现乘法表
用户如果传递参数,就按照他传递参数输出乘法表
用户不传递参数,输出99的, 默认
/*
* 需求 : 方法定义实现乘法表
用户如果传递参数,就按照他传递参数输出乘法表
用户不传递参数,输出99的, 默认
本案例的存在的问题 : 代码出现了重复 (很大重复)
进行简化,不能有这么大的重复
方法: 共性代码的抽取
*/
public class MethodDemo07 {
public static void main(String[] args) {
printChengFaBiao(5);
}
/*
* 写有参数的方法,传递什么,输出什么
*/
public static void printChengFaBiao(int num) {
//实现乘法表的功能
for(int i = 1 ; i <= num ; i++) {
for(int j = 1; j <= i ; j++) {
System.out.print(j+"*"+i+"="+j*i+"\t");
}
System.out.println();
}
}
/*
* 写无参数的方法,实现输出99乘法表
* 上面的方法,是带有参数的方法,传递9,就是99乘法表
* 在本方法中,调用上面的方法,传递9
*/
public static void printChengFaBiao() {
printChengFaBiao(9);
//实现乘法表的功能
/*
* for(int i = 1 ; i <= 9 ; i++) { for(int j = 1; j <= i ; j++) {
* System.out.print(j+"*"+i+"="+j*i+"\t"); } System.out.println(); }
*/
}
}
方法参数的传递效果
- 方法的参数是基本数据类型
public static void main(String[] args) {
//定义2个变量
int a = 1;
int b = 2;
//调用方法change,传递实际参数
change(a, b);
System.out.println(a); // a = 1
System.out.println(b); // b = 2
}
/*
* 定义方法,传递2个整数值
* 不返回
*/
public static void change(int a, int b) {
a = a + b;
b = b + a;
}
- 方法的参数是引用数据类型
public static void main(String[] args) {
int[] arr = {1,2,3};
System.out.println(arr[0]); // 1
//调用方法change,传递数组,传递到方法参数的也是内存的地址
change(arr);
System.out.println(arr[0]); // 100
}
//change方法参数,写数组, 方法参数接收到的也是地址
public static void change(int[] arr) {
//修改数组中的元素值
arr[0] = 100;
}