复用代码是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 初始化及类的加载

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

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

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

    看了老罗罗升阳的专訪,不由自主地佩服,非常年轻,我之前以为和罗永浩一个级别的年龄.也是见过的不是初高中编程的一位大牛之中的一个,专訪之后.发现老罗也是一步一个脚印的人. 别说什么难做,做不了.你根本就 ...

  2. Java编程思想学习笔记——类的访问权限

    类的访问权限 Java中,访问权限修饰词用于确定库中哪些类对于该库的使用者是可用的. public class Foo{ } 注意点: 每个文件(编译单元)只能有一个public类. public类的 ...

  3. Java编程思想:File类list()方法

    import java.util.regex.Pattern; import java.io.File; import java.io.FilenameFilter; public class Tes ...

  4. Java编程思想:File类其他方法

    import java.io.File; public class Test { public static void main(String[] args) { MakeDirectories.te ...

  5. Java编程思想:嵌套类

    public class Test { public static void main(String[] args) { // Parcell11.test(); // ClassInterface. ...

  6. Java编程思想:File类getCanonicalFile()方法,listFile()方法

    import java.io.IOException; import java.util.*; import java.util.regex.Pattern; import java.io.File; ...

  7. java编程思想-复用类总结

    今天继续读<java 编程思想>,读到了复用类一章,看到总结写的很好,现贴上来,给大家分享. 继承和组合都能从现有类型生成新类型.组合一般是将现有类型作为新类型底层实现的一部分来加以复用, ...

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

    33.JAVA编程思想--JAVA IO File类 RandomAccessFile用于包括了已知长度记录的文件.以便我们能用 seek()从一条记录移至还有一条:然后读取或改动那些记录. 各记录的 ...

  9. Java编程思想 (1~10)

    [注:此博客旨在从<Java编程思想>这本书的目录结构上来检验自己的Java基础知识,只为笔记之用] 第一章 对象导论 1.万物皆对象2.程序就是对象的集合3.每个对象都是由其它对象所构成 ...

随机推荐

  1. Web消息推送框架windows部署实践

    一.官方下载地址:https://www.workerman.net/web-sender 二.解压至任意目录下,双击start_for_win.bat,效果如下图: 三.打开Chrome浏览器访问: ...

  2. Java深入学习(1):多线程

    多线程目的:在同一时刻有多条不同路径执行程序,提高程序运行效率 多线程应用:数据库连接池,多线程文件下载等 注意:在文件下载中使用多线程,无法提高速度 在一个进程中,一定会有主线程 从基础开始,多线程 ...

  3. FreeRTOS 任务通知

    可以替代队列.二值信号量.计数型信号量和事件标志组 发送任务通知 获取任务通知 FreeRTOS 任务通知模拟二值信号量 FreeRTOS 任务通知模拟计数型信号量 FreeRTOS 任务通知模拟消息 ...

  4. 12306 抢票项目霸榜 GitHub,标星即将破万

    十一将至,你买到回家的火车票了吗?如果没有,你可以试着打开 GitHub,在搜索栏键入 12306 的关键词,我相信你会发现一个新大陆.没错,这里有 1572 个抢票项目.它们大多用 Python.J ...

  5. YUM方法安装mysql5.7版本

      版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/kabolee/article/deta ...

  6. 第一册:lesson 133.

    原文: Sensational news. question:What reasons did  Karen give for a wanting to retire? Have you just m ...

  7. Python学习日记(四十二) Mysql数据库篇 十

    前言 当我们自己去写SQL代码的时候有时候会因为不熟练会导致效率低,再之后要进行许多的优化,并且操作也较为繁琐.因此ORM框架就能够解决上面的问题,它能根据自身的一些规则来帮助开发者去生成SQL代码. ...

  8. Fedora 安装 MongoDB 教程

    MongoDB 安装 本文原始地址:https://sitoi.cn/posts/37161.html 安装环境 Fedora 29 安装步骤 安装 mongodb 和 mongodb-server ...

  9. .DS_Store文件是什么?Mac系统如何彻底清除该文件?

    用过Mac OS系统的都会注意到一个名为.DS_Store的隐藏文件,尤其是zip格式的压缩包解压的出来,会出现在各种文件夹内,非常烦人! 特别是把文件分享给使用windows的朋友的时候,这些文件会 ...

  10. Flask 开启多进程或多线程

    2018-07-15 23:31:20 yang9315 阅读数 7703更多 分类专栏: python   版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接 ...