继承 接口 抽象类 多态 反射 加载

继承。多态。抽象类。接口

继承:

class A extends B{

}

1、派生类继承了基类的除了  基类的构造函数  的其他数据成员??????

2、super(): 调用基类的构造函数
* super.data: 访问我基类的数据成员
* super.func(): 访问我基类的成员方法

复制代码
class Base{//基类  父类  超类
    public int ma;//数据成员
    
    static{
        System.out.println("Base.static init!!");
    }
    {
        System.out.println("Base.instance init!!!");
    }
    
    public Base(int a){
        System.out.println("Base init!!!");
        this.ma = a;
    }
}

//Derive子类     派生类
class Derive extends Base{
    private int mb;
    
    static{
        System.out.println("Derive.static init!!");
    }
    
    {
        System.out.println("Derive.instance init!!!");
    }
    //派生类继承了基类的除了  基类的构造函数  的其他数据成员
    public Derive(int a,int b){
        super(a);//基类的构造函数        第一行            如果此时没有super(),那么Derive构造函数就会报错
        /*super():     调用基类的构造函数
              super.data:   访问我基类的数据成员
              super.func():  访问我基类的成员方法*/
        //int i = super.ma;
        //ma = a;//error
        this.mb = b;
        System.out.println("Derive init!!!");
    }
}
复制代码

3、类---》对象 初始化顺序:::
* 1.静态数据成员 简单类型 : 引用类型 null 
* 2.静态代码块初始化
* 3.实例数据成员
* 4.实例代码块初始化
* 5.调用合适的构造函数

4、派生类继承基类后的打印顺序????静态(只初始化一次) 
* --- 》 实例----》构造函数

