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 初始化及类的加载
在对导出类进行加载时,会先对基类进行加载。如果该基类还有自身的基类,那么第二个基类就会被加载。
Java编程思想之七复用类的更多相关文章
- Java编程思想(四) —— 复用类
看了老罗罗升阳的专訪,不由自主地佩服,非常年轻,我之前以为和罗永浩一个级别的年龄.也是见过的不是初高中编程的一位大牛之中的一个,专訪之后.发现老罗也是一步一个脚印的人. 别说什么难做,做不了.你根本就 ...
- Java编程思想学习笔记——类的访问权限
类的访问权限 Java中,访问权限修饰词用于确定库中哪些类对于该库的使用者是可用的. public class Foo{ } 注意点: 每个文件(编译单元)只能有一个public类. public类的 ...
- Java编程思想:File类list()方法
import java.util.regex.Pattern; import java.io.File; import java.io.FilenameFilter; public class Tes ...
- Java编程思想:File类其他方法
import java.io.File; public class Test { public static void main(String[] args) { MakeDirectories.te ...
- Java编程思想:嵌套类
public class Test { public static void main(String[] args) { // Parcell11.test(); // ClassInterface. ...
- Java编程思想:File类getCanonicalFile()方法,listFile()方法
import java.io.IOException; import java.util.*; import java.util.regex.Pattern; import java.io.File; ...
- java编程思想-复用类总结
今天继续读<java 编程思想>,读到了复用类一章,看到总结写的很好,现贴上来,给大家分享. 继承和组合都能从现有类型生成新类型.组合一般是将现有类型作为新类型底层实现的一部分来加以复用, ...
- 33.JAVA编程思想——JAVA IO File类
33.JAVA编程思想--JAVA IO File类 RandomAccessFile用于包括了已知长度记录的文件.以便我们能用 seek()从一条记录移至还有一条:然后读取或改动那些记录. 各记录的 ...
- Java编程思想 (1~10)
[注:此博客旨在从<Java编程思想>这本书的目录结构上来检验自己的Java基础知识,只为笔记之用] 第一章 对象导论 1.万物皆对象2.程序就是对象的集合3.每个对象都是由其它对象所构成 ...
随机推荐
- Python 之 计算psnr和ssim值
基于python版的PSNR和ssim值计算 总所周知,图像质量评价的常用指标有PSNR和SSIM等,本博文是基于python版的图像numpy的float64格式和uint8格式计算两种指标值(附代 ...
- Unity手游汉化笔记③:UABE替换BMFont
总的笔记:https://www.cnblogs.com/guobaoxu/p/12055930.html 目录 一.Demo 二.分析思路 三.替换 四.总结 五.补充 工具: Unity版本:20 ...
- Python 常用语句
条件语句 a=input("请输入数字a的值:\n") a=int(a) #从控制台接收到的都是字符串类型,需要转换 if a==0: #也可以写成if(a==0): print( ...
- k8s的常用命令(一)
常用的kubectl命令 kubectl run kubia --image=luksa/kubia --port=8080 --generator=run/v1 --image 指定镜像 - ...
- 攻防世界WEB高手进阶之blgdel
CISCN final 打开页面 扫描目录 Robots.txt Config.txt 代码审计 <?php class master { private $path; private $nam ...
- Linux必知必会--sed
致沅弟:至于当大事,全在明强二字. --<曾国藩家书> 参考资料:https://man.linuxde.net/sed https://www.jianshu.com/p/047cd ...
- web api .net C# mvc API返回XML文档的解析并取值
[HttpGet] public System.Net.Http.HttpResponseMessage GetNotify() { var xmlstring = @" <xml&g ...
- windows命令查看端口占用情况
打开cmd 查看端口占用情况:netstat -aon 查看PID对应的进程:tasklist /FI "PID eq 16948"
- *Bootstrap系列 - (1)概述
参考 [1] v3.bootcss.com
- Is Safari on iOS 6 caching $.ajax results? post Cache
https://stackoverflow.com/questions/12506897/is-safari-on-ios-6-caching-ajax-results Since the upgra ...