1 空指针异常
2 栈、堆和方法区
① 栈:局部变量(方法的参数列表),方法中的变量都是局部变量
② 堆:new的对象(成员变量)
③ 指向对象:
(1)引用类型(以b1为例):调用成员变量时,首先会找到栈中的b1,通过地址找到堆中的Bomb对象的成员变量。
(2)基本类型(以a为例):直接找到栈中的a,修改a的值即可
④ 注意:基本类型装的是数,引用类型装的是地址
3 知识整理
① 引用类型默认值为null
② 引用类型需要new来创建
③ 引用类型数组必须给每个元素都赋值,不然使用时会报空指针异常
④ 当运行发现错误时,结束运行不执行之后的语句,并报错,如:下标越界,空指针异常
4 引用类型的数组
//声明一个Student类型的数组stus,包含3个元素,每个元素类型为Student类型
Student[] stus=new Student[3];
stus[0]=new Student("zhansan",18,"LF");
注意:每个元素都是Student类型,且引用类型需要new调用构造器来赋值。
//练习
ObserveSubmarine[] oses=new ObserveSubmarine[3];
oses[0]=new ObserveSubmarine();
oses[1]=new ObserveSubmarine();
oses[2]=new ObserveSubmarine();
for(int i=0;i<oses.length;i++){
System.out.println(oses[i].x+","+oses[i].y+","+oses[i].speed);
oses[i].move();
}
注意:
(1)oses只有length,所以有oses.length
(2)oses[i]x/y/width/heigh/speed,所以可以有oses[i].x等,可以通过内存分配来解释
5 数组对象内存释义
① 基本类型数组:
分析:
(1)new了一个int[]类型对象存储在堆中,且堆中存储该对象的成员变量
(2)main方法中变量arr为局部变量,存储在栈中,因为是引用类型的变量,所以存储的是地址
(3)栈中arr的地址是int[]数组中的arr[0],且知道了arr[0],arr[1]和arr[2]就都能找到了,因为是连续的
(4)以修改arr[0]的值为例,首先找到栈中的arr,然后通过arr存储的地址找到堆中的arr[0]进行修改数值
② 引用类型数组
分析:
(1)new了一个Student[]类型的对象存储在堆中;通过new调用了Student构造方法,产生了Student类型的对象存储在堆中
(2)main方法中的局部变量stus存储在栈中,因为是引用类型的变量,所以存储的是地址
(3)栈中stus的地址是Student数组中的stus[0],且知道了stus[0],stus[1]和stus[2]就都能找到了,因为是连续的
(4)堆中的Student数组对象的成员变量因为是引用类型,所以初始值是null,通过new调用Student构造方法赋值,因为是引用类型,所以存储的地址
(5)以修改stus[1].age=26为例,首先找到栈中的stus,通过stus存储的地址找到堆中的Student数组对象的成员变量stus[0],然后通过stus[0]存储的地址找到student对象的成员变量age修改为26
6 关于超类构造方法的调用问题
① java规定:构造派生类之前必须先构造超类
② 在派生类构造方法中若没有调用超类构造方法,则默认super()调超类无参构造方法,若超类只有有参构造方法,则派生类会报错。
③ 在派生类构造方法中若自己调用了超类构造方法,则不再默认提供
④ 注意:super()调用超类构造方法,必须位于派生类构造方法的第一行
7 关于超类与派生类参数接收问题
① 案例一:
分析:派生类通过调用超类的构造方法,将数值传输给超类的成员变量
//超类
SeaObject(int width,int heigh,int x,int y,int speed){
this.width=width;
this.heigh=heigh;
this.x=x;
this.y=y;
this.speed=speed;
}
//派生类
int life;
BattleShip(){
super(66,26,270,124,20);
life=5;
}
② 案例二:
分析:
调用测试中,通过new调用了派生类的构造方法,将数值传输给派生类,然后派生类调用超类的构造方法,将数值传输给超类的成员变量
//超类
SeaObject(int width,int heigh,int x,int y,int speed){
this.width=width;
this.heigh=heigh;
this.x=x;
this.y=y;
this.speed=speed;
}
//派生类
Mine(int x, int y){
super(11,11,x,y,1);
}
//调用测试
Mine m1=new Mine(100,200);