day08.面向对象
java
课前回顾:
1.封装:将细节隐藏起来(不让外界直接使用),对外提供公共的接口(让外界通过这个接口间接使用封装起来的细节)
2.代表性关键字:private
a.概述:私有权限
b.作用范围:只能在当前类中使用
c.使用:修饰成员变量,方法
3.公共的接口:
getxxx:获取属性值
setxxx:为属性赋值
4.this关键字:
a.概述:代表的是当前对象,哪个对象调用的this所在的方法,this就代表哪个对象
b.作用:区分重名的成员变量和局部变量 -> this后面一定是成员的
c.注意:当成员变量和局部变量重名时,访问遵循"就近原则"
5.无参构造:
a.格式:
public 类名(){}
b.作用:new对象使用
c.注意:每个类都有一个无参构造,不写默认也有
6.有参构造:
a.格式:
public 类名(形参){
为属性赋值
}
b.作用:
new对象,为属性赋值
c.注意:如果手写了有参构造,jvm将不再提供无参构造,所以我们需要都写上
7.javabean
a.概述:书写类的一种规范
b.包含:
public的类,非抽象的类
属性私有
get/set方法
无参构造/有参构造
c.作用:
封装数据
8.static关键字:
a.概述:静态关键字
b.使用:修饰成员变量,方法
c.调用:类名直接调用
d.特点:
静态成员属于类成员,会随着类的加载而加载
静态成员优先于对象存在
凡是根据static所在的类创建出来的对象,都可以共享这个静态成员
e.成员访问特点:
不管在不在同一个类中,访问静态成员,能直接调用就直接调用,不能直接调用就类名调用
不管在不在用一个类中,访问非静态成员,能直接调用就直接调用,不能直接调用就对象调用
f.使用场景:
抽取工具类
g.工具类:
构造私有化,成员都是静态的
今日重点:
1.会使用可变参数
2.会手撕冒泡排序,二分查找
3.会往数组中存对象,会遍历
第一章.可变参数
java
1.需求:定义一个方法,实现若干个整数相加
2.分析需求:
参数:类型确定了,但是个数不确定
1 介绍和基本使用
java
1.格式:
数据类型...变量名
2.本质:可变参数本质上是数组
3.注意:
参数位置只能有一个可变参数,而且要在参数列表最后

