Java编程思想之七复用类

复用代码是Java众多引人注目的功能之一。但要想成为极具革命性的语言,仅仅能够复制代码并对之加以改变是不够的,它还必须做更多的事情。
使用类而不破坏程序代码:

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

7.1 组合语法

组合只需要将对象引用置于新类中就可以了。
但编译器并不是简单的为每一个引用都创建默认对象。如果想初始化这些引用,可以在代码中下列位置进行:

  • 在定义对象的地方。
  • 在类的构造器中。
  • 就在正要使用这些对象之前,这种方式称为惰性初始化。
  • 使用实例初始化。

7.2 继承语法

除非已明确指出要从其他类中继承,否则就是在隐式的从Java的标准根中类Object进行继承。
这种声明是通过在类主体的左边花括号之前,书写后面紧随基类名称的关键字extends而实现的。当这么做时,会自动得到基类中所有域和方法。
Javay用super关键字表示超类的意思。C#中用base。

7.2.1 初始化基类

当创建了一个导出类对象时,该对象包含了一个基类的子对象。这个子对象与你用基类直接创建的对象是一样的。二者区别在于,后者来自于外部,而基类的子对象被包装在导出类对象内部。
在构造器中调用基类构造器来执行初始化,而基类构造器具有执行基类初始化所需要的所有知识和能力。Java会自动在导出类的构造器中插入对基类构造器的调用。
即使你不为导出类创建构造器,编译器也会为你合成一个默认的构造器,该构造器将调用基类的构造器。

带参数的构造器

如果没有默认的基类构造器,或者想调用一个带参数的基类构造器,就必须使用关键字super显式的编写调用基类构造器的语句,并且配以适当的参数列表。

7.3 代理

这是继承于组合之间的中庸之道,因为我们将一个成员对象置于所要构造的类中,但与此同时我们在新类中暴露了该成员对象的所有方法。

public class SpaceShipDelegation {
    SpaceShipControls spaceShipControls=null;
    public SpaceShipDelegation(SpaceShipControls controls){
        this.spaceShipControls=controls;
    }
    public void up(int i){
        spaceShipControls.up(i);
    }
    public void  down(int i){
        spaceShipControls.down(i);
    }
}
class SpaceShipControls{
    void up(int velocity){}
    void down(int i){}
}

7.4 结合使用组合和继承

7.4.1 确保正确清理

Java中没有C++中析构函数的概念。析构函数是一种在对象被销毁时可以被自动调用的函数。
在清理方法中,还必须注意对基类的清理方法和成员对象清理方法的调用顺序,以防止某个对象依赖于另一个子对象情形发生。首先,执行类的所有特定的清理动作,其顺序同生成顺序相反。然后,调用基类的清理方法。

一旦涉及垃圾回收,能够信赖的事就不会很多了。垃圾回收器可能永远也无法被调用,即使被调用,它也可能以任何它想要的顺序来回收对象。最好的办法是除了内存外,不能依赖垃圾回收器去做任何事。如果需要进行清理,最好事编写自己的清理方法,但不要使用finalize()。

7.4.2 名字屏蔽

如果Java的基类拥有某个已被多次重载的方法名称,那么在导出类中重新定义该方法名称并不会屏蔽在基类中的任何版本。无论是在该层的基类中对方法进行定义,重载机制都可以正常工作。
当你想要覆写某个方法时,可以使用@Override这个注解。它可以防止你在不需要进行重载时意外进行了重载。

7.5 在组合与继承之间选择

组合和继承都允许在新的类中放置子对象,组合是显式的这样做,而继承是隐式的做。
组合技术通常用于想在新类中使用现有类的功能,但新类的用户看到的只是为新类所定义的接口,而非所嵌入对象的接口。

7.6 protected关键字

对于任何继承于此类的导出类或其他任何位于同一包内的类来说,它是可以访问的。

7.7 向上转型

将导出类转换成基类。
导出类是基类的一个超集,它可能比基类含有更多的方法,但它必须至少具备基类中所含有的方法。

7.7.2 组合与继承

该用组合还是继承,一个最清晰的判断办法就是是否需要从新类向基类进行向上转换。

final关键字

final可以用于三种情况:数据、方法、类

7.8.1 final数据

使数据恒定不变是有用的:

  • 1.一个永不改变的编译时常量
  • 2.一个再运行时被初始化的值,而你不希望它被改变

在编译期常量这种情况,编译器可以将该常量值带入任何可能用到它的计算式中,也就是可以在编译时执行计算式,这就减轻了运行时的负担。在对这个常量进行定义时,必须初始化。
一个是static又是final的域只占据一段不能改变的存储空间。
对于对象引用,final引用恒定不变,对象自身可以被修改。

空白final

Java允许生成"空白final",空白final指被声明为final但又未给定初始值的域。无论什么情况,编译器都确保final在使用前必须被初始化。

public class BlankFinal {
    private final int i=0;
    private final int j;//必须进行初始化
    private final Poppet p;
    public BlankFinal(){
        j=1;
        p=new Poppet(1);
    }

    public BlankFinal(int x){
        j=x;
        p=new Poppet(x);
    }

    public static void main(String[] args){
        new BlankFinal();
        new BlankFinal(2);
    }
}

class Poppet{
    private int i;
    Poppet(int ii){
        i=ii;
    }
}
final参数

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

public class FinalArguments {
    void with(final Gizmo g){
        //g=new Gizmo();不能赋值。
    }

    int without(final int i){
        //i+=1;不能改变
        return i+1;
    }
}

