javaseday09(多态,内部类,匿名内部类)

先接口(定义规则)再焊上去(使用接口)

接口一部分定义 usb接口像usb 

定义一个规则 只要然后出现的设备都符合这个规则就可以

这个规则就是接口

interface USB{ //暴露的规则

public void open();

public void  close();

}

class BookPc{

public static void main(String[] args){

useUsb(new Upan()); //功能扩展了

}

//使用规则

public static void useUsb(USB u){  //接口类型的引用,用于接受接口的子类对象

u.open();

u.close();

}

}

//实现规则

//这些设备和电脑的耦合性降低了

class Upan implements USB{

public  void open(){};

public  void close(){};

}

对象的多态性

猫既是动物也是猫 父类引用指向子类对象就体现了多态的特点  Animal x = new Cat(); 一个对象两种形态

简单说就是一个对象对应着不同类型

多态在代码中的体现:就是父类或者接口引用指向了子类的对象


多态的好处

提高了代码的扩展性,前期定义的代码可以使用后期的内容 Animal 的子类可以传入到Animal 的方法中

父类作为引用能接受很多子类 

多态的弊端::

前期定义的内容不能使用(调用)后期子类的特有内容

多态的前提:

1、必须有关系 继承、实现

2、要有覆盖

Animal a = new Cat();//自动类型提升,猫对象提升为动物类型但是特有功能无法访问  作用就是限制对特有功能的访问 只能用父类的方法

专业叫向上转型 将子类型隐藏 就不用使用子类的特有方法

如果还想用具体动物猫的特有功能

可以进行向下转型

Cat c = (Cat) a;//向下转型的目的是为了使用子类中的特有方法

c.eat();

c.catchMouse();

对于转型自始至终都是子类对象在做着类型的变化

method (Animal  a){

a.eat();

if(a instanceof Cat){ //用于判断对象的具体类型只能用于引用数据类型判断 通常在向下转型时用于健壮性的判断

Cat c = (Cat) a;

c.catchMouse();

}

}

多态时

成员的特点   编译不通过类文件 (字节码文件)都不能产生

1、成员变量: 

编译时:参考引用型变量所属的类中是否有调用的成员变量,有,编译通过,没有,编译失败

运行时:参考引用型变量所属的类中是否有调用的成员变量,并运行该所属类中的成员变量

编译和运行都参考等号的左边

一般都不出现因为父类有了直接用父类的

2、成员函数(非静态的 动态绑定在某个对象上)

编译时:参考引用型变量所属的类中是否有调用的函数 有编译通过,没有编译失败

运行时:参考对象所属的类中是否有调用的函数 

简单说编译看左边 运行看右边

运行以对象为主 编译的时候 子类还有个super可以找父类的方法

3、静态函数 (不需要对象 静态直接绑定了父类)

对象多态性 静态没对象或者说不需要  直接用类名.调用

编译时:参考引用型变量所属的类中的是否有调用的静态方法

运行时:参考引用型变量所属的类中的是否有调用的静态方法

简单说:编译和运行都看左边

降低耦合性简称解耦

内部类 

将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)

内部类的访问特点

1、内部类可以直接访问外部类中的成员2、外部类要访问内部类,必须建立内部类的对象

一般用于类的设计

分析事物时 发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容 这时就把还有的事物定义成内部类的描述

class Outer{

private int num = 3;

class Inner{ //内部类 一般都私有就访问不了

void show(){

syso;

}

static void fu(){

syso:}  如果内部类 中定义了静态成员 该内部类也必须是静态的 因为 内部成员是静态随着类的加载而加载如果类不是静态的 就不能直接类名调用静态无用

}

public void method(){

Inner in = new Inner();

in.show();

}

}

class Demo{

public static void main(String[] args){

Outer.Inner in = new Outer().new Inner();

in.show();

//如果内部类是静态的 相当于一个外部类

Outer.Inner in = new Outer.Inner();

in.show();

//如果内部类是静态的,成员是静态的

Outer.Inner.function|();

}

}

为什么内部类能直接访问外部类中成员

那是因为内部类持有了外部类的引用 外部类名.this

内部类可以存在在局部位置上

内部类在局部位置上只能访问局部中被final修饰的局部变量  因为方法 弹栈后变量就没了而内部类的对象还在却不能访问到局部变量了

匿名内部类就是内部类的简写格式

必须有前提:内部类必须继承或实现一个外部类或者接口

匿名内部类:其实就是个匿名子类对象

格式就是:new 父类or接口()    {子类对象}

abstract class Demo{

abstract void show();

}


class Outer{

int num=4;

public  void method(){

new Demo(){ //匿名内部类(new Inner().show();)

void show(){

syso();

}

}.show();(调用部分)

}

}

通常使用场景之一

当函数参数是接口类型时 而且接口中的方法不超过三个

可以用匿名内部类作为实际参数进行传递

Inter in  =  new Inter(){

public void show(){}

public void show2(){}

};

in.show1();

in.show2();

静态中不允许有this 主方法 不能直接 加非静态class的new inner(); 

Object obj= new Object()因为向上转型了所以子类特有的方法不能调用 show就不能用了

构造函数快于常量的显示初始化不过有默认初始化

class Zi extends Fu{

int num = 9;

Zi(){

//super();

//显示初始化 int num=9;

//构造代码块初始化

}

}

class Fu{
int num=1;
{
System.out.println("fu constructor"+num); //1
}
Fu(){
//显示初始化
//构造函数初始化
System.out.println("Fu"+num);//2
show();
}
void show() {
System.out.println("ss");
}


}
class Zi extends Fu{
int num = 9;


{
System.out.println("zi constructor"+num);//4
num=10;
}
Zi(){
// 显示初始化
// 构造函数初始化
System.out.println("zi "+num);//5
}
void show() {
System.out.println("show"+num);//3
}
}
class Abstract{
public static void main(String[] args) {
new Zi();
}
}

fu constructor1
Fu1
show0
zi constructor9
zi 10

你可能感兴趣的:(javase)