[7]复用类 0X01

来源:互联网 发布:ido软件下载 编辑:程序博客网 时间:2024/04/30 00:04

复用代码的两种方式:
1.组合
2.继承

每一个非基本类型的对象都有一个toString()方法。

组合

1.引用的初始化:
类中域的基本数据类型能够自动被初始化为”零”,但是对象引用会被初始化为null,如果这时你试图为他们调用任何方法,都会得到一个空指针异常。然而,在不抛出异常的情况下,仍旧可以打印一个null引用。

  • 初始化引用的位置:
    1.在定义对象的地方,意味着它们总是能够在构造器被调用之前初始化。
    2.在类的构造器中。
    3.使用实例初始化。
    4.“惰性初始化”、就在正要使用这些对象之前。(在生成对象不值得及
    不必每次都生成对象的情况下,这种方式可以减少额外的负担)

  • 上代码,演示四种方式:

package me.funnyzhao.recycleclass;class Soap{    private String s;    Soap(){        //构造器中初始化        System.out.println("Soap()");        s="Constructed";    }    @Override    public String toString(){        return s;    }}public class Bath {    //在定义对象的地方初始化    private String s1="Happy",            s2="Happy",            s3,s4;    private Soap catille;    private int i;    private float toy;    public Bath(){        System.out.println("Inside Bath()");        s3="joy";        toy=3.14f;        catille=new Soap();    }    {        //在所有初始化前调用        i=47;        System.out.println(i);    }    @Override    public String toString() {        //惰性初始化        if(s4==null){            s4="joy";        }        return             "s1="+s1+"\n"+            "s2="+s2+"\n"+            "s3="+s3+"\n"+            "s4="+s4+"\n"+            "i="+i+"\n"+            "toy="+toy+"\n"+            "castille= "+catille;    };    public static void main(String[] args) {        Bath b=new Bath();        System.out.println(b);    }}

OutPuts:

47Inside Bath()Soap()s1=Happys2=Happys3=joys4=joyi=47toy=3.14castille= Constructed

继承

1.初始化基类
java会自动在子类的构造器中插入对基类构造器的调用,下面的代码展示了上述机制在三层继承关系上是如何工作的:

class Art{    Art(){Sytem.out.println("Art Cr")}}class Drawing extends Art{    Drawing(){        System.out.println("Deawing Cr");    }}public class Cartoon extends Drawing{    public Cartoon(){System.out.println("Cartoon Cr");}    public static void main(String[] args){        Cartoon x=new Cartoon();    }}/*output:Art CrDrawing CrCartoon Cr*/

可以看到,对于构造器的调用是从基类“向外”扩散的,所以基类在子类构造器可以访问它之前,就已经完成了初始化。即使你不为Cartoon()创建构造器,编译器也会为你合成一个默认的构造器,该构造器将调用基类的构造器。

1.1下面的我们来证明基类构造器总是会被调用,并且在子类构造器之前被调用:

class Soap{    Soap(){        System.out.println("Soap()");    }}public class Bath extends Soap{    static{        System.out.println("static域");    }    {        System.out.println("空白");    }    Bath(){        System.out.println("Bath");    }    Bath(int i){        System.out.println("Bath"+i);    }    public static void main(String[] args) {        new Bath(1);        new Bath(2);    }}/*output:static域Soap()空白Bath1Soap()空白Bath2*/

从打印的结果可以看出,结论是成立的。
2.带参数的构造器
如果一个类的基类没有默认的构造器,或者想调用一个带参数的基类构造器,就必须用关键字super显示地编写调用基类构造器的语句,并且配以适当的参数列表:

class Game{    Game(int i){        System.out.println("Game()");    }}class BoardGame extends Game{    BoardGame(int i) {        super(i);        System.out.println("BoardGame()");    }}public class Bath extends BoardGame {    Bath(){        super(11);        System.out.println("Bath()");    }    public static void main(String[] args) {        Bath c=new Bath();    }}/*output:Game()BoardGame()Bath()*/

如果不在BoardGame()中显示的调用基类构造器,编译器会出错误提示;而且,调用基类构造器是你在子类中应该做的第一件事情。

0 0
原创粉丝点击