class Gizmo{
    public void spin(int i){
        System.out.println(i);
    }
}
7.8.2 final方法

使用final方法的原因有两个:

  • 把方法锁定,以防止任何继承类修改它的含义。保持继承中使方法保持不变,并且不会被覆盖。
  • 效率。将一个方法指定为final,就是同意将针对该方法的所有调用都转为内嵌调用。但在现在的虚拟机中,不需要使用final方法来进行优化了。
final和private关键字

private方法都隐式的指定是final。

7.8.3 final类

当将某个类整体定义为final时,就表面此类不能被继承。

7.9 初始化及类的加载

在对导出类进行加载时,会先对基类进行加载。如果该基类还有自身的基类,那么第二个基类就会被加载。

原文地址:https://www.cnblogs.com/Tan-sir/p/11228965.html

时间: 2024-11-09 11:42:00

Java编程思想之七复用类的相关文章

Java编程思想(四) —— 复用类

看了老罗罗升阳的专访,情不自禁地佩服,很年轻,我之前以为和罗永浩一个级别的年龄,也是见过的不是初高中编程的一位大牛之一,专访之后,发现老罗也是一步一个脚印的人.别说什么难做,做不了,你根本就没去尝试,也没有去坚持. If you can't fly then run,if you can't run then walk, if you can't walk then crawl,but whatever you do,you have to keep moving forward--Martin

java 编程思想 Directory工具类

1 package net.bigwrok; 2 3 import java.io.File; 4 import java.io.FilenameFilter; 5 import java.io.IOException; 6 import java.util.ArrayList; 7 import java.util.Iterator; 8 import java.util.List; 9 import java.util.regex.Pattern; 10 11 public class Di

Java编程思想:嵌套类

public class Test { public static void main(String[] args) { // Parcell11.test(); // ClassInterface.Test.test(); TestBed.Tester.test(); } } /* 嵌套类和普通的内部类还有一个区别.普通的内部类的字段和方法,只能放在类的外部 层次上,所以普通的内部类不能有static数据和static字段,也不能包含嵌套类.但 是嵌套类可以包含这些东西 */ interfac

Java编程思想(五) —— 多态(上)

上一章,Java编程思想(四) -- 复用类里面讲到了向上转型,感觉和多态放在一起写更好. 多态,polymorphism.一个重要的特性,篇幅太长了,分上下两篇写. (1)向上转型 class TV{ public static void show(TV tv){ System.out.println("TV"); } } public class LeTV extends TV{ public static void main(String[] args) { LeTV letv

33.JAVA编程思想——JAVA IO File类

33.JAVA编程思想--JAVA IO File类 RandomAccessFile用于包括了已知长度记录的文件.以便我们能用 seek()从一条记录移至还有一条:然后读取或改动那些记录. 各记录的长度并不一定同样:仅仅要知道它们有多大以及置于文件何处就可以. 首先.我们有点难以相信RandomAccessFile 不属于InputStream 或者OutputStream 分层结构的一部分.除了恰巧实现了DataInput 以及DataOutput(这两者亦由 DataInputStream

《Java编程思想》学习01:普通类的初始化加载顺序分析

<Java编程思想>学习01:普通类的初始化加载顺序分析 本文根据控制变量法,分析普通类(没有extends,implement)初始化的加载顺序: 参考<Java编程思想>第五章 源码 StaticClass1类 package com.tyj.study.thinkinjava; /* * *@Description: *@Author:TYJ *@Date: create in 2019/7/9 17:22 */ public class StaticClass1 { { S

《Java编程思想(第4版)》pdf

下载地址:网盘下载 内容简介 编辑 本书赢得了全球程序员的广泛赞誉,即使是最晦涩的概念,在Bruce Eckel的文字亲和力和小而直接的编程示例面前也会化解于无形.从Java的基础语法到最高级特性(深入的面向对象概念.多线程.自动项目构建.单元测试和调试等),本书都能逐步指导你轻松掌握.[1] 从本书获得的各项大奖以及来自世界各地的读者评论中,不难看出这是一本经典之作.本书的作者拥有多年教学经验,对C.C++以及Java语言都有独到.深入的见解,以通俗易懂及小而直接的示例解释了一个个晦涩抽象的概

【java编程思想--学习笔记(四)】对象导论

写这篇博客的前言: 长话短说,我希望通过阅读<java编程思想>来使我的代码 简洁可用 . 目的的层次不同,首先具体的目标是,了解Java的特性和巩固Java的基础. 更抽象的目的如下: 1.期待以巩固基础的方式,使代码优美,简洁,高效. 2.使自己写的模块能够开放适度,好用. 3.形成一种对代码是否优美的审美观. 于是<Java编程思想>第一章 对象导论 由此开始. 1.1 抽象过程 java 相对于命令式语言的优势在于只针对于待解问题建模.后者所做的主要抽象要求所做问题基于计算

Java编程思想之8多态

这一章看下来,感觉比较混乱.乱感觉主要乱在8.4  8.5. 开始读的时候,感觉8.1 8.2 8.3都挺乱的.读了两遍后发现前三节还是比较有条理的. 8.1主要讲了什么是多态,多态的好处. 8.2主要讲了什么情况会发生多态?? 8.3主要讲了构造器内部里面的方法调用会发生多态. 8.4就一页,而且感觉一般用不到.用到了再看也行. 8.5也很简单,相当于一个总结,一个补充(向下转型) 我主要根据书上的内容,总结两个内容: 1.什么是多态,多态的好处: 2.什么情况下会发生多态?为什么这些情况下会