java
public class Demo01Var {
public static void main(String[] args) {
method(1,2,3,2,3,4,53,4,5);
method02(1,2,3,4,5);
}
public static void method(int...arr){
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum+=arr[i];
}
System.out.println("sum = " + sum);
}
public static void method02(int a,int...arr){
}
}
2 可变参数
在JDK1.5之后,如果我们定义一个方法时,此时某个形参的类型可以确定,但是形参的个数不确定,那么我们可以使用可变参数。
格式:
【修饰符】 返回值类型 方法名(【非可变参数部分的形参列表,】参数类型... 形参名){ }
要求:
(1)一个方法最多只能有一个可变参数
(2)如果一个方法包含可变参数,那么可变参数必须是形参列表的最后一个
(3)其实这个书写“≈”
【修饰符】 返回值类型 方法名(【非可变参数部分的形参列表,】参数类型[] 形参名){ }
只是后面这种定义,在调用时必须传递数组,而前者更灵活,既可以传递数组,又可以直接传递数组的元素,这样更灵活了。
示例一: 求 n 个整数的和
java
自己练习
示例二:字符串拼接
需求一:返回 n 个字符串拼接结果,如果没有传入字符串,那么返回空字符串""
java
public class Demo02Var {
public static void main(String[] args) {
String result = concat("唐老鸭", "光头强", "灰太狼", "哆啦A梦", "迪迦");
System.out.println("result = " + result);
}
public static String concat(String...arr){
String str = "";
for (int i = 0; i < arr.length; i++) {
str+=arr[i];
}
return str;
}
}
需求二:n 个字符串进行拼接,每一个字符串之间使用某字符进行分隔,如果没有传入字符串,那么返回空字符串""
java
concat("-","柳岩","金莲","王婆","三上","松下") -> 柳岩-金莲-王婆-三上-松下
java
public class Demo03Var {
public static void main(String[] args) {
String result = concat("-", "唐老鸭", "光头强", "灰太狼", "哆啦A梦", "迪迦");
System.out.println(result);
}
private static String concat(String s, String... arr) {
String str = "";
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
str += arr[i];
} else {
str += arr[i] + s;
}
}
return str;
}
}
第二章.递归
从前有座山,山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事,讲的啥呢?
从前有座山,山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事,讲的啥呢?
从前有座山,山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事,讲的啥呢?...
java
1.概述:方法内部自己调用自己
2.分类:
a.直接递归: 方法内部自己调用自己
b.间接递归:
方法之间互相调用
3.注意:
a.递归必须要有出口,否则会出现"栈内存溢出"
b.即使有出口,也不要递归太多次,否则也会出现"栈内存溢出"
java
public class Demo01DiGui {
public static void main(String[] args) {
method();
}
public static void method() {
method();//没有出口,就会出现栈内存溢出现象
}
}
3.1 递归
- 递归:指在当前方法内调用自己的这种现象。
- 递归的分类:
- 递归分为两种,直接递归和间接递归。
- 直接递归称为方法自身调用自己。
- 间接递归可以 A 方法调用 B 方法,B 方法调用 C 方法,C 方法调用 A 方法。
- 注意事项:
- 递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出(因为会不断的压栈)。
- 在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。
示例一:需求:利用递归输出 3 到 1
java
public class Demo02DiGui {
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!
java
需求:求3的阶乘
3*2*1
分析:3的阶乘相当于
3*2的阶乘
假设定义一个方法method(3)代表的是阶乘方法
3的阶乘就相当于 -> 3*method(2)
规律: n的阶乘 -> n*method(n-1)
java
public class Demo03DiGui {
public static void main(String[] args) {
int result = method(3);
System.out.println("result = " + result);
}
private static int method(int n) {
if (n==1){
return 1;
}
return n*method(n-1);
}
}

示例三:计算斐波那契数列(Fibonacci)的第 n 个值
java
不死神兔
故事得从西元1202年说起,话说有一位意大利青年,名叫斐波那契。
在他的一部著作中提出了一个有趣的问题:假设一对刚出生的小兔一个月后就能长成大兔,再过一个月就能生下一对小兔,并且此后每个月都生一对小兔,一年内没有发生死亡
问:一对刚出生的兔子,一年内繁殖成多少对兔子?
规律:一个数等于前两个数之和,比如: 1 1 2 3 5 8 13 21 34 55....

java
1.假设定义一个方法,代表生兔子,参数为月份 method(n)
method(1) 1
method(2) 1
method(3) 2 -> method(1)+method(2)
method(4) 3 -> method(2)+method(3)
method(5) 5 -> method(3)+method(4)
2.结论:
n个月 -> method(n-1)+method(n-2)
java
public class Demo04DiGui {
public static void main(String[] args) {
int result = method(12);
System.out.println("result = " + result);
}
public static int method(int n){
if (n==1||n==2){
return 1;
}
return method(n-1)+method(n-2);
}
}
第三章.数组操作
1.数组翻转
java
1.概述:数组中对称索引位置上的元素互换

java
public class Demo01Rerverse {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9,10};
for (int min = 0,max = arr.length-1;min<max;min++,max--){
int temp = arr[min];
arr[min] = arr[max];
arr[max] = temp;
}
System.out.println(Arrays.toString(arr));
}
}
2.冒泡排序
数组的排序,是将数组中的元素按照大小进行排序,默认都是以升序的形式进行排序,数组排序的方法很多,我们讲解的是数组的冒泡排序。
排序,都要进行数组 元素大小的比较,再进行位置的交换。冒泡排序法是采用数组中相邻元素进行比较换位。
2.1 冒泡排序图解

2.2 代码实现
java
public class Demo02MaoPao {
public static void main(String[] args) {
int[] arr = {5,4,3,2,1};
/*
当i到4的时候,i<5?true ->进循环 -> if(arr[4]>arr[4+1])
此数组没有5索引,所以越界了
解决:让arr.length减去1
第一圈:比较了4次
*/
/*for (int i = 0; i < arr.length-1-0; i++) {
if (arr[i]>arr[i+1]){
int temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
System.out.println(Arrays.toString(arr));*/
/*
第二圈:比较了3次
*/
/* for (int i = 0; i < arr.length-1-1; i++) {
if (arr[i]>arr[i+1]){
int temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
System.out.println(Arrays.toString(arr));*/
/*
第三圈:比较了2次
*/
/*for (int i = 0; i < arr.length-1-2; i++) {
if (arr[i]>arr[i+1]){
int temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
System.out.println(Arrays.toString(arr));*/
/*
第四圈:比较了1次
*/
/*for (int i = 0; i < arr.length-1-3; i++) {
if (arr[i]>arr[i+1]){
int temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
System.out.println(Arrays.toString(arr));*/
/*
外层代表几圈
内层代表比较次数
*/
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;
}
}
}
System.out.println(Arrays.toString(arr));
}
}
3.二分查找
java
1.问题:
之前我们从数组中查询元素,我们需要遍历数组,然后元素和我们想要找的数据挨个比较,这样查询起来就会很慢
[11,22,33,44,55,66,77,88]
2.二分查找:
a.作用:提高查询效率
b.前提:数组必须是有序的 -> 一般都是升序
3.中心思想:
先找一个数组的中间索引,然后用我们的数据和中间索引对应的元素比较,如果查不到,下次查找干掉数组的一半,跟另外一半的中间索引比较....

