大数据—面向对象
递归方法的使用
*
* 1. 递归方法:一个方法体内调用它自身。
* 2. 方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。
* 3. 递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
* 死循环是我们开发中要避免出现的。进而递归方法也必须满足执行的有限性。否则的话,会报StackOverflowError
代码演示:
1 public class RecursionTest { 2 public static void main(String[] args) { 3 RecursionTest test = new RecursionTest(); 4 int sum = test.sum1(100); 5 System.out.println("总和为:" + sum); 6 7 int result = test.f(10); 8 System.out.println("结果为:" + result); 9 } 10 11 //计算1-num所有自然数的和 12 public int sum(int num){ 13 int sum = 0; 14 for (int i = 1; i <= num; i++) { 15 sum += i; 16 } 17 return sum; 18 } 19 20 //递归实现:1-100所有自然数的和 21 public int sum1(int num){ 22 if(num == 1){ 23 return 1; 24 }else{ 25 return sum1(num - 1) + num; 26 } 27 } 28 29 //递归实现1:计算n! 30 public int multiply(int num){ 31 if(num == 1){ 32 return 1; 33 }else{ 34 return multiply(num - 1) * num; 35 } 36 } 37 38 //递归实现2:已知有一个数列:f(0) = 1,f(1) = 4,f(n+2)=2*f(n+1) + f(n), 39 // 其中n是大于0的整数,求f(10)的值。 40 public int f(int num){ 41 if(num == 0){ 42 return 1; 43 }else if(num == 1){ 44 return 4; 45 }else{ 46 //错误的 47 // return f(num + 2) - 2 * f(num + 1); 48 //正确的 49 return 2 * f(num - 1) + f(num - 2); 50 } 51 } 52 53 //递归实现3:已知一个数列:f(20) = 1,f(21) = 4,f(n+2) = 2*f(n+1)+f(n), 54 //其中n是大于0的整数,求f(10)的值。 55 public int func(int num){ 56 if(num == 20){ 57 return 1; 58 }else if(num == 21){ 59 return 4; 60 }else{ 61 return func(num + 2) - 2 * func(num + 1); 62 } 63 } 64 65 //递归实现4:斐波那契数列: 1 1 2 3 5 8 13 21 34 55 66 //f(1) = 1;f(2) = 1;f(n + 2) = f(n + 1) + f(n) 67 68 //递归实现5:汉诺塔 69 70 //递归实现6:IO流时File类的使用:遍历指定文件目录下的所有文件名 71 public void printFileName(File file){ 72 if(file.isDirectory()){ 73 File[] files = file.listFiles(); 74 for(int i = 0;i < files.length;i++){ 75 printFileName(files[i]); 76 } 77 78 }else{ 79 System.out.println(file.getAbsolutePath()); 80 } 81 } 82 83 //递归实现7:快排 84 85 }
1. 问题的引入
* 我们在创建一个类的对象之后,可以通过“对象.属性”的方式给属性赋值。默认情况下,赋的值需要满足指定的
* 数据类型和变量的存储值的范围。但是,在实际情况中,此属性的赋值,需要满足实际情况的一些限制条件。(比如:
* legs必须是正数、且是偶数)。又由于我们不能直接在属性的声明位置加上此限制语句,则必须通过方法的
* 方法的方式给属性赋值,在方法内设置限制条件。则我们设计一个SetXxx()的方法。将此方法暴露出去(设置为public)
* 同时,不允许在类的外部再直接修改此属性。则将此属性隐藏起来(设置为private)即可。
*
* 1.1 为了出了类之后,能调用此属性的值,我们还需要提供一个getXxx()的方法。此方法声明为public的即可。
*
* 2. 小结:设计类时,可以考虑把类中的属性私有化(private),同时提供公共(public)的get和set方法,进行获取和设置此属性的操作。
代码演示:
1 public class AnimalTest { 2 public static void main(String[] args) { 3 Animal ani = new Animal(); 4 5 ani.name = "佩奇"; 6 // ani.age = 1; 7 // ani.legs = -4; 8 ani.setLegs(14); 9 // ani.legs = -14;//非法访问 10 11 ani.info(); 12 13 // System.out.println(ani.legs); 14 System.out.println(ani.getLegs()); 15 } 16 } 17 18 class Animal { 19 String name; 20 private int age; 21 private int legs;//腿的个数 22 23 //获取属性值的方法 24 public int getLegs(){ 25 return legs; 26 } 27 //设置属性值的方法 28 //设计一个方法,通过方法给legs属性赋值 29 public void setLegs(int l){ 30 if(l >= 0 && l % 2 == 0 && l <= 30){ 31 legs = l; 32 }else{ 33 System.out.println("传入的数据非法!"); 34 } 35 } 36 //提供age属性的get和set方法 37 public int getAge(){ 38 return age; 39 } 40 41 public void setAge(int a){ 42 age = a; 43 } 44 45 46 public void info() { 47 System.out.println("name = " + name + ", age = " + age + ",legs = " + legs); 48 } 49 }
1 public void sort(Student[] stus,String sortMethod){ 2 if("ascend".equals(sortMethod)){ 3 4 for(int i = 0;i < stus.length - 1;i++){ 5 for(int j = 0;j < stus.length - 1 - i;j++){ 6 if(stus[j].score > stus[j + 1].score){ 7 swap(stus,j,j + 1); 8 } 9 } 10 } 11 }else if("descend".equals(sortMethod)){ 12 for(int i = 0;i < stus.length - 1;i++){ 13 for(int j = 0;j < stus.length - 1 - i;j++){ 14 if(stus[j].score < stus[j + 1].score){ 15 swap(stus,j,j + 1); 16 } 17 } 18 } 19 }else{ 20 System.out.println("排序方式有误!"); 21 } 22 } 23 24 private void swap(Student[] stus,int i,int j){ 25 Student temp = stus[i]; 26 stus[i] = stus[j]; 27 stus[j] = temp; 28 }
3. 封装与隐藏,体现了设计java类及java类的内部结构时,其可被访问的权限的大小。
* java规定的4种访问权限修饰符:(从小到大的顺序)
* private < 缺省 < protected < public
4. 我们可以使用4种权限修饰符修饰类及类的内部结构
* > 可以使用4种权限修饰符修饰:属性、方法、构造器、内部类
* > 可以使用缺省或public修饰符修饰:类。 (不能使用private\protected修饰类)

类的成员之三:构造器的使用
*
* 1. Constructor = 构造器 = 构造方法 = 构造函数
* construct : 构建、构造
*
* 2.构造器的作用:
* ① 创建类的对象 (或 类的实例化)
* ② 可以初始化对象的信息(比如:属性的初始化)
*
* 3. 说明:
* ① 任何一个类,如果没有显式提供构造器的话,系统都会默认提供一个空参的构造器
* ② 自定义构造器的格式: 权限修饰符 类名(形参列表){ }
* ③ 类中可以声明多个构造器,彼此构成重载
* ④ 一旦显式的定义了类的构造器,则系统不再提供默认的空参的构造器。
代码演示:
1 public class PersonTest { 2 public static void main(String[] args) { 3 Person p1 = new Person(); 4 p1.name = "吴辉"; 5 p1.age = 25; 6 7 p1.eat(); 8 p1.sleep(6); 9 10 System.out.println("####################"); 11 Person p2 = new Person("石磊"); 12 System.out.println(p2.name);//石磊 13 } 14 } 15 16 class Person{ 17 18 //属性 19 String name; 20 int age; 21 22 //构造器 23 public Person(){ 24 System.out.println("hello,Person()"); 25 } 26 27 public Person(String n){ 28 name = n; 29 } 30 31 public Person(int a){ 32 if(a >= 0 && a <= 130){ 33 age = a; 34 } 35 } 36 37 //方法 38 public void eat(){ 39 System.out.println("人每天需要吃饭"); 40 } 41 public void sleep(int hour){ 42 System.out.println("人每天需要保证" + hour + "小时的睡眠"); 43 } 44 45 46 }
1 /** 2 * 小结:类中属性赋值的位置及执行先后顺序测试 3 * 4 * 1. 类中的属性都可以在哪些位置赋值? 5 * ① 默认初始化 6 * ② 显式初始化 7 * ③ 构造器中初始化 8 * 9 * ④ 在创建了对象之后,使用"对象.方法" 或 "对象.属性"的方式赋值 10 * 11 * 12 * 2. 赋值的先后顺序: 13 * ① - ② - ③ - ④ 14 * 15 * 3. 上述的 ①、②、③过程,在对象实例化过程中,只能执行一次! 16 * 17 * @author shkstart 18 * @create 2020-07-03 14:40 19 */ 20 public class UserTest { 21 public static void main(String[] args) { 22 User u1 = new User(); 23 24 System.out.println(u1.name); 25 26 User u2 = new User(10); 27 System.out.println(u2.age); 28 } 29 } 30 31 class User{ 32 String name = "Tom"; 33 int age = 1; 34 35 public User(){} 36 37 public User(int a){ 38 age = a; 39 } 40 }
2. this调用属性、方法:
* this可以理解为:当前对象 或 当前正在创建的对象
*
* 2.1 在类的方法内或构造器内执行操作时,如果方法的形参或构造器的形参与类的属性名相同,则
* 必须显式的通过"this."的方式,表明调用的当前类的属性。如果省略了"this.",则认为调用的是形参。
* 2.2 在类的方法内或构造器内执行操作时,如果方法的形参或构造器的形参与类的属性名不相同时,
* 则调用类的属性时,前面修饰的"this."可以省略。
*
* 2.3 在类的方法中,我们可以通过"this."的方式调用本类中的其他方法。只是大多数情况下,我们都
* 省略了"this."。
代码演示:
1 class Person{ 2 private String name; 3 private int age; 4 5 public void setName(String name){ 6 this.name = name; 7 } 8 public void setAge(int age){ 9 this.age = age; 10 } 11 public String getName(){ 12 return name; 13 } 14 public int getAge(){ 15 return age; 16 } 17 18 public void eat(){ 19 System.out.println("人:吃饭"); 20 this.sleep(); 21 } 22 public void sleep(){ 23 System.out.println("人:睡觉"); 24 } 25 }
3. this调用构造器:
* ① this调用构造器的格式:this(形参列表)
* ② 在类的构造器中,我们可以显示的使用"this(形参列表)"的方式,调用本类中的其他构造器。
* ③ “this(形参列表)”必须声明在类的构造器的首行!
* ④ 在类的一个构造器中,只能最多声明一个“this(形参列表)”
* ⑤ 如果一个类中声明了n个构造器,则最多有n - 1 个构造器中使用了“this(形参列表)”
代码演示:
1 class Person{ 2 private String name; 3 private int age; 4 5 public Person(){ 6 // this("吴瀚"); 7 System.out.println("我是一个人。我刚出生,需要洗澡!"); 8 } 9 public Person(String name){ 10 this(); 11 this.name = name; 12 } 13 14 public Person(String name,int age){ 15 this(name); 16 this.age = age; 17 // this.eat(); 18 } 19 20 }
1 /** 2 * 满足如下条件的类,可以称为是一个javabean: 3 * >类是公共的 4 * >有一个无参的公共的构造器 5 * >有属性,且有对应的get、set方法 6 * 7 * @author shkstart 8 * @create 2020-07-03 15:12 9 */ 10 public class Student { 11 12 private int number;//学号 13 private int state;//年级 14 private int score;//成绩 15 16 public int getNumber() { 17 return number; 18 } 19 20 public void setNumber(int n) { 21 number = n; 22 } 23 24 public int getState() { 25 return state; 26 } 27 28 public void setState(int s) { 29 state = s; 30 } 31 32 public int getScore() { 33 return score; 34 } 35 36 public void setScore(int s) { 37 score = s; 38 } 39 }
1 //数据 2 class Student{ 3 int number;//学号 4 int state;//年级 5 int score;//成绩 6 7 public void info(){ 8 System.out.println("number : " + number + ", state : " + state + ", score : " + score); 9 } 10 11 }
操作数据的工具类:StudentUtil
1 //操作数据的工具类 2 class StudentUtil{ 3 4 /** 5 * 根据指定的条件,创建相应的学生数组,并给数组元素赋值 6 * @param length 指定学生数组的长度 7 * @param lowState 指定学生对象的年级的下边界 8 * @param highState 指定学生对象的年级的上边界 9 * @param lowScore 指定学生对象的成绩的下边界 10 * @param highScore 指定学生对象的成绩的上边界 11 * @return 返回满足指定条件的数组 12 */ 13 public Student[] getStudentArray(int length,int lowState,int highState,int lowScore,int highScore){ 14 Student[] stus = new Student[length];//虚位以待 15 for (int i = 0; i < stus.length; i++) { 16 stus[i] = new Student(); 17 //给每一个学生的属性赋值 18 //学号 19 stus[i].number = i + 1; 20 //年级:1-6 21 stus[i].state = (int)(Math.random() * (highState - lowState + 1) + lowState); 22 //成绩:0-100 23 stus[i].score = (int)(Math.random() * (highScore - lowScore + 1) + lowScore); 24 } 25 26 return stus; 27 } 28 29 /** 30 * 遍历学生数组,打印出指定年级学生的信息 31 * @param stus 待遍历的数组 32 * @param state 指定的学生年级 33 */ 34 public void printStudentState(Student[] stus,int state){ 35 for (int i = 0; i < stus.length; i++) { 36 if (stus[i].state == state) { 37 stus[i].info(); 38 } 39 } 40 } 41 42 43 /** 44 * 排序Student数组:使用冒泡排序 45 * @param stus 46 * @param sortMethod 47 */ 48 public void sort(Student[] stus,String sortMethod){ 49 if("ascend".equals(sortMethod)){ 50 51 for(int i = 0;i < stus.length - 1;i++){ 52 for(int j = 0;j < stus.length - 1 - i;j++){ 53 if(stus[j].score > stus[j + 1].score){ 54 swap(stus,j,j + 1); 55 } 56 } 57 } 58 }else if("descend".equals(sortMethod)){ 59 for(int i = 0;i < stus.length - 1;i++){ 60 for(int j = 0;j < stus.length - 1 - i;j++){ 61 if(stus[j].score < stus[j + 1].score){ 62 swap(stus,j,j + 1); 63 } 64 } 65 } 66 }else{ 67 System.out.println("排序方式有误!"); 68 } 69 } 70 71 private void swap(Student[] stus,int i,int j){ 72 Student temp = stus[i]; 73 stus[i] = stus[j]; 74 stus[j] = temp; 75 } 76 77 /** 78 * 遍历Student数组 79 * @param stus 80 */ 81 public void print(Student[] stus){ 82 for (int i = 0; i < stus.length; i++) { 83 stus[i].info(); 84 } 85 } 86 }
测试类
1 //测试类 2 public class Exer3 { 3 public static void main(String[] args) { 4 StudentUtil util = new StudentUtil(); 5 // 创建20个学生对象 6 Student[] stus = util.getStudentArray(20, 1, 6, 0, 100); 7 8 //问题一:打印出3年级(state值为3)的学生信息。 9 util.printStudentState(stus,3); 10 //问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息 11 // util.sort(stus,"descend"); 12 13 //遍历操作 14 // util.print(stus); 15 } 16 }


浙公网安备 33010602011771号