------- android培训、java培训、期待与您交流! ---------- 继承,总结: 一.代码块: 1.代码块的种类: 1).局部代码块:定义在某个
Java_Day10 多态+内部类
.01 .02 多态 猫 x = new 猫(); 动物 x = new 猫(); 一个对象对应着不同类型。 多态在代码中的体现:父类或者接口的引用指向了其子类的对象。 .03 多态的好处:提高了代码的扩展性,前期定义的代码可以使用后期的内容。 第100行(animal a)使代码简单,其下面的两个method就可以省略 ,这是多态性的使用。 .04动态的弊端 前期定义的内容 不能调用后期子类中的特有内容。 84行会出现错误,因为animal中没有catchMouse的方法 多态的前提:1:必须要有关系,继承,实现。 2:要有覆盖。 .05转型 猫提升为动物 只能使用动物类中的方法,如果做eat这个动作,调用的是子类猫中的吃,因为子类中与父类有相同的eat方法,而子类覆盖了父类的eat方法(覆盖只发生在函数上,不发生在变量上) 专业讲:向上转型。将子类型隐藏。就不用使用子类的特有方法。(除非父类子类有同样的方法,子类会覆盖父类,执行子类中的方法) Animal a强制转换为(cat) 即向下转型 但是a创建时必须是cat型 如果是animal a = new animal()或者new成其他dog型等,则a不能强转成cat型 错误例子: Classcastexception 类转换错误
对于转型,自始至终都是子类对象在做着类型的变化。
.06转型 .07多态类型判断
Main函数中将dog向上转为了animal 调用method时,如果用a.catchMouse()语句会出现错误 因为dog不是cat,没有catchmouse这个方法 所以必须进行判断 If(a instanceof Cat) 如果对象a传进来之前本身是cat则进行判断,如果是 进入if语句 才能再调用cat中的catchmouse方法
instanceof:用于判断对象的具体类型。只能用于引用数据类型判断 通常在向下转型前用于健壮性的判断。
.08多态_成员变量 多态时: 成员的特点: 1.成员的变量。 a) 编译时:参考引用型变量所属的类中的是否有调用的成员变量,有,编译通过,没有,编译失败。 b) 运行时:参考引用型变量所属的类中的是否有调用的成员变量,并运行该所属类中的成员变量。 c) 编译和运行都参考等号的左边。
解释c:(面试中会考察,实际应用中很少出现这种情况,作为了解)
运行26行,输出3, 看等号左边,23行定义是: Fu f =
,是父类中的 所以Num输出的是Fu中的Num
3 如果23行等号左边是是:Zi f = ,则输出4
另外:如果等号左边是Zi f =,而子类中没有定义成员变量即://int num =4; 那么f.num会调用父类的num,如果父类中的Num也没有,那么就会出现a)编译失败
.09多态_成员函数
2.成员函数(这是非静态,依靠对象有关)。 编译时:参考引用型变量所属的类中的是否有调用的函数。有,编译通过,没有,编译失败。 运行时:参考的是对象所属的类中是否有调用的函数。 简单说:编译看左边,运行看右边。 因为成员函数存在覆盖特性。
第28行中的f.show输出的是zi show也就是调用子类的show,其实是应该先用父类的show但是子类父类都有相同的方法,子类覆盖了父类的show,所以执行输出的是zi show,但是如果父类中没有show()方法,则编译失败。 编译的时候看的等号左边。Fu f = ,如果父类中没有show,那么编译失败。 如果子类没有show方法,则用父类的show
Fu f =
new Zi(); 等号左边:引------ Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------- 1、抽象类(abstract)
特点: 1)抽象方法一定在抽象类中; 2)抽象方法和抽象类都必须被abstract关键字修饰; 3)抽象类不可以用new创建对象,调用抽象方法没有意义; 4)抽象用型变量
等号右边:对象所属类
.10多态_静态函数 静态函数(静态,跟类有关,一创建就有所属了,叫做静态型绑定,跟对象无关) 编译时:参考引用型变量所属的类中的是否有调用的静态方法。 运行时:参考引用型变量所属的类中的是否有调用的静态方法。 简单说,编译和运行都看左边。 其实对于静态方法,是不需要对象的。直接用类名调用即可。
.11内部类 内部类访问特点: 1.内部类可以直接访问外部类中的成员。 2.外部类要访问内部类,必须建立内部类的对象。 一般用于类的设计。 分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容,这是就是还有的事物定义成内部类来描述。
.12内部类——修饰符(不常见) Class outer { Class inner }
Outer.inner a = new outer().new inner(); Class outer { Static Class inner//如果是静态内部类,相当于外部类 } Outer.inner in = new outer.inter();
如果内部类都是静态的,成员是静态的。 Outer.inner.方法();
当内部类如果内部类定义了静态成员,该内部类必须被静态修饰
.13内部类-细节
11行如果是system.out.println(num);输出5 如果是system.out.println(this.num);输出4 如果是system.out.println(outer.this.num);输出3
为什么内部类能直接访问外部类的成员呢? 因为内部类持有了父类的引用
外部类名.this
.14局部内部类 内部类可以放在局部位置上。可以放到for循环里面。
如果内部类在局部位置method里面,new内部类对象的时候,要跟内部类在同一局域内,并且必须在内部类的下面,不能在内部类的上面。 第12行,必须定义成final
原理:内部类在局部位置上,只能访问局部中被final修饰的局部变量。
.15匿名内部类 内部类的简写模式 必须有前提:内部类必须继承或者实现一个外部类或者接口。 匿名内部类:其实就是一个匿名子类对象。
34-40就是匿名内部类
代替了23-29行内容 格式:new 父类or接口(){子类内容} .16匿名内部类-应用
通常的使用场景之一: 当函数参数是接口类型时,而且接口中的方法不超过三个。 可以用匿名内部类作为实际参数进行传递
.17匿名内部类—细节
.18对象的初始化过程
New对象时,到子类的构造对象中,第19行,有个隐藏的super(super只默认存在于子类构造函数中),再运行到父类的无参构造函数,父类无参构造函数中有一个show()方法,这时因为子类也有show()方法 会覆盖父类show ,所以执行子类中的show,此时num=9还没有运行,说明new对象时,先默认初始化0,再进行构造函数初始化的super内容,之后,回到子类的无参构造函数,再进行第17行的显示初始化,再执行20行。
Super()是直接转到父类的无参构造函数?是的
New Zi(); 1.子类默认初始化0 2.子类无参构造函数中的super->父类的无参构造函数 3.父类无参构造函数super(到object,但是无作用) 4.
第11行 显示初始化num=9; 5.
第12行 打印Fu 6.
第13行show但是子类有show覆盖父类的show输出32行的zi show (注意:虽然父类显示初始化num=9 ,但是回到子类的show num还是0) 7. 第27行显示初始化num=8 8. 构造代码初始化 输出22行Zi 9. 第28行,再次调用子类show输出zi show...8