day07.可变参数 命令行参数 递归 对象数组
课前回顾:1.面向对象:Java语言的核心变成思想,自己的事情自己不做,找别人帮我去做事2.为什么要使用面向对象思想编程:为了让编写过程更简单(很多的功能别人都已经封装好了,不用我们自己一步一步的写,直接调用,就能完成想要的功能)3.什么情况下使用面向对象思想:在一个类中使用别的类的成员时,就需要new对象 点方法(new对象,点方法的过程就是在使用面向对象的过程)4.怎么用?new 对象 点方法5.类和对象类:属性(成员变量)行为(成员方法(不带static的))对象:一类事物的具体体现导包:import 包名.类名两个类不在同一个包下,需要导包在同一个包下,不用导包了lang包下类使用时无需导包创建对象:想使用哪个类中的成员,就new哪个类的对象类名 对象名 = new 类名()调用成员(成员方法,成员变量):想调用哪个成员,就用哪个对象去点哪个成员对象名.成员变量 = 值对象名.成员方法(参数)6.成员变量和局部变量的区别:a.定义位置成员变量:定义在类中方法外局部变量:定义在方法内部或者参数位置b.作用范围成员变量:作用于整个类局部变量:只作用于自己的方法中c.默认值成员:有默认值的局部:没有默认值,不手动赋值,不能直接使用d.在内存中的位置成员:在堆中局部:在栈中e.生命周期不同成员:随着对象的创建而存在,随着对象的消失而消失局部:随着方法被调用而产生,随着方法调用完毕而消失7.static:静态a.被static修饰的成员,属于类,随着类的加载而加载b.非static的属于对象,所以static的成员优先于非静态成员存在的c.只要是根据static所在的类创建出来的对象,都可以共享这个static成员d.访问:类名直接调用今日重点:1.会使用可变参数定义方法2.会简单使用递归3.会往数组中存储对象,遍历数组,获取每一个对象中的属性值4.会二分查找法
第一章.可变参数
1介绍和基本使用
1.需求:定义一个方法,实现若干个整数相加(参数类型确定,个数不确定)2.可变参数什么时候使用:当定义方法时,参数类型确定,但是个数不确定3.格式:数据类型...变量名4.可变参数的本质:数组5.注意事项:a.参数位置只能出现一个可变参数b.如果可变参数和其他的普通参数一起出现,可变参数放在最后面
public class Test01 {public static void main(String[] args) {sum(1,2,3,4,5,6,6,5,6,4,5,7);}public static void sum(int...arr){//定义一个变量sum接收两个数的和int sum = 0;for (int i = 0; i < arr.length; i++) {sum+=arr[i];}System.out.println(sum);}}
Collections类中的方法:static <T> boolean addAll(Collection<? super T> c, T... elements)->将elements代表的元素批量放到c代表的集合中
public class Test02 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");Collections.addAll(list,"涛哥","柳岩","金莲","武松");System.out.println(list);}}
2可变参数
在JDK1.5之后,如果我们定义一个方法时,此时某个形参的类型可以确定,但是形参的个数不确定,那么我们可以使用可变参数。
格式:
【修饰符】 返回值类型 方法名(【非可变参数部分的形参列表,】参数类型... 形参名){ }
要求:
(1)一个方法最多只能有一个可变参数
(2)如果一个方法包含可变参数,那么可变参数必须是形参列表的最后一个
(3)其实这个书写“≈”
【修饰符】 返回值类型 方法名(【非可变参数部分的形参列表,】参数类型[] 形参名){ }
只是后面这种定义,在调用时必须传递数组,而前者更灵活,既可以传递数组,又可以直接传递数组的元素,这样更灵活了。
示例二:求n个整数的和
public class Test01 {public static void main(String[] args) {sum(1,2,3,4,5,6,6,5,6,4,5,7);}public static void sum(int...arr){//定义一个变量sum接收两个数的和int sum = 0;for (int i = 0; i < arr.length; i++) {sum+=arr[i];}System.out.println(sum);}}
示例二:字符串拼接
需求一:返回n个字符串拼接结果,如果没有传入字符串,那么返回空字符串””
public class Test03 {public static void main(String[] args) {String concat = concat("hello", "world", "柳岩", "最美");System.out.println(concat);}public static String concat(String...arr){//定义一个str,用于接收两个字符串拼接的结果String str = "";for (int i = 0; i < arr.length; i++) {str+=arr[i];}return str;}}
需求二:n个字符串进行拼接,每一个字符串之间使用某字符进行分隔,如果没有传入字符串,那么返回空字符串””
调用方法:concat(",","hello","world")-> hello,world
public class Test04 {public static void main(String[] args) {String concat = concat(",", "hello", "world");System.out.println(concat);}public static String concat(String s,String...arr){String str = "";for (int i = 0; i < arr.length; i++) {if (i==arr.length-1){// str = str+arr[i];str+=arr[i];}else{//str = str+arr[i]+s;str+=arr[i]+s;}}return str;}}
第二章.递归
1.从前有座山,山上有座庙,庙里有个老和尚,老和尚跟小和尚讲故事,讲的啥呢?从前有座山,山上有座庙,庙里有个老和尚,老和尚跟小和尚讲故事,讲的啥呢?从前有座山,山上有座庙,庙里有个老和尚,老和尚跟小和尚讲故事,讲的啥呢?2.递归概述:方法内部自己调用自己->直接递归public static void method(){method();}方法之间互相调用->间接递归public static void method1(){method2();}public static void method2(){method3();}public static void method3(){method1();}3.注意:递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出(因为会不断的压栈)。在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。
3.1 递归
- 递归:指在当前方法内调用自己的这种现象。
- 递归的分类:
- 递归分为两种,直接递归和间接递归。
- 直接递归称为方法自身调用自己。
- 间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法。
注意事项:
- 递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出(因为会不断的压栈)。
- 在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。
示例一:需求:利用递归输出3到1
public class Test01 {public static void main(String[] args) {method(3);}public static void method(int n) {System.out.println(n);n--;if (n==1){System.out.println(1);//结束方法return;}method(n);}}
![day07[可变参数_命令行参数_递归_数组] - 图1](/uploads/projects/liuye-6lcqc@vk53cd/985e5623f35ba20325cfb9b0fadc3daf.png)
示例二:求n!
![day07[可变参数_命令行参数_递归_数组] - 图2](/uploads/projects/liuye-6lcqc@vk53cd/4572aeb9f6fb1d15cddddb1d61cb0453.png)
1.定义一个方法f() 表示 阶乘方法2.分析过程f(1): 1f(2): 1*2-> f(1)*2f(3): 1*2*3->f(2)*3f(4): 1*2*3*4->f(3)*4f(5): 1*2*3*4*5->f(4)*5....总结规律: f(n) = f(n-1)*n
public class Test02 {public static void main(String[] args) {int result = f(5);System.out.println(result);}/*f(1): 1f(2): 1*2-> f(1)*2f(3): 1*2*3->f(2)*3f(4): 1*2*3*4->f(3)*4f(5): 1*2*3*4*5->f(4)*5....总结规律: f(n) = f(n-1)*n*/public static int f(int n){if (n==1){return 1;}return f(n-1)*n;}}
![day07[可变参数_命令行参数_递归_数组] - 图3](/uploads/projects/liuye-6lcqc@vk53cd/342d0f3cd9c7548f72ccd3b8ffd9fe94.png)
示例三:计算斐波那契数列(Fibonacci)的第n个值
不死神兔故事得从西元1202年说起,话说有一位意大利青年,名叫斐波那契。在他的一部著作中提出了一个有趣的问题:假设一对刚出生的小兔一个月后就能长成大兔,再过一个月就能生下一对小兔,并且此后每个月都生一对小兔,一年内没有发生死亡问:一对刚出生的兔子,一年内繁殖成多少对兔子?144
规律:一个数等于前两个数之和,比如: 1 1 2 3 5 8 13 21 34 55….
![day07[可变参数_命令行参数_递归_数组] - 图4](/uploads/projects/liuye-6lcqc@vk53cd/68b51c7886c1416ef2879e76974d0510.png)
定义一个方法f 代表递归方法,传递的参数代表月份f(1) : 1f(2) : 1f(3) : 2 f(1)+f(2)f(4) : 3 f(2)+f(3)f(5) : 5 f(3)+f(4)总结:问第n个月,有多少对兔子f(n-2)+f(n-1)
![day07[可变参数_命令行参数_递归_数组] - 图5](/uploads/projects/liuye-6lcqc@vk53cd/cfa0a56ae5240f568708efaab32c8e3d.png)
public class Test03 {public static void main(String[] args) {int result = f(12);System.out.println(result);}public static int f(int n){if (n==1 || n==2){return 1;}return f(n-2)+f(n-1);}}
第三章 对象数组
需求:定义一个长度为3的数组,存储3个Person对象 遍历数组,将Person对象的属性值获取出来
public class Person {String name;int age;}
public class Test01 {public static void main(String[] args) {/*1.定义数组,长度为3Person p = new Person()->Person类型Person[] arr = new Person[3]"abc"->String类型String[] arr = new String[3]1->int类型int[] arr = new int[3]2.5->double类型double[] arr = new double[3]*//*创建一个专门存储Person对象的数组,由于数组中的Person对象数据类型为Person类型所以,我们定义数组时就写Person[]*/Person[] arr = new Person[3];//创建3个Person对象Person p1 = new Person();p1.name = "柳岩";p1.age = 36;Person p2 = new Person();p2.name = "金莲";p2.age = 26;Person p3 = new Person();p3.name = "杨幂";p3.age = 32;//将三个对象存储到数组中arr[0] = p1;arr[1] = p2;arr[2] = p3;//遍历/*第一次循环: i = 0 arr[i]->arr[0]->p1p1.name = "柳岩"p1.age = 36第二次循环: i = 1 arr[i]->arr[1]->p2第三次循环: i = 2 arr[i]->arr[2]->p3*/for (int i = 0; i < arr.length; i++) {Person p = arr[i];System.out.println(p.name+"..."+p.age);}}}
![day07[可变参数_命令行参数_递归_数组] - 图6](/uploads/projects/liuye-6lcqc@vk53cd/4389722d547e8b1c1cbe45e704759f5a.png)
数组是用来存储一组数据的容器,一组基本数据类型的数据可以用数组装,那么一组对象也可以使用数组来装。
即数组的元素可以是基本数据类型,也可以是引用数据类型。当元素是引用数据类型时,我们称为对象数组。
注意:对象数组,首先要创建数组对象本身,即确定数组的长度,然后再创建每一个元素对象,如果不创建,数组的元素的默认值就是null,所以很容易出现空指针异常NullPointerException。
练习1
(1)定义学生类Student
声明姓名和成绩实例变量
(2)测试类ObjectArrayTest的main中创建一个可以装3个学生对象的数组,并且按照学生成绩排序,显示学生信息
public class Student {String name;int score;}
public class Test02_Student {public static void main(String[] args) {//1.创建长度为3的数组Student[] students = new Student[3];//2.创建3个Student对象Student s1 = new Student();s1.name = "柳岩";s1.score = 36;Student s2 = new Student();s2.name = "金莲";s2.score = 26;Student s3 = new Student();s3.name = "涛哥";s3.score = 100;//3.将三个对象,存储到数组中students[0] = s1;students[1] = s2;students[2] = s3;//4.根据成绩排序for (int j = 0;j<students.length-1;j++){for (int i = 0; i < students.length-1-j; i++) {if (students[i].score>students[i+1].score){Student temp = students[i];students[i] = students[i+1];students[i+1] = temp;}}}//5.遍历for (int i = 0; i < students.length; i++) {System.out.println(students[i].name+"..."+students[i].score);}}}
第四章.二分查找
1.前提:数组元素是有序2.怎么查:一次干掉一半这种方式去查询
![day07[可变参数_命令行参数_递归_数组] - 图7](/uploads/projects/liuye-6lcqc@vk53cd/ea8c27d741308c72dc8b3651eaf0bba5.png)
public class Test01 {public static void main(String[] args) {//定义数组int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};//定义min 和max 分别代表数组的最小索引和最大索引int min = 0;int max = arr.length - 1;//定义mid,代表中间索引int mid = 0;//明确要查找的数据int key = 0;while(min<=max){//计算出中间索引mid = (min+max)/2;if (key>arr[mid]){min = mid+1;}else if (key<arr[mid]){max = mid-1;}else{System.out.println(mid);return;//结束方法}}System.out.println(-1);}}
第五章.数组翻转
1.对称索引位置上的元素互换位置
![day07[可变参数_命令行参数_递归_数组] - 图8](/uploads/projects/liuye-6lcqc@vk53cd/c75b451b74ecacb0b303abfa830226b1.png)
public class Test01 {public static void main(String[] args) {int[] arr = {1,2,3,4,5,6,7,8};for (int min = 0,max = arr.length-1;min<max;min++,max--){int temp = arr[min];arr[min] = arr[max];arr[max] = temp;}for (int i = 0; i < arr.length; i++) {System.out.print(arr[i]+" ");}}}
第六章.命令行参数(了解)
通过命令行给main方法的形参传递的实参称为命令行参数
![day07[可变参数_命令行参数_递归_数组] - 图9](/uploads/projects/liuye-6lcqc@vk53cd/67995a89b8d693d3b562186090907354.png)
public class TestCommandParam{//形参:String[] argspublic static void main(String[] args){for(int i=0; i<args.length; i++){System.out.println("第" + (i+1) + "个参数的值是:" + args[i]);}}}
运行命令:
java TestCommandParam
java TestCommandParam 1 2 3
java TestCommandParam hello atguigu
第七章.API文档的使用
1.API概述:定义好的类以及接口以及类和接口中的方法2.API文档:是我们程序员的"字典"
1.查找想要使用的API
![day07[可变参数_命令行参数_递归_数组] - 图10](/uploads/projects/liuye-6lcqc@vk53cd/602c3b2e32adfca9cca368c6589ac97e.png)
2.看对应API的成员
![day07[可变参数_命令行参数_递归_数组] - 图11](/uploads/projects/liuye-6lcqc@vk53cd/4708f0af679512935bc7ea9338c724f3.png)
![day07[可变参数_命令行参数_递归_数组] - 图12](/uploads/projects/liuye-6lcqc@vk53cd/5de176a678721fef5d85f1f102b52f59.png)
第八章.封装
1.封装的介绍和基本使用
1.面向对象的三个特征: 封装 继承 多态2.概述:a.为什么需要封装?封装的作用和含义?我要用洗衣机,只需要按一下开关和洗涤模式就可以了。有必要了解洗衣机内部的结构吗?有必要碰电动机吗?b.隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。将细节隐藏起来,对外提供一个暴露的接口,供我们使用者使用,我们只需要调用这个接口,接口中的细节(代码)就执行起来了3.考虑的问题:不是说private(私有的权限修饰符)就代表了所有的封装将代码放到一个代码块中也可以称之为封装4.关键字(在封装思想中比较有代表性的)a.private-> 私有权限b.修饰一个成员变量: private 数据类型 变量名修饰一个成员方法: private 返回值类型 方法名(参数){}c.私有的成员,只能当前类使用,别的类中不能直接使用5.问题:a.当一个成员被private修饰,外界彻底使用不了了,我们使用private将细节隐藏起来,我们还需要将接口暴露出来供别人使用b.被private修饰的成员变量,需要提供对应的getxxx/setxxx方法来为private修饰的成员变量赋值.取值c.getxxx()获取属性值setxxx()为属性赋值
public class Person {private String name;//隐藏细节->封装思想private int age;//对外提供可使用的接口public void setAge(int nianLing){if (nianLing<0){System.out.println("你疯了,你没了");}else{age = nianLing;}}public int getAge(){return age;}public void setName(String xingMing){name = xingMing;}public String getName(){return name;}}
public class Test {public static void main(String[] args) {Person person = new Person();//person.name = "狗剩";person.setName("狗剩");//person.age = 18;person.setAge(18);System.out.println(person.getName()+"..."+person.getAge());}}
