先接口(定义规则)再焊上去(使用接口)
接口一部分定义 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