java基础1--继承

java类的构造顺序

public class test {
    public static void main(String[] args) {
        B b = new B("b");   //实体化一个B的对象b 使用了B(String )构造函数 
        B bb = new B("bb");//实体化了一个B的对象b 
    }
}


class B {
    public B(String b1) {
        System.out.println(b1);
    }

    static {
        System.out.println("初始化静态语句块");
    }
}

执行结果:

初始化静态语句块
b
bb

可以看到初始化静态语句块输出只有一次并且在第一个执行
 在类内部,对于成员变量,如果在定义的时候没有进行显示的赋值初始化,则Java会保证类的每个成员变量都得到恰当的初始化:

  1)对于 char、short、byte、int、long、float、double等基本数据类型的变量来说会默认初始化为0(boolean变量默认会被初始化为false);

  2)对于引用类型的变量,会默认初始化为null。
    当程序执行时,需要生成某个类的对象,Java执行引擎会先检查是否加载了这个类,如果没有加载,则先执行类的加载再生成对象,如果已经加载,则直接生成对象。

  在类的加载过程中,类的static成员变量会被初始化,另外,如果类中有static语句块,则会执行static语句块。static成员变量和static语句块的执行顺序同代码中的顺序一致。记住,在Java中,类是按需加载,只有当需要用到这个类的时候,才会加载这个类,并且只会加载一次。在生成对象的过程中,会先初始化对象的成员变量,然后再执行构造器。也就是说类中的变量会在任何方法(包括构造器)调用之前得到初始化,即使变量散步于方法定义之间。
  
 

public class Main {
    public static void main(String[] args) {
        B b = new B("b");   //实体化一个B的对象b 使用了B(String )构造函数
        B bb = new B("bb");//实体化了一个B的对象b
    }
}


class B {
    public B(String b1) {
        System.out.println(b1);
    }

    {
        System.out.println("初始化静态语句块");
    }
}

输出结果:

初始化静态语句块
b
初始化静态语句块
bb

结论:非静态语句快被执行了两次 注意这里去掉语句块的大括号会报错

public class test {
    public static void main(String[] args) {
        B b = new B();

    }
}

class B {
    public B() {
        System.out.println("b loaded");
    }

    C c = new C();

}

class C {
    public C() {
        System.out.println("c loaded");
    }
}

以上运行结果为:

c loaded
b loaded

c 在b之前生成 说明成员变量优先被初始化

下面是继承相关的语法

class Person {
    public Person() {
         
    }
}
 
class Man extends Person {
    public Man() {
         
    }
}

类Man继承于Person类,这样一来的话,Person类称为父类(基类),Man类称为子类(导出类)。如果两个类存在继承关系,则子类会自动继承父类的方法和变量,在子类中可以调用父类的方法和变量。在java中,只允许单继承,也就是说 一个类最多只能显示地继承于一个父类。但是一个类却可以被多个类继承,也就是说一个类可以拥有多个子类。

  1.子类继承父类的成员变量

  当子类继承了某个类之后,便可以使用父类中的成员变量,但是并不是完全继承父类的所有成员变量。具体的原则如下:

  1)能够继承父类的public和protected成员变量;不能够继承父类的private成员变量;

  2)对于父类的包访问权限成员变量,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承;

  3)对于子类可以继承的父类成员变量,如果在子类中出现了同名称的成员变量,则会发生隐藏现象,即子类的成员变量会屏蔽掉父类的同名成员变量。如果要在子类中访问父类中同名成员变量,需要使用super关键字来进行引用。

  2.子类继承父类的方法

  同样地,子类也并不是完全继承父类的所有方法。

  1)能够继承父类的public和protected成员方法;不能够继承父类的private成员方法;

  2)对于父类的包访问权限成员方法,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承;

  3)对于子类可以继承的父类成员方法,如果在子类中出现了同名称的成员方法,则称为覆盖,即子类的成员方法会覆盖掉父类的同名成员方法。如果要在子类中访问父类中同名成员方法,需要使用super关键字来进行引用。
注意:隐藏和覆盖是不同的。隐藏是针对成员变量和静态方法的,而覆盖是针对普通方法的

构造器的继承:

 
 

public class test {
    public static void main(String[] args) {
        B b = new B();

    }
}

class B {
    public B() {
        System.out.println("b loaded");
    }

