方法
方法的定义与调用
方法即一个java语句块,用来调用以实现一个功能,
注意为了利于后期的拓展,每个方法只应该实现一个功能,
方法的命名规则:英文,首字母小写,驼峰命名。
试举例而说明之:
public class Demo01 { //方法示例:静态方法的调用 public static void main(String[] args) { System.out.println(Demo01.add(10,5)); } //加法 public static int add(int a, int b){ return a+b; } }
我们在Demo01里面定义了一个静态方法add:
-
public修饰符表示这个方法随便调用
-
static表示这是个静态方法,无需实例化一个Demo01类就能够调用
-
int声明了这个方法的返回值是int类型的
-
add是方法名,用于调用
-
(int a, int b)说明这个方法的参数,先说明类型再说明参数名,两个参数中间用逗号隔开
-
return a+b说明这个方法的返回值,与前面声明的int类型相对应,如果声明的类型是void则无需返回值
在main方法中,我们直接调用了add方法,并输入了参数(10,5),返回的结果为15。
如果不加static关键字:
public class Demo02 { //方法示例:非静态方法的调用 public static void main(String[] args) { Demo02 demo02 = new Demo02(); //实例化一个Demo02对象 System.out.println(demo02.add(20,5)); //然后才能用里面的方法 } //加法 public int add(int a, int b){ return a+b; } }
需要实例化一个Demo02对象才能调用里面的add方法。
-
形式参数 = 形参,即定义时用的a、b
-
实际参数 = 实参,即实际传入的20、5
一个取最大值的例程:
public class Demo03 { //方法的定义与调用 public static void main(String[] args) { System.out.println(max(3,4)); } public static int max(int a,int b){ if(a>b){ return a; }else { return b; } } }
可以看到方法里有两个return,return有返回值和终止方法两个作用,
如果在选择结构中return,要保证所有可能都有可以return的值。
方法的重载
重载即同一个类中,方法名称相同,而形参不同,
编译器根据传入的实参(类型、个数),调用形参与之对应的方法,并执行。
要点:
-
方法名必须相同
-
形参必须不同(个数、类型及其排列顺序)
-
返回值可以相同也可以不同
-
仅仅返回值不同无法构成重载
例如:
public class Demo04 { //方法的重载 public static void main(String[] args) { System.out.println(max(3,4)); System.out.println(max(10,20,30)); } public static int max(int a,int b){ if(a>b){ return a; }else { return b; } } public static int max(int a,int b,int c){ if(a>b){ if (a>c){ return a; }else { return c; } }else { if (b>c){ return b; }else { return c; } } } }
代码对max方法进行了重载,使得传入的参数有两个或有三个时,能够调用对应的方法进行比较,
主程序中两行输出语句,对两个方法分别进行了调用。
还可以将参数类型改为double练习一下,类型不同也能重载,体会方法重载的概念。
可变参数
有时一个方法可能传入的参数有很多种,需要重载写很多次,很麻烦,
这时候可以使用可变参数,用一个不确定类型的参数作为形参。
注意:一个方法中最多只能有一个可变参数,而且必须是方法的最后一个参数。
在参数类型后面加省略号...,即可作为不定项参数使用:
public static void main(String[] args) { Demo05 demo05 = new Demo05(); demo05.test(1,2,3,4,5); } public void test(int... i){ for(int x:i){ System.out.println(x); } }
根据主程序中调用test时传入的实参个数,可将这些数字都输出来,此时i是一个数组。
(其实这个不定项参数本质就是可变长数组)
递归
A方法调用B方法,我们很容易理解,而递归就是A方法调用A方法。
递归在解决一些问题时可以大大减少代码量,可以用少量程序描述多次重复计算。
递归结构包含两部分:
-
递归头:什么时候不调用此方法,用于避免死循环
-
递归体:什么时候调用此方法
例如用递归实现阶乘的计算:
public static void main(String[] args) { Demo06 demo06 = new Demo06(); System.out.println(demo06.method(5)); } public int method(int i){ if (i==0||i==1){ return 1; }else if(i<0){ System.out.println("负数没有阶乘!"); return 0; }else { return i*method(i-1); } }
在递归体直接return i*method(i-1)就行了,挺巧妙的,
不过递归对计算机不友好,调用深度太多的话,计算机的容量都不够了。
数组
数组的声明与创建
什么是数组呢:
-
数组是同一类型的若干个数据的有序集合
-
即同一类型的数据,按照一定次序排列而成
-
每个数据有一个下标,即编号,可以由此被访问
数组需要声明、创建两个步骤:
//两种声明数组变量的方式 int[] arr1; //平时用这个就好 int arr2[]; //这个知道就好 //创建数组:然后还要new一下! arr1 = new int[5]; //说明数组容量
或者写在一起:
int[] arr3 = new int[3]; //声明跟创建写在一起的写法
此后要给数组赋值,可以一个一个赋值或者利用循环赋值:
(快捷键:Ctrl + Alt + ↓,将此行复制到下一行)
//一个一个赋值 arr[0] = 10; arr[1] = 20; System.out.println("一个一个赋值:"+arr[0]+"\t"+arr[1]); //利用循环赋值 System.out.print("利用循环赋值:"); for (int i = 2; i <= 4; i++) { arr[i] = (i+1)*10; System.out.print(arr[i]+"\t"); }
未赋值的数据会存放该数据类型的默认值,如int是0。
数组四个基本特点:
-
数组的长度固定,一旦声明无法改变
-
数组的数据类型固定,同一数组中的元素数据类型相同
-
数组的数据类型可以是基本类型或引用类型,数组本身是引用类型
-
数组本身就是对象,Java中的对象的存在堆中的
下标越界:一个长度为5的数组,下标编号为0到4,如果你求下标为5的值,就会报下标越界。
三种初始化及内存分析
内存分析部分直接看吧(没多少):
Java数组03:三种初始化及内存分析_哔哩哔哩_bilibili
静态初始化:
//静态初始化 int[] arr = {1,2,3,4,5}; for (int i = 0; i < 5; i++) { System.out.print(arr[i] + "\t"); }
动态初始化:
//动态初始化 int[] arr2 = new int[5]; for (int i = 0; i < 5; i++) { arr2[i] = i+1; System.out.print(arr2[i] + "\t"); }
还有一种是默认初始化,就是动态声明和创建而未赋值时,数组的默认值,
就是说,动态初始化包含默认初始化。
数组的使用
来写几个关于数组的使用的练习:
-
输出所有数组元素
-
输出所有数组元素的和
-
输出数组中的最大值
代码如下:
int[] arr = new int[10]; for (int i = 0; i < arr.length; i++) { if (i%2==0){ arr[i] = i*3; }else { arr[i] = i*2; } } //输出所有数组元素 for (int j : arr) { System.out.print(j + "\t"); } System.out.println(); //输出所有数组元素的和 int sum = 0; for (int j : arr){ sum += j; } System.out.println("sum="+sum); //输出数组元素中的最大值 int max = arr[0]; for(int j : arr){ if (j > max){ max = j; } } System.out.println("max="+max);
输出结果:
0 2 6 6 12 10 18 14 24 18 sum=110 max=24
快捷键:arr.for,出现增强for循环,arr.fori,出现普通for循环。
此外,数组可以作为方法的形参,也可以作为返回值:
//数组作为形参与返回值 public static void main(String[] args) { int[] arr = buildArray(1,2,3,4,5,6); printArray(arr); arr = reverseArray(arr); printArray(arr); } //数组作为返回值:创建数组 public static int[] buildArray(int... i){ int[] arr = new int[i.length]; for (int i1 = 0; i1 < i.length; i1++) { arr[i1] = i[i1]; } return arr; } //数组作为形参:打印数组 public static void printArray(int[] array){ for (int i : array) { System.out.print(i+"\t"); } System.out.println(); } //数组作为形参与返回值:反转数组 public static int[] reverseArray(int[] array){ //直接调用System里的方法创建数组 int[] arr = new int[array.length]; System.arraycopy(array, 0, arr, 0, array.length); int c; for (int i = 0; i < arr.length/2; i++) { c = arr[i]; arr[i] = arr[arr.length - i - 1]; arr[arr.length - i - 1] = c; } return arr; }
主程序调用buildArray方法初始化数组,再调用printArray方法打印出来,
然后调用reverseArray反转数组并打印。
多维数组
二维数组就是数组之数组。
定义二维数组:
int[][] arr = {{1,2,3},{4,5,6}}; System.out.println(arr.length); System.out.println(arr[0].length); System.out.println(arr[1][1]); //取arr中第二个数组的第二个数 //遍历二维数组 for (int[] ints : arr) { for (int anInt : ints) { System.out.print(anInt+"\t"); } System.out.println(); }
arr.length是最外层的长度,arr[0].length是其中第一个数组的长度,
三维数组同理,很少用。
Arrays类
Arrays工具类方便我们操作数组,常用方法如下:
public static void main(String[] args) { int[] arr = {1,8,3,2,5}; System.out.println(Arrays.toString(arr)); Arrays.sort(arr); System.out.println(Arrays.toString(arr)); Arrays.fill(arr,1,4,10); System.out.println(Arrays.toString(arr)); }
分别是打印数组、数组升序、数组填充,结果如下:
[1, 8, 3, 2, 5] [1, 2, 3, 5, 8] [1, 10, 10, 10, 8]
冒泡排序
最出名的排序算法,八大排序之一!
-
比较数组中两个相邻的元素
-
如果第一个比第二个大,则调换他们的位置
-
每轮比较之后,可以得到一个最大或最小值
-
循环直到结束
用两层嵌套加上交换的方法即可实现:
int[] arr = {4,5,8,7,2,2}; for (int i = 0; i < arr.length-1; i++) { for (int j = 0; j < arr.length-1-i; j++) { if (arr[j+1]<arr[j]){ int temp = arr[j+1]; arr[j+1] = arr[j]; arr[j] = temp; } } } System.out.println(Arrays.toString(arr));
考虑到即使数组已经有序,程序还是会走完循环,我们可以加个flag判断,优化一下:
int[] arr = {4,5,8,7,2,2}; boolean flag = false; for (int i = 0; i < arr.length-1; i++) { for (int j = 0; j < arr.length-1-i; j++) { if (arr[j+1]<arr[j]){ int temp = arr[j+1]; arr[j+1] = arr[j]; arr[j] = temp; flag = true; } } if (flag==false){ break; } } System.out.println(Arrays.toString(arr));
如果一轮排序没有产生任何调换,则说明排序已经完成,不再执行后面的轮次。