Java编程思想(七、复用类)

   复用代码是Java众多引人注目的功能之一。

   复用类有两个方法。第一种:只需在新的类中产生现有类的对象。由于新的类是由现有类的对象所组成,所以这种方法称为组合。第二种:按照现有类的类型来创建新类。无需改变现有类的形式,采用现在类的形式并在其中添加新代码。这种方式称为继承。

   1、组合语法。只需将对象引用置于新类中即可。编译器并不会简单地伟每一个引用都创建默认对象。如果想要初始化这些引用,可以在代码中的下列位置进行:1)、在定义对象的地方。这意味着它们总是能够在构造器被调用之前被初始化。2)、在类的构造器中 3)、就在正要使用这些对象之前,这种方式称为惰性初始化。判一次空,如果为空则初始化。4)、使用实例初始化。

   2、继承语法。当创建一个类时,总是在继承。Java中所有的类都来自于根类Object。在继承过程中,需要先声明“新类与旧类相似”。这种声明是通过在类主体的左边花括号之前,书写后面紧随基类名称的关键字extends而实现的。当这么做时,会自动得到基类中所有的域和方法。

    1)、初始化基类。继承并不只是复制基类的接口。当创建了一个导出类的对象时,该对象包含了一个基类的子对象。这个子对象与你用基类直接创建的对象是一样的。二者区别在于,后者来自外部,而基类的子对象被包装在导出类对象内部。

    2)、带参数的构造器。如果没有构造器,或者想调用一个带参数的基类构造器,就必须用关键字super显式地编写基类构造器的语句。

   3、代理。Java并没有直接提供对它的支持。用代码介绍比较容易理解。

public class SpaceShipDelegation{
     private SpaceShipControls controls = new SpaceShipControls();
     public void back(int velocity){
       controls.back(velocity);          
  }          
}

和组合类似,但是比组合多包装了一层。这样可以控制,controls暴露哪些方法。如果是组合,那么controls中的所有方法都会暴露出来。

  4、确保正确清理。许多情况下,清理并不是问题,仅需让垃圾回收器完成该动作就行。但当必须亲自处理清理时,就要多加小心。因为,垃圾回收器可能永远也无法被调用,即时被调用,它是按照任何它想要的顺序来回收对象。最好的办法是除了内存以外,不能依赖垃圾回收器去做任何事。如果需要清理,就自己写一个清理方法,但不要使用finalize()。

public static void main(String[] args){
  CADSystem  x = new CADSystem ();  
   try{
   } finally{
     x.dispose();   //try块退出时,一定会调用finally子句。
  }          
}    

  5、名称屏蔽。如果Java的基类已经拥有某个已被多次重载的方法名称(参数列表不同)。那么在导出类中重新定义该方法名称并不会屏蔽其在基类中的任何版本。因此,无论是在该层或者它的基类中队方法进行定义,重载机制都可以正常工作。

    Java SE5中增加了@Override注解。它并不是关键字,但是可以把它当作关键字使用。当你选择覆写某个方法时,可以选择添加这个注解。

  6、在组合与继承之间选择。组合和继承都允许在新的类中放置子对象,组合是显式地这样做,而继承是隐式地做。一般来说很简单。如果是“is-a”的关系,那就使用继承。如果是“has-a”的关系,那就使用组合。

  7、protected关键字。在实际项目中,经常会想要将某些事物尽可能8、对这个世界隐藏起来,但仍允许导出类的成员访问它们。这时候便可以使用protected关键字。

  8、向上转型。派生类引用向上转型成为基类引用。因为派生类一定具有基类的方法。所以这种转型是肯定可以的。类接口唯一可能发生的事情是丢失方法,而不是获取它们。

  9、final关键字。下面介绍一下final的三个使用场景:数据,方法和类。

    1)、final数据。一:一个永远不变的编译时常量。 二:一个在运行时被初始化的值,但不会再被改变。这是针对于基本数据类型。如果当final修饰一个引用的时候,那是意味着这个引用永远不能再改变了,不能再指向其他对象,但是对象的内容是可以改变的。

    2)、空白final。所谓空白final指被声明为final但又未给定初值的域。但编译器必须确保空白final在使用前必须被初始化。所以必须在域的定义处或者每个构造器中用表达式对final进行赋值。

    3)、final参数。Java允许在参数列表中以声明的方式将参数指明为final。这意味着你无法在方法中更改参数引用所指向的对象。

    4)、final方法。使用final方法有两个原因。1、把方法锁定,以防任何继承类修改它的含义。可以确保在继承中使方法行为保持不变,并且不会被覆盖。2、是使用final方法时。等于同意编译器将针对这个方法的所有调用转为内嵌调用。但现在一般只有要明确静止覆盖时,才将方法设置为final。

    5)、final和private关键字。类中的所有private方法都隐式地指定为是final。由于无法取用private方法,所以也就无法覆盖它。对private方法添加final修饰词是没有什么意义的。

    6)、final类。当将某个类的整体定义为final时(通过关键字final置于它的定义之前),就表明了你不打算继承该类,并且也不允许别人这么做。

  10、初始化及类的加载。Java中的所有事物都是对象。所以它采用了不同的加载方式。每个类的编译代码都在它自己的独立的文件之中,该文件只有需要使用程序代码时才会被加载。“类的代码在初次使用时才加载”。这通常是指加载发生在创建类的第一个对象之时,但是当访问static域或static方法时,也 发生加载。其实构造器也是static方法,尽管static关键字并没有显式地写出来。因此更准确地讲,类是在其任何static成员被访问时加载的。

    运行一个类时的加载顺序是这样的:假设该类名为Bettle。首先访问Beetle.main()(一个static方法),于是加载器开始启动并找出Beetle类的编译代码(在名为Beetle.class的文件之中)。在对它进行加载的过程中,编译器注意到它有一个基类(这是由关键字extends得知的),于是它继续进行加载。不管你是否打算产生一个该基类的对象,这都要发生。如果该基类还有其自身的基类,那么第二个基类就会被加载,如此类推。接下来,根基类中的static初始化即会被执行,然后是下一个导出类,以此类推。这种方式很重要,因为导出类的static初始化可能会依赖于基类成员能否被正确初始化。至此,必要的类都有已经加载完毕。于是就可以开始创建对象。首先,对象中所有的基本类型都会被设为默认值,对象引用被设为null--这是通过将对象的内存设为二进制灵零值而一举产生的。然后,基类的构造器会被调用。在本例中,它是被自动调用的。但也可以用super来指定对基类构造器的调用。基类构造器和导出类的构造器一样,以相同的顺序来经历相同的过程。在基类构造器完成之后,实例变量按其次序被初始化。最后,构造器的其余部分被执行。

posted @ 2017-12-12 22:18  渣渣R  阅读(658)  评论(0编辑  收藏  举报