    public B(String b1) {
        System.out.println("B " + b1 + " loaded");
    }

    public B(String b1, String b2) {
        System.out.println("B " + b1 + " " + b2 + " loaded");
    }
}

class C extends B {
    public C(String a) {
        System.out.println(a);
        ;
    }
}

如果将B的无参构造其注释去掉会报错
当子类重新定义父类继承的有参构造方法时 父类必须要有无参构造方法
如果父类的没有无参构造方法则必须使用super

public class test {
    public static void main(String[] args) {
        C c = new C("c");

    }
}

class B {
    /* public B()
     {
         System.out.println("b loaded");
     } */
    public B(String b1) {
        System.out.println("B " + b1 + " loaded");
    }

    public B(String b1, String b2) {
        System.out.println("B " + b1 + " " + b2 + " loaded");
    }
}

class C extends B {
    public C(String a) {
        super("m");  //super语句必须在构造器的第一句  这里也可以是super("c","d")
        System.out.println(a);
        ;
    }
}

运行结果

B m loaded
c

super()调用了父类的有参参构造方法:B(String b1);
如果使用super("c","d")则调用父类的方法B(String b1,String b2);

super.成员 的用法

要注意的是早使用super.之前要使用超类型的构造器

public class test {
    public static void main(String[] args) {

        C c = new C("c", "c");
    }
}

class B {
    String b = "10";

    /* public B()
     {
         System.out.println("b loaded");
     } */
    public B(String b1) {
        System.out.println("B " + b1 + " loaded");
    }

    public B(String b1, String b2) {
        System.out.println("B " + b1 + " " + b2 + " loaded");
    }
}

class C extends B {
    public C(String a) {
        super("m", "3");
        System.out.println(a);
        ;
    }

    public C(String a1, String a2) {

        super("superb:" + "  ");
        //当调用超类型构造器后可以在这里调用父类的成员变量
        System.out.println(super.b);
    }
}

一道题


public class test {
    public static void main(String[] args) {
        E e = new E();
    }
}

class C {
    public C(String cString) {
        System.out.println(cString + " constructor");
    }
}

class D {
    private C c = new C("c");

    public D() {
        System.out.println("D constructor");
    }
}

class E extends D {
    private D d = new D();

    public E() {
        System.out.println("E constructor");
    }
}

输出结果

c constructor
D constructor
c constructor
D constructor
E constructor

如果将class E extends D{...}更改为class E

public class test {
    public static void main(String[] args) {
        E e=new E();
    }
}

class C {
    public C(String cString) {
        System.out.println(cString + " constructor");
    }
}

class D {
    private C c = new C("c");

    public D() {
        System.out.println("D constructor");
    }
}

class E extends D {
    private D d = new D();

    public E() {
        System.out.println("E constructor");
    }
}

输出结果为
c constructor
D constructor
E constructor

可以发现少了两次输出 因此该小题第一段代码的实际的传递过程如下:

new E();//需要构造E 先构造E的父类D

构造父类D要先构造父类的成员c
所以调用C();输出了一次c constructor
继续构造D 调用D的构造方法D(); 输出D constructor
D构造结束后构造E
先构造E的成员d
d是D的对象 要实例化D 先构造D的成员c
new C("c");//调用了C的构造方法 输出c constructor
//回到
D d=new D();//输出constructor D 这时d也构造完毕
最后 调用E();方法构造e 结束

下面是验证

public class test {
    public static void main(String[] args) {
        E e = new E();
        F f = new F();
    }
}

class C {
    public C(String cString) {
        System.out.println(cString + " constructor");
    }
}

class D {
    private C c = new C("c");

    public D() {
        System.out.println("D constructor");
    }
}

class E extends D {
    private D d = new D();

    public E() {
        System.out.println("E constructor");
    }
}

class F extends D {
    public F() {
        System.out.println("F constructor");
    }
}

输出结果:
c constructor
D constructor
c constructor
D constructor
E constructor
c constructor
D constructor
F constructor
总结:先有父类后有子类 现有成员后有构造
每一次继承前都会把父类的方法和成员构造一次

感谢作者海子 原文地址http://www.cnblogs.com/dolphin0520/p/3803432.html

posted @ 2016-02-20 20:26  Salaku  阅读(264)  评论(0编辑  收藏  举报