java
public class Demo03BinarySearch {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9,10};
int index = binarySearch(arr);
System.out.println("index = " + index);
}
public static int binarySearch(int[] arr) {
//定义min和max以及mid
int min = 0;
int max = arr.length-1;
int mid = 0;
int key = 10;
while(min<=max){
mid = (min+max)/2;
if (key>arr[mid]){
min = mid+1;
} else if (key<arr[mid]){
max = mid-1;
}else{
return mid;
}
}
return -1;
}
}
4.对象数组
java
需求:定义一个数组,存储3个Person对象,遍历数组,将3个对象中的属性值获取出来
java
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
java
public class Demo04ObjectArray {
public static void main(String[] args) {
/*
1.存储int型数据 -> int[]
2.存储double型数据 -> double[]
3.存储String字符串数据 -> String[]
4.存储Person对象数据 -> Person[]
Person p = new Person()
等号左边的Person是数据类型
p:对象名
new Person():创建对象,是p的具体值
*/
Person[] arr = new Person[3];
Person p1 = new Person("张三", 10);
Person p2 = new Person("李四", 11);
Person p3 = new Person("王五", 12);
//将三个Person对象存储到数组中
arr[0] = p1;
arr[1] = p2;
arr[2] = p3;
//遍历
for (int i = 0; i < arr.length; i++) {
/*
i = 0,arr[0]就是p1 -> 将p1的地址值给了p,此时p就是p1
i = 1,arr[1]就是p2 -> 将p2的地址值给了p,此时p就是p2
i = 2,arr[2]就是p3 -> 将p3的地址值给了p,此时p就是p3
*/
//Person p = arr[i];
//System.out.println(p.getName()+"..."+p.getAge());
System.out.println(arr[i].getName()+"..."+arr[i].getAge());
}
}
}

练习 1
(1)定义学生类 Student
声明姓名和成绩成员变量
(2)测试类 ObjectArrayTest 的 main 中创建一个可以装 3 个学生对象的数组,并且按照学生成绩排序,显示学生信息
java
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;
}
}
java
public class Demo05ObjectArray {
public static void main(String[] args) {
//创建Student数组
Student[] arr = new Student[3];
Student s1 = new Student("张三", 100);
Student s2 = new Student("李四", 60);
Student s3 = new Student("王五", 80);
arr[0] = s1;
arr[1] = s2;
arr[2] = s3;
for (int j = 0; j < arr.length - 1; j++) {
for (int i = 0; i < arr.length - 1 - j; i++) {
if (arr[i].getScore() > arr[i + 1].getScore()) {
Student temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
}
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i].getName() + "..." + arr[i].getScore());
}
}
}
第四章.方法参数
1.基本数据类型做方法参数传递
java
基本类型做方法参数传递,传递的是变量的值,不是变量本身
java
public class Test01 {
public static void main(String[] args) {
int a = 10;
int b = 20;
/*
参数为基本类型,传递的是变量代表的值
不是变量本身
*/
method(a,b);
System.out.println(a);//10
System.out.println(b);//20
}
public static void method(int a,int b){
a+=10;
b+=20;
System.out.println(a);//20
System.out.println(b);//40
}
}
2.引用数据类型做方法参数传递
java
引用类型做方法参数传递,传递的地址值
java
public class Test02 {
public static void main(String[] args) {
int[] arr = {10,20};
method(arr);
System.out.println(arr[0]);//20
System.out.println(arr[1]);//40
}
public static void method(int[] arr){
arr[0]+=10;
arr[1]+=20;
System.out.println(arr[0]);//20
System.out.println(arr[1]);//40
}
}

第五章.命令行参数(了解)
通过命令行给 main 方法的形参传递的实参称为命令行参数
java
public class TestCommandParam{
//形参:String[] args
public static void main(String[] args){
for(int i=0; i<args.length; i++){
System.out.println("第" + (i+1) + "个参数的值是:" + args[i]);
}
}
}
运行命令:
command
java TestCommandParam
command
java TestCommandParam 1 2 3
command
java TestCommandParam hello atguigu

第六章.快速生成方法小技巧
1.先调用,再生成
java
先调用,按alt+回车 ->选择创建方法

2.快速将一段代码放到一个方法中
java
1.选中要抽取的代码
2.按ctrl+alt+m