案例1.
package cn.itcast.oop; public class ThisDemo { public static void main(String[] args) { Student s=new Student(); s.setName("李卫康"); s.setAge(22); String name=s.getName(); int age=s.getAge(); System.out.println("学生的姓名是:"+name+" 学生的年龄是:"+age); } } class Student{ private String name; private int age; public String getName() { return name;//这里默认省略了this,实际上是this.name } public void setName(String name) { name = name; } public int getAge() { return age; } public void setAge(int age) { age = age; } }
这段代码很简单,但是很容易出错!出错的关键点就在于this.
运行结果:
为什么会这样呢?为什么打印结果不是-->学生的姓名是:李卫康 学生的年龄是:22
案例2.
package cn.itcast.oop; public class StudentDemo { public static void main(String[] args) { Person s=new Person(); } } class Person{ private String name="林青霞"; private int age=27; public Person(){ name="刘毅"; age=30; } }Person s=new Person();做了哪些事情
A:把Student.class文件加载到内存
B:在栈内存中给s变量开辟一个空间
C:在堆内存中为人类对象申请一个空间
D:给成员便令进行默认初始化.null 0
E:给成员变量进行显示 初始化。林青霞,27
F:通过构造方法给成员变量进行初始化 刘毅,30
G:数据初始化完毕,然后把堆内存的地址值赋值给栈内存的s变量
3.继承概述
A:java只支持类的单继承不支持类的多继承
B:子类只能继承父类所有非私有的成员(成员方法和成员变量)
C:子类不能继承父类的构造方法,但是可以通过super(马上讲)关键字去访问父类构造方法。
D:子类中的成员变量和父类中的成员变量名称一样,
在子类方法中访问一个变量的查找顺序:
a:在子类方法的局部范围找,有就使用
b:在子类的成员范围找,有就使用
c:在父类的成员范围找,有就使用
d:如果还找不到,就报错。
E:this代表本类对应的引用。super代表父类存储空间的标识(可以理解为父类引用,可以操作父类的成员)
F:继承中构造方法的关系
子类中所有的构造方法默认都会访问父类中空参数的构造方法:因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化。注意:子类每一个构造方法的第一条语句默认都是:super();
G:如果父类没有无参构造方法,那么子类的构造方法会出现什么现象呢?报错。
如何解决呢?
1):在父类中加一个无参构造方法
2):通过使用super关键字去显示的调用父类的带参构造方法
3):子类通过this去调用本类的其他构造方法,子类中一定要有一个去访问了父类的构造方法,否则父类数据就没有初始化。
注意事项:
this(...)或者super(...)必须出现在第一条语句上。
如果不是放在第一条语句上,就可能对父类的数据进行了多次初始化,所以必须放在第一条语句上。
H:继承中成员方法的关系:1):子类中的方法和父类中的方法声明不一样,这个太简单。2):子类中的方法和父类中的方法声明一样,这个该怎么玩呢?
通过子类对象调用方法:
a:先找子类中,看有没有这个方法,有就使用
b:再看父类中,有没有这个方法,有就使用
c:如果没有就报错。
I:方法重写的注意事项
1):父类中私有方法不能被重写-->因为父类私有方法子类根本就无法继承
2):子类重写父类方法时,访问权限不能更低-->最好就一致
3):父类静态方法,子类也必须通过静态方法进行重写
其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中我会讲
子类重写父类方法的时候,最好声明一模一样。
例题:
class Fu { static { System.out.println("静态代码块Fu"); } { System.out.println("构造代码块Fu"); } public Fu() { System.out.println("构造方法Fu"); } } class Zi extends Fu { static { System.out.println("静态代码块Zi"); } { System.out.println("构造代码块Zi"); } public Zi() { System.out.println("构造方法Zi"); } } class ExtendsTest2 { public static void main(String[] args) { Zi z = new Zi(); Zi z2 = new Zi(); } }执行结果:
看程序写结果:
A:一个类的静态代码块,构造代码块,构造方法的执行流程
静态代码块 > 构造代码块 > 构造方法
B:静态的内容是随着类的加载而加载
静态代码块的内容会优先执行
C:子类初始化之前先会进行父类的初始化
结果是:
静态代码块Fu
静态代码块Zi
构造代码块Fu
构造方法Fu
构造代码块Zi
构造方法Zi
经典面试题:
class X { X() { System.out.print("X"); } Y b = new Y(); } class Y { Y() { System.out.print("Y"); } } public class Z extends X { Z() { //super System.out.print("Z"); } Y y = new Y(); public static void main(String[] args) { new Z(); } }记住一句话:先初始化父类数据,再初始化子类数据
因此执行流程为:根据初始化的顺序:先默认初始化,显示初始化,构造初始化
1.先初始化父类class X:执行成员变量显示初始化Y y=new Y();因此调用Y的构造函数打印Y
2.父类的构造方法初始化,执行构造方法中的代码打印X
3.子类进行初始化Class Z:执行成员变量初始化Y y=new Y()因此调用Y的构造方法打印Y
4.子类的构造方法初始化:执行构造方法中的代码打印Z
结果为:YXYZ
debug模式:
案例:
package cn.itcast.extend; public class Demo { public static void main(String[] args) { Zi z=new Zi(); z.show(); } } class Fu{ int num=10; public void show(){ System.out.println(num); } } class Zi extends Fu{ int num=20; public void show(){ System.out.println(num); } }结果是毋容置疑的:20
去掉子类的show方法
package cn.itcast.extend; public class Demo { public static void main(String[] args) { Zi z=new Zi(); z.show(); } } class Fu{ int num=10; public void show(){ System.out.println(num); } } class Zi extends Fu{ int num=20; }
为什么呢:因为子类中找方法show()没有找到就去父类中找.
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/u014010769/article/details/47725781