复制代码
public static void main(String[] args) {
        
        //实例化两个子类的对象
        /*Derive d = new Derive(10,20);
        System.out.println("================");
        Derive d2 = new Derive(10,20);*/
        
        //初始化顺序 先static代码块初始化     再父类实例代码块初始化 再父类构造函数初始化 再子类实例代码块初始化 再子类构造函数初始化
        /*Base.static init!!
        Derive.static init!!
        Base.instance init!!!
        Base init!!!
        Derive.instance init!!!
        Derive init!!!
        ================
        //静态代码块只能初始化一次
        Base.instance init!!!
        Base init!!!
        Derive.instance init!!!
        Derive init!!!*/
        
        
        
        
        //实例化一个父类对象
        /*Base b = new Base(10);*/
        
         //父类的初始化顺序
        /*Base.static init!!
        Base.instance init!!!
        Base init!!!*/
        
        
        
        
        //实例化一个子类对象
        /*Derive d = new Derive(10,20);*/
         
         //子类的初始化顺序
        /*Base.static init!!
        Derive.static init!!
        Base.instance init!!!
        Base init!!!
        Derive.instance init!!!
        Derive init!!!
*/
        
        
        /*Derive d = new Derive(10,20);
        Base b = new Base(10);*/
        
        /*Base.static init!!
        Derive.static init!!
        Base.instance init!!!
        Base init!!!
        Derive.instance init!!!
        Derive init!!!
        Base.instance init!!!
        Base init!!!*/
复制代码

5、基类数据成员在派生类当中的访问权限
*                               同包子类               同包非子类              不同包子类              不同包非子类
* public                         可以                      可以                          可以                            可以

* protected                   可以                       可以                          可以                          不可以 
* (包访问权限,继承当中 )                                                          (继承)

* private                       不可以                  不可以                       不可以                        不可以

* 默认权限                    可以                      可以                         不可以                        不可以
* (包访问权限)

 6、派生类和基类之间相互赋值

子类对象可以给父类对象赋值,父类对象不能给子类对象赋值
复制代码
public static void main(String[] args) {
        Derive d = new Derive(10,20);
        Base b = new Base(10);*/
        
        /*Base.static init!!
        Derive.static init!!
        Base.instance init!!!
        Base init!!!
        Derive.instance init!!!
        Derive init!!!
        Base.instance init!!!
        Base init!!!*/
        
        //子类对象可以给父类对象赋值,父类对象不能给子类对象赋值
        //b = d;//   true  人    学生  从下到上的转换
        //d = b;//  error 学生     人 
复制代码

7.7、invokevitural   invokestatic  invokespecial

扫描二维码关注公众号,回复: 1877111 查看本文章

java中除了构造函数和静态函数,其他成员函数都被处理为虚函数也就是invokevitural 

复制代码
class Base1{
    private int ma;
    public Base1(int a){
        this.ma = a;
        fun1();
    }
    
    
    public void fun1(){//实例方法
        System.out.println("Base.fun1!!!");
    }
    
    public static void fun2(){//类方法
        System.out.println("Base.fun2!!!");
    }
    
}

class Derive1 extends Base1{ 
    private int mb;
    public Derive1(int a,int b){
        super(a);
        this.mb = b;
    }
    //重载
    public void fun1(int i){
        System.out.println("Derive1.fun1(int)!!");
    }
}

class Derive2 extends Base1{
    private int mc;
    public Derive2(int a,int c){
        super(a);
        this.mc = c;
        fun1();
    }
    
    public void fun1(){//实例方法
        System.out.println("Derive2.fun1!!!");
    }
    
    public static void fun2(){//类方法
        System.out.println("Derive2.fun2!!!");
    }
    
}
复制代码
复制代码
public static void main(String[] args) {
        
        Base1 b = new Base1(10);//通过反汇编发现关键字invokespecial
        System.out.println(b);
结果:
Base.fun1!!!
renben.Base1@feb48

         b.fun1();//invokevirtual

         Base.fun2();//invokestatic

 
复制代码

8.派生类和基类同名方法的关系

(1)重载   函数名相同  参数列表不同  返回值无要求

(2)重写、覆盖    函数名相同  参数列表相同  返回值相同

复制代码
class Base1{
    private int ma;
    public Base1(int a){
        this.ma = a;
        fun1();
    }
    
    
    public void fun1(){//实例方法
        System.out.println("Base.fun1!!!");
    }
    
    public static void fun2(){//类方法
        System.out.println("Base.fun2!!!");
    }
    
}

class Derive1 extends Base1{ 
    private int mb;
    public Derive1(int a,int b){
        super(a);
        this.mb = b;
    }
    //重载
    public void fun1(int i){
        System.out.println("Derive1.fun1(int)!!");
    }
}

class Derive2 extends Base1{
    private int mc;
    public Derive2(int a,int c){
        super(a);
        this.mc = c;
        fun1();
    }
    //重写
    public void fun1(){//实例方法
        System.out.println("Derive2.fun1!!!");
    }
    
    public static void fun2(){//类方法
        System.out.println("Derive2.fun2!!!");
    }
    
}
复制代码
复制代码
 重载:       
main{
        Base1 b = new Base1(10);  
        Derive1 d = new Derive1(10,20);
        d.fun1();  
        d.fun1(10);
}
结果:Base1.fun1!!!
     Derive1.fun1(int)!!

重写:
main{
        Base1 b1=new Base1(10);
        Derive2 d2=new Derive2(10,40);
        Base1 b2=new Derive2(10,40);
        b1.fun1();
        d2.fun1();
        b2.fun1();
}
结果:
Base1.fun1!!!
Derive2.fun1!!!
Derive2.fun1!!!

通过javap -c反汇编发现:
43行发现:显示的是Base为什么打印的是Derive2.fun1!!!呢???
这是因为发生了动态绑定:编译期间不知道调用谁所以叫做动态绑定


类加载器加载产生class对象→静态代码块初始化→实例代码块初始化→构造函数初始化



静态绑定:

main{
     Base1 b2=new Derive2(10,40);

        b2.fun2();
       
        b2.fun1();
}
结果:
Base1.fun2!!!
Derive2.fun1!!!

 
      
复制代码

 那为什么静态绑定打印出来的是Base.fun2!!!呢?而动态打印是Derive2.fun1!!!?

这是因为方法表本身在编译期间产生,fun2是静态方法,它在编译期间产生,所以不会发生动态绑定
而动态绑定发生在运行期间  需要new



10.构造函数可以发生动态绑定

猜你喜欢

转载自blog.csdn.net/qq_41974391/article/details/80616063
今日推荐