博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
读书笔记 | 《Think in Java》Ⅶ 复用类
阅读量:6992 次
发布时间:2019-06-27

本文共 2117 字,大约阅读时间需要 7 分钟。

Ⅶ 复用类

复用代码是Java众多引人注目的功能之一,Java的代码复用都是围绕类来展开的。所以很多时候,不需要重复去造轮子,而是可以直接调试使用他人写好的类库框架。当然,在现阶段,自己动手才是最好的学习方式。

Java的代码复用方式主要有两种:

  1. 组合:在新的类中产生现有类的对象。
  2. 继承:通过现有的类型来创建新类。

7.1 组合语法

  • 在前文关于初始化的部分中提到,Java类钟域为基本数据类型时能自动初始化某默认值(具体可以去查表),对象引用默认会被初始化为null。 其实编译器并不是简单地为每一个引用都创建默认对象,因为这样的好处是可以减轻某些不必要的负担与开销。如果明确想要初始化这些引用,可以在以下几个位置进行:
  1. 在定义对象的地方,这将在调用构造器之前被初始化。
class Wheel{  private String type;  Wheel{}{  }//Class Car{  private Wheel w=new Wheel();}}复制代码
  1. 在类的构造器中。
class Wheel{  private String type;  Wheel{}{  }//Class Car{  private Wheel w;  Car (){    this.w=new Wheel();  }`}}复制代码
  1. 在需要使用到这些对象时,这种被称为惰性初始化。

7.2 继承语法

  • 在子类中完全可以使用基类中的方法并对它进行修改。假如基类中有个方法叫take(),你想要在子类的take()方法中不对基类方法进行修改,那么不能直接在子类的take()中调用take(),因为这会产生递归。而是需要在子类的take()super.take()

7.3 代理

  • 代理是介于继承和组合中间的一种方式,Java没有对其直接支持。代理是什么意思? 比如我们把一个成员对象置于所要构建的新类中(组合),但是需要在新类中暴露这个对象的所有方法(继承)(不适合使用继承的另一个原因是也往往违背了is-a关系)。

  • 实际用法是需要在新类中再次对这个对象的方法进行封装描述,这有点麻烦,但是好处是使用代理时可以获得多个对象得不同能力,而且也可以取其子集。

7.4 结合使用组合和继承

  • 有时记得进行必要的清理,在清理时注意对基类清理方法和对成员对象清理方法的调用顺序,其顺序应该和生成对象的顺序相反。

  • 大多数情况下,清理不是问题,仅仅交给垃圾回收器来做就行了。但有必要时,需要我们手动处理。最好的办法是除内存以外,不要依赖垃圾回收器做其他清理工作。当需要进行必要的清理时,编写你自己的方法,但不要使用前文提到的finalize()

  • 相较于继承,组合方式往往更常用,尽管在学习OOP时,我们强调继承这一概念。那么到底什么情况下使用继承?一个比较好的方法是,考虑在工程中,是否有需要从新类向基类进行向上转型。如果必须向上转型,那么继承是必要的。

7.7 向上转型

  • 向上转型是一个专用的类型向通用类型转换,所以总是很安全的。在向上转型的过程中,类接口中可能发生的情况是丢失方法。

7.8 final关键字

在不同的上下文环境中,final有着细微的区别,它通常是来表示“不可改变的”,当然也存在着特殊的情况。

final一般有三种使用场景:数据、方法、类。

7.8.1 数据
  • 编译期常量,是使用final修饰的基本数据类型,在定义时必须进行赋值。这是一种使数据恒定不变的方式。

  • 在使用 final修饰一个引用时,final使引用固定地指向一个对象,但是这个对象本身是可以修改的。

  • final修饰的数据并不代表我们在编译期就可以知道它的值。比如:

static Random rand=new Random(10);final int a=rand.nextInt(10);复制代码
  • 值得一提的是,还可以用final来修饰方法参数,当一个参数被final修饰后,意味着在这个方法中,无法改变参数引用所指向的对象了。
7.8.2 方法
  • final方法的用处有两个:
  1. 锁定方法,防止在继承类中被重写。(这是出于一些情况的设计,需要确保在继承中此被继承方法的功能不变)
  2. 过去使用final修饰方法可能是出于效率的考量,但是现在并不是很需要。(如果将一个方法指明为final,就是同意编译器将针对该方法的所有调用都转为内嵌调用。在后续版本中这样效率反而降低,已经不需要了。)
  • 所有的private方法其实都是隐式地被指定为final。如果你试图去覆盖一个private方法,似乎是奏效的,因为编译器没有报错,但实际是不对的,可以编写代码来测试。这里就不演示了。 覆盖只有在子类中某方法是基类的接口的一部分时才会出现。private修饰的方法,不会是基类接口的一部分。
7.8.3 类
  • 使用final修饰的类无法被继承。当然,其中的方法也无法被覆盖。

7.10 总结

  • 继承和组合都能从现有类型生成新类型。组合一般是将现有类型作为新类型底层实现的一部分来加以复用,继承复用的是接口。

  • 子类拥有父类接口,所以可以向上转型,这对多态来说至关重要。


小白的成长探索之路。

转载地址:http://ygbvl.baihongyu.com/

你可能感兴趣的文章
规范化-数据库设计原则
查看>>
HTML5语音输入(淘宝语音搜索)方法
查看>>
很兴奋的一刻!
查看>>
容易搞混的JavaScript方法:typeof和instanceof
查看>>
C# 文件重命名的处理方法
查看>>
C#索引器-索引器和属性的区别
查看>>
重启开源,分享无限--微软面试187题精选[转]
查看>>
NYOJ 60 谁获得了最高奖学金
查看>>
Atitit.java jna 调用c c++ dll的原理与实践 总结 v2 q27
查看>>
SpringMVC进行文件的上传以及多文件的上传(转)
查看>>
iOS 推送,当接到推送消息时如何处理?
查看>>
$(window).load(function(){})跟$(document).ready(function(){})跟$(function(){})区别
查看>>
neutron 同一虚拟网卡的多个IP设置
查看>>
springboot 配置多数据源 good
查看>>
Leetcode: Intersection of Two Arrays II
查看>>
监听套接字不可写?
查看>>
QueenPuzzle-N皇后问题
查看>>
衣服吊牌标签的秘密你懂吗?
查看>>
FastFel解析一个公式的步骤
查看>>
修复/lib/ld-linux.so.2: bad ELF interpreter: No such file or directory问题
查看>>