【day09】面向对象编程进阶
【day08】重点回顾
在深入本模块之前,让我们回顾一下【day08】中的关键内容:
-
封装:
- 隐藏对象内部细节,仅通过公共接口与外界交互。
- 使用
private
关键字修饰成员变量和方法,限制直接访问。 - 提供
get
和set
方法,以便外界通过公共接口间接访问私有成员。 - 使用
this
关键字区分同名的成员变量和局部变量。
-
构造方法:
- 无参构造:用于创建对象时不传递任何参数。
- 有参构造:用于创建对象时初始化对象的属性。
-
标准JavaBean:
- 公共的、具体的类。
- 私有属性。
- 无参和有参构造方法。
get
和set
方法。
模块九重点
本模块我们将探索面向对象编程的进阶概念,包括:
- 静态成员的定义和调用。
- 可变参数的使用。
- 二分查找算法的实现。
- 冒泡排序算法的实现。
- Debug调试技巧。
第一章:static关键字
1. static的介绍及基本使用
static
关键字用于声明类级别的成员,这些成员不属于任何对象,而是属于类本身。
示例代码
public class Student {String name;int age;static String classRoom;
}public class Test01 {public static void main(String[] args) {Student.classRoom = "222";Student s1 = new Student();s1.name = "郭靖";s1.age = 28;System.out.println(s1.name+","+s1.age+","+Student.classRoom);Student s2 = new Student();s2.name = "黄蓉";s2.age = 26;System.out.println(s2.name+","+s2.age+","+Student.classRoom);}
}
2. static修饰成员的访问特点
- 静态成员可以通过类名直接访问,无需创建对象。
- 非静态成员可以通过对象访问,也可以在类内部直接访问。
注意事项
- 静态成员会随着类的加载而加载,因此使用时应考虑内存占用。
- 工具类通常包含静态成员,因为它们提供通用功能。
第二章:可变参数
可变参数允许方法接受任意数量的参数。
示例代码
public class Demo01Var {public static void main(String[] args) {sum(1,2,3,4,5);}public static void sum(int...arr){int sum = 0;for (int i = 0; i < arr.length; i++) {sum+=arr[i];}System.out.println(sum);}
}
字符串拼接
需求一:返回n个字符串拼接结果,如果没有传入字符串,那么返回空字符串""
public class Demo02Var {public static void main(String[] args) {String result = concat("张无忌", "张翠山", "张三丰", "张三");System.out.println("result = " + result);}public static String concat(String...s){String str = "";for (int i = 0; i < s.length; i++) {str+=s[i];}return str;}
}
需求二:n个字符串进行拼接,每一个字符串之间使用某字符进行分隔,如果没有传入字符串,那么返回空字符串"",比如:concat("-","张三丰","张翠山","张无忌")
-> 返回 -> 张三丰-张翠山-张无忌
public class Demo03Var {public static void main(String[] args) {String result = concat("-", "张三丰", "张翠山", "张无忌");System.out.println("result = " + result);}public static String concat(String regex, String... s) {String str = "";for (int i = 0; i < s.length; i++) {if (i == s.length - 1) {str += s[i];} else {str += s[i] + regex;}}return str;}
}
第三章:递归
递归是一种方法自我调用的编程技巧,常用于解决分治问题。
示例代码
public class Demo02Recursion {public static void main(String[] args) {method(3);}public static void method(int n){if (n==1){System.out.println(n);return;}System.out.println(n);n--;method(n);}
}
注意:
- 递归必须要有出口,否则会出现"栈内存溢出"
- 递归即使有出口,递归次数不不要太多
public class Demo01Recursion {public static void main(String[] args) {method();}public static void method(){method();}
}
示例一:需求:利用递归输出3到1
public class Demo02Recursion {public static void main(String[] args) {method(3);}public static void method(int n){if (n==1){System.out.println(n);//结束方法return;}System.out.println(n);n--;method(n);}
}
示例二:求n!(n的阶乘)
public class Demo03Recursion {public static void main(String[] args) {int method = method(3);System.out.println("method = " + method);}public static int method(int n){if (n==1){return 1;}return n*method(n-1);}
}
示例三:计算斐波那契数列(Fibonacci)的第n个值
不死神兔
故事得从西元1202年说起,话说有一位意大利青年,名叫斐波那契。在他的一部著作中提出了一个有趣的问题:假设一对刚出生的小兔一个月后就能长成大兔,再过一个月就能生下一对小兔,并且此后每个月都生一对小兔,一年内没有发生死亡
问:一对刚出生的兔子,一年内繁殖成多少对兔子?
规律:一个数等于前两个数之和,比如: 1 1 2 3 5 8 13 21 34 55…
public class Demo04Recursion {public static void main(String[] args) {int method = method(12);System.out.println("method = " + method);}public static int method(int n){if (n==1 || n==2){return 1;}return method(n-1)+method(n-2);}
}
第四章:数组常见算法
概述: 数组对称索引位置上的元素互换
1. 数组翻转
示例代码
public class Demo01Reverse {public static void main(String[] args) {int[] arr = {1,2,3,4,5,6,7};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]+" ");}}
}
2. 冒泡排序
数组的排序,是将数组中的元素按照大小进行排序,默认都是以升序的形式进行排序,数组排序的方法很多,我们讲解的是数组的冒泡排序。
排序,都要进行数组元素大小的比较,再进行位置的交换。冒泡排序法是采用数组中相邻元素进行比较换位。
示例代码
public class Demo02Bubble {public static void main(String[] args) {int[] arr = {5,4,3,2,1};for (int j = 0; j < arr.length-1; j++) {for (int i = 0; i < arr.length-1-j; i++) {if (arr[i]>arr[i+1]){int temp = arr[i];arr[i] = arr[i+1];arr[i+1] = temp;}}}for (int i = 0; i < arr.length; i++) {System.out.print(arr[i]+" ");}}
}
3. 二分查找
- 前提:数组中的数据必须是有序的
- 查询思想:
- 老式查询: 遍历数组,一个一个比较 -> 查询效率慢
- 二分查找: 每次找中间索引对应的元素进行比较查询(每一次查询少一半数据)
示例代码
public class Demo03Binary {public static void main(String[] args) {int[] arr = {1,2,3,4,5,6,7,8,9};int index = binary(arr, 60);System.out.println(index);}public static int binary(int[] arr, int data){int min = 0;int max = arr.length-1;int mid = 0;while(min<=max){mid = (min+max)/2;if (data>arr[mid]){min = mid+1;}else if(data<arr[mid]){max = mid-1;}else{return mid;}}return -1;}
}
第五章:对象数组
对象数组是存储对象引用的数组。
示例代码
public class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}
}public class Demo01ObjectArray {public static void main(String[] args) {Person[] arr = new Person[3];arr[0] = new Person("金莲",26);arr[1] = new Person("涛哥",18);arr[2] = new Person("张三",20);for (int i = 0; i < arr.length; i++) {System.out.println(arr[i].getName()+"..."+arr[i].getAge());}}
}
练习1
(1)定义学生类Student:声明姓名和成绩成员变量
(2)测试类ObjectArrayTest的main中创建一个可以装3个学生对象的数组,并且按照学生成绩排序,显示学生信息
public class Student {private String name;private int score;public Student() {}public Student(String name, int score) {this.name = name;this.score = score;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getScore() {return score;}public void setScore(int score) {this.score = score;}
}
public class Demo02ObjectArray {public static void main(String[] args) {Student[] students = new Student[3];students[0] = new Student("金莲",26);students[1] = new Student("大郎",50);students[2] = new Student("涛哥",18);for (int j = 0; j < students.length-1; j++) {for (int i = 0; i < students.length-1-j; i++) {if (students[i].getScore()>students[i+1].getScore()){Student temp = students[i];students[i] = students[i+1];students[i+1] = temp;}}}for (int i = 0; i < students.length; i++) {System.out.println(students[i].getName()+"..."+students[i].getScore());}}
}
第六章:方法参数
1. 基本数据类型做方法参数传递
基本数据类型作为参数传递时,传递的是值的拷贝。
示例代码
public class Demo01Param {public static void main(String[] args) {int a = 10;int b = 20;method(a,b);System.out.println(a);//10System.out.println(b);//20}public static void method(int a,int b){a+=10;b+=20;System.out.println(a);//20System.out.println(b);//40}
}
2. 引用数据类型做方法参数传递
引用数据类型作为参数传递时,传递的是引用的地址值。
示例代码
public class Demo02Param {public static void main(String[] args) {int[] arr = {10,20};method(arr);System.out.println(arr[0]);//20System.out.println(arr[1]);//40}public static void method(int[] arr){arr[0]+=10;arr[1]+=20;System.out.println(arr[0]);//20System.out.println(arr[1]);//40}
}
第七章:命令行参数(了解)
Java程序可以通过命令行参数传递给main
方法。
示例代码
public class TestCommandParam {public 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 potter
第八章:其他操作
1. 快速生成方法
IDE提供了快捷键来快速生成方法和抽取代码到方法中。
-
初学者要求先定义,再调用;不是初学者,就可以先调用,再定义方法。快捷键:
alt+回车
-
快速将一段代码抽取到一个方法中:
- 选中要抽取的方法
- 按
ctrl+alt+m
2. debug调试
Debug是调试代码的一种手段,可以帮助我们观察变量的变化和查找错误。