------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
day10 02-面向对象-多态-概述
1、多态定义:某一类事物的多种存在形式。
2、对象的多态性,代码示例
class 动物{
}
class 猫 extends 动物{
}
class 狗 extends 动物{
}
猫 m = new 猫();
动物 d = new 动物();//父类引用指向子类对象
小猫!小动物!你原来管小猫叫小猫,后来你管小猫叫小动物,有错吗?没错的呀!
猫这类事物既具备猫的形态,又具备着动物的形态。这就是对象的多态性。
简单说,就是一个对象对应着不同类型。
多态在代码中的体现:父类或者接口的引用,指向其子类的对象。
day10 03-面向对象-多态-好处
1、代码示例
简略为下图:
2、多态的好处
提高了代码的扩展性,前期定义的代码可以使用后期的内容。
如上例:我前期定义了一个Animal类。我可以拿Animal接受任何,后期所创建的Animal的子类对象。我后期可以随便来什么动物,小鸡、小鸭,我前期有了Animal,后期只要是动物,尽管来。
day10 04-面向对象-多态-弊端&前提
1、多态的前提:前期定义的内容不能使用(调用)后期子类的特有内容。
2、多态的前提:
①必须有关系,要么继承,要么实现。(因为你要拿父类或接口来接收,后期定义的子类或实现类对象)
②要有覆盖(有覆盖,执行的才是后面各个子类所应该执行的内容。比如上例中的eat()方法。小狗是啃骨头,小猫是吃鱼)。调用通用覆盖方法,运行子类函数。
day10 05-面向对象-多态-转型1
1、代码示例
这时,猫一旦提升为动物,访问上就出现了局限性,就不能访问猫这个子类所特有的功能了。
作用:可以限制对特有功能的访问。提高扩展性。
专业点讲:向上转型。猫已经向上荣升为动物了。
2、那么问题来了,我如果想继续用猫的特有功能,怎么办?你可以将该对象进行向下转型。
猫一定是动物,但是动物就一定是猫吗?不一定!这种判断,要看右边new的实例到底是什么。
3、注意:对于转型,自始至终都是子类对象在做着类型的变化。
day10 07-面向对象-多态-类型判断-instanceof
1、观察以下代码
2、别人往这个函数里面传什么动物,你根本就不知道。那么你向下转成猫,就会报错。怎么解决?解决方式就是在向下转型前,加一个判断。他是猫你才转,他不是猫你别瞎转。
在向下转型之前,通常进行instanceof的判断,增加程序的健壮性。
day10 08-面向对象-多态-成员变量
1、代码示例
class Fu{
int num=3;
}
class Zi extends Fu{
int num=4;
}
public class Demo11 {
public static void main(String[] args){
Zi z=new Zi();
System.out.println(z.num);
Fu f=new Zi();
System.out.println(f.num);
}
}
运行结果:4
3
2、new Zi()里面有俩num,一个是父类的num,一个是子类的num。子类对象提升为了父类对象,那么就找父类的num。不覆盖!覆盖只发生在函数上。若class Fu{},再执行下面,运行结果:报错,找不到num。
3、多态时,成员的特点:
①成员变量:编译时,参考引用型变量所属类中是否有调用成员变量。有,编译通过;没有,编译失败。
运行时,参考引用型变量所属的类中是否有调用的成员变量,并运行该所
属类中的成员变量。
4、简单说,编译和运行都参考等号的左边。
day10 09-面向对象-多态-成员变量
1、此为重点!必须的重点!
2、代码示例
class Fu{
void show(){
System.out.println("Fushow");
}
}
class Zi extends Fu{
void show(){
System.out.println("Zishow");
}
}
public class Demo11 {
public static void main(String[] args){
Fu f=new Zi();
f.show();
}
}
运行结果:Zi show
3、如果父类对象中没有show()可不可以?不可以!编译失败。
4、若子类中无show(),一个super指向父类,运行结果:Fu show
5、多态时,成员的特点:②成员函数(非静态)
编译时,参考引用型变量所属的类中是否有调用的函数。有,编译通过。没有,编译失败。
一有多态,向上转型,将子类型隐藏,就不能使用子类型的特有方法了。
运行时:参考对象所属的类中是否有调用的函数。
简单来说:编译看左边,运行看右边。右边没有这个方法,super到超类。
day10 10-面向对象-多态-静态函数
1、代码示例
class Fu{
static void method(){
System.out.println("Fu staticmethod");
}
}
class Zi extends Fu{
static void method(){
System.out.println("Zi staticmethod");
}
}
public class Demo11 {
public static void main(String[] args){
Fu f=new Zi();
f.method();
}
}
运行结果:fu static method
2、非静态方法,必须依赖对象来调用。
3、对象的多态性。静态方法需要用对象吗?直接Fu.method();Zi.method();哦了。
4、多态时,成员的特点:③静态函数
编译时:参考引用型变量所属的类中是否有调用的静态方法。
运行时:参考引用型变量所属的类中是否有调用的静态方法。
简单说:编译和运行都看左边。
5、其实对于静态方法,是不需要对象的。那我就根本不用管它new的是什么了。直接用类名(左边)调用即可。
day10 11-面向对象-内部类-概述
1、内部类:将一个类定义在另一个类里面,对里面那个类就成为内部类。
2、一个内部类写好了之后,他应该有所属才对,谁的内部类。
class Outer{
class Inner{
}
}
class Outer2{
class Inner{
}
}
public class Demo12 {
public static void main(String[] args) {
}
}
3、内部类的访问特点:
①内部类可以直接访问外部类中的成员。
②外部类要访问内部类,必须建立内部类的对象。
4、一般用于类的设计:分析事物时,发现该事物描述中还有事物。而且这个事物还在访问被描述事物的内容。这时,就把还有的事物定义成内部类来描述。
5、代码示例
class Outer{
private int num=3;
class Inner{
void show(){
System.out.println("showrun..."+num);
}
}
public void method(){
Inner in=new Inner();//method()是外部类的方法,外部类访问内部类,必须建立内部类的对象。
in.show();
}
}
class Demo12{
public static void main(String args[]){
Outer out=new Outer();
out.method();
}
}
运行结果:show run…3
day10 12-面向对象-内部类-修饰符
1、在其他类访问另一个类中的内部类。代码示例:
class Outer{
private int num=3;
class Inner{
void show(){
System.out.println("showrun..."+num);
}
}
public void method(){
Inner in=new Inner();
in.show();
}
}
class Demo12{
public static void main(String args[]){
Outer.Inner in=new Outer().new Inner();
in.show();
}
}
运行结果:show run…3
2、
3、如果内部类是静态的,相当于一个外部类(static可以用来修饰类——static class Inner),那么内部类所使用的东西也要是静态的。
4、
5、如果内部类是静态的,成员是静态的。如果对内部类中定义了静态成员,该内部类也必须是静态的。否则报错:内部类当中不能有静态声明。
6、
day10 13-面向对象-内部类-细节
1、代码示例
class Outer{
int num=3;
class Inner{
int num=4;
void show(){
int num=5;
System.out.println(num);
}
}
public void method(){
new Inner().show();
}
}
class Demo12{
public static void main(String args[]){
new Outer().method();
}
}
运行结果:5(栈内存中有,先用栈里的)
2、如果我想打印4,show方法里写System.out.println(Inner.this.num);
如果我想打印3,show方法里写System.out.println(Outer.this.num);
3、你写this.num,前面隐含了一个本类对象,即Inner.this.num。你要打印外部类的Outer.this.num。只写this.num,打印的也是4。
4、为什么内部类能直接访问外部类中的成员?
那是因为内部类持有外部类的引用——外部类名.this
day10 14-面向对象-内部类-局部内部类
1、内部类可以存放在局部位置上。
2、代码示例
class Outer{
int num=3;
void method(){
int x=9;
class Inner{
void show(){
System.out.println("show..."+x);
}
}
Inner in=new Inner();
in.show();
}
}
public class Demo13 {
public static void main(String[] args) {
new Outer().method();
}
}
内部类放到了方法体中。但是此处报错:从内部类中访问局部变量x,需要x被声明为最终类型。(final)
void method(){
final int x=9;
class Inner{
void show(){
System.out.println("show..."+x);
}
}
Inner in=new Inner();
in.show();
}
运行结果:show…9
3、注意:内部类在局部位置上只能访问局部中被final修饰的局部变量。
day10 15-面向对象-匿名内部类-概述
1、匿名内部类,必须有前提,内部类必须继承或者实现一个外部类或者接口。
2、匿名内部类顾名思义——他没有名字。没名字你new什么?所以才有了这些前提。
3、代码示例
abstract class Demo{
abstract void show();
}
class Outer{
int num=4;
public void method(){
new Demo(){
void show(){
System.out.println("show..."+num);
}
}.show();
}
}
这里面的new demo是匿名内部类。这里面同时覆盖了show(),同时也顺便调用了show()。在调用show方法时,由于匿名内部类中无num。一个Outer.this,去外部类去找。
4、匿名内部类,其实就是一个匿名子类对象。
5、格式:new 父类or接口(){子类内容}
6、主方法中:new Outer().method();
运行结果:show…4
day10 17-面向对象-匿名内部类-细节
1、代码示例:
class Outer{
void method(){
Object obj=new Object(){
public void show(){
System.out.println("showrun");
}
};
obj.show();
}
}
public class Demo14 {
public static void main(String[] args) {
new Outer().method();
}
}
2、obj.show()这句挂了,因为show()是子类特有方法。因为匿名内部类这个子类对象被向上转型为了Object类型了,这样就不能再使用子类的特有方法了。
day10 18-面向对象-对象的初始化过程
1、代码示例
class Fu{
int num=9;
{
System.out.println("Fu");
}
Fu(){
super();
//显示初始化
//构造代码块初始化
show();
}
void show(){
System.out.println("Fushow"+num);
}
}
class Zi extends Fu{
int num=8;
{
System.out.println("Zi");
}
Zi(){
super();
//显示初始化
//构造代码块初始化
show();
}
void show(){
System.out.println("Zi show"+num);
}
}
public class Demo15 {
public static void main(String[] args) {
new Zi();
}
}
运行结果:Fu
Zi show 0
Zi
Zi show 8
2、对象的初始化过程