本节完成于2024.7.18
类与对象
简单应用:
public class Demo240705 {
public static void main(String[] args) {
Cat kitty = new Cat();
kitty.name = "kitty";
kitty.age = 4;
kitty.color = "white";
}
}
class Cat {
//属性:
String name;
int age;
String color;
}
如果有对象间赋值代码如下:
Person p1;
Person p2 = p1;
则两个对象指向同一个类对象的地址,和别名有点像,具体运作规则和上节数组相同。
属性如果不赋值,系统会给默认值,给予方法同数组的默认值。
上图可以总结如下:
Java创建对象的流程简单分析:
成员方法
方法调用机制分析:
step1:
step2:
以上总结:
1、程序执行到一个方法时,会开辟一个独立的栈空间。
2、方法执行完毕或到return语句时,会返回到调用该方法的地方。
3、main方法栈执行完毕,整个程序退出。
部分使用细节:
5、方法不可以嵌套定义!
方法的调用规则:
成员方法传参机制
parameter:参数
此节讲的主要是,基本数据类型传参时,原来的数据不发生变化,引用类型传参时,原来的数据会随着方法的操作发生变化,因为底层来讲,一个是值传递,一个是地址传递。
值得注意的是,如果如下情况:
则证明,p的指向改变了,并不会使主栈中的对象改变,即如果主方法中打印p.age的话不会报错,仍是原来的值。
递归
递归的部分实现细节:
2、方法的局部变量是独立的,每个递归的方法单独一个栈。
但传参时如果是引用类型,因为本质是传地址,所以会共享。如下第三条。
小老鼠走迷宫:
public class Demo240705 {
public static void main(String[] args) {
//maze: 0--empty 1--not empty
int[][] map = new int[8][7];
for(int i = 0; i < 7; i++){
map[0][i] = 1;
map[7][i] = 1;
map[i][0] = 1;
map[i][6] = 1;
}
map[3][1] = 1;
map[3][2] = 1;
MyTools t = new MyTools();
t.printArr(map);
System.out.println();
boolean is = t.findWay(map,1,1);
t.printArr(map);
}
}
class MyTools{
//老鼠出迷宫
public boolean findWay(int[][] map, int i, int j){
if(map[6][5] == 2){
return true;
}
else{
if(map[i][j] == 0){
map[i][j] = 2;
//使用找路策略
if(findWay(map,i + 1,j)||findWay(map,i,j + 1)||
findWay(map,i - 1, j)||findWay(map,i,j - 1)){
return true;
}
else{
map[i][j] = 3;
return false;
}
}
else{
return false;
}
}
}
//对传入的二维数组进行遍历
public void printArr(int[][] a){
for(int i = 0; i < a.length; i++){
for(int j = 0; j < a[i].length; j++){
System.out.print(a[i][j] + " ");
}
System.out.println();
}
}
}
汉诺塔:(想死)
public void move(int num, char a, char b, char c){ if(num == 1){ System.out.println(a + "->" + c); } else{ //先移动上面所有的盘到b,借助C move(num - 1,a,c,b); //把最下面的盘移动到c System.out.println(a + "->" + c); //把B塔所有盘移动到C,借助A move(num - 1, b, a, c); } }
重载(overload)
Java中要求形参列表不一致。
重载使用细节:
第三点可以解读为:返回类型不可以作为构成重载的一个条件。(因为系统难以判断)
实际编程是会报错:重名错误!
可变参数
1、传进去的实参可以是0到多个数,也可以是数组。
2、当作数组来使用。本质就是数组。
class MyCalculators{
//可以接受0到多个参数!0个也可以!
//可以当作数组来使用
public int varParameter(int... nums){
int sum = 0;
for(int i = 0; i < nums.length; i++){
sum += nums[i];
}
return sum;
}
}
使用细节:
以上情况均可能会出现二义性!
作用域 Scope
属性(全局变量)不赋值时有默认值,规则和数组一致。(前面的知识点)
使用细节(比较好理解,仅贴图复习时带过)
构造器 constructor
作用是完成对新对象的初始化(而非创建一个对象,使用到构造器时对象实际已经存在了)
类似C++中构造函数:(中括号内的修饰符可以不写,使用默认的)
使用实例:
Cat tmp = new Cat("kitty", 3, "white");
class Cat{
//属性
String name;
int age;
String color;
//constructor
Cat(String tname, int tage, String tcolor){
name = tname;
age = tage;
color = tcolor;
}
}
部分使用细节:(与C++相同)
javap Dog.class:or javap Dog
默认构造器如下:
Dog(){}
对象创建的流程分析
在课程的245节,很重要,有时间的时候回去多看几遍这一节:
步骤(文字版):
1、在方法区中加载Person类信息,只会加载一次(创建多个对象时)
2、在堆中分配空间(地址)
3、完成对象初始化:1.默认初始化,2.显式初始化,3.构造器初始化
4、把对象在堆中的地址返回给栈中的p(p是对象名/对象的引用)
this关键字
this的引入:
否则按照就近原则,name永远是局部变量,而非属性(全局变量)。
Cat(String name, int age, String color){
this.name = name;
this.age = age;
this.color = color;
}
this的本质:
相当于一个隐藏的属性。
哈希码查阅是否是同一对象:
dog2.hashcode();
使用细节:
本章作业遇到的问题
System.out.println(c.radius + '\t' + c.findArea());
结果输出的是一个很奇怪的数字,经过几次检查发现问题出在:
+的使用规则:两侧如果有一个字符串,则是连接作用,如无,则为运算作用。
此处为
运算作用,将字符化作int型后参与运算。
应更改为:
System.out.println(c.radius + "\t\t" + c.findArea());
这也是为什么如下代码没有发生错误,导致我愣神不知道如何下手:
System.out.println("Radius" + '\t' + "Area");