第七章 复用类

第一种方法非常直观:只需在新的类中产生现有类的对象(组合)。

第二种方法更细致一些:它按照现有类的类型来创建新类(继承)。

7.1 组合语法

  只需将对象引用置于新类中即可。

class A{}
class B{
A a = new A();
}

  如果想初始化这些引用,可在下列位置进行:

  1. 在定义对象的地方。
  2. 在类的构造器中。
  3. 在真正使用这些对象之前,惰性初始化。
  4. 使用实例初始化。

7.2 继承语法

当创建一个类时,总是在继承。

  在继承过程中,需要先声明“新类与旧类相似”。在基类名称后紧随关键词extends,当这么做时,会自动得到基类中所有的域和方法。

  为了继承,一般将数据成员指定为private,将方法指定为public(protected成员也可以借助导出类访问)。

  Java使用super关键字表示超类,当前类就是从超类继承来的,如super.scrub()将调用基类(父类)版本的scrub()。

7.2.1 初始化基类

  当创建一个导出类对象,该对象包含了一个基类的子对象。这个字对象与你用基类直接创建的对象是一样的。

  Java会自动在导出类的构造器中插入对基类构造器的调用。

7.3 代理

  代理是继承和组合之家你的中庸之道。将一个成员对象置于所要构造的类中(就像组合),但与此同时我们在新类中暴露了该成员对象所有方法(就像继承)。

class AControls{
void up(){}
void down(){}
}
class B{
AControls a = new AControls();
void up(int i){
a.up(i);
}
void down(int i){
a.down(i);
}
}

7.4 在组合和继承之间选择

  is-a(是一个)的关系用继承来表达。

  has-a(有一个)的关系用组合来表达。

7.5 protected关键字

  就类用户而言,这是private的,但对于任何继承于此类的导出类或其他任何位于同一包内的类来说,它却可以访问。

7.6 向上转型

  “为新的类提供方法”并不是继承最总要的,最重要的方面是用来表现新类和基类之间的关系。这种关系可以用“新类是现有类的一种类型”概括。

class A{
public void play(){}
static void tune(A a){
a.play();
}
}
class B extends A{
public static void main(String[] args){
B b = new B();
A.tune(b); // 向上转型
}

  在tune()中,程序代码可以对A(父类)和他所有的导出类(子类)起作用,这种将B(子)引用转换为A(父)引用的动作,称之为向上转型。

7.6.1 为什么称为向上转型

  由导出类转型为基类,在继承图上是向上移动的,一般称向上转型。由于向上转型是从一个较专用类型向较普通类型转换,所以总是很安全的。

7.6.2 再论组合与继承

  一个最清晰的判断办法就是问一问自己是否需要从新类向基类进行向上转型。如果必须向上转型,则继承是必要的,但如果不需要,则应当考虑是否继承。

7.7 final关键字

7.7.1 final数据

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

  一个既是static又是final的域只占据一段不能被改变的存储空间。

  当对对象引用而不是基本类型运用final时,final使引用恒定不变。一旦引用被初始化指向一个对象,就无法把它改为指向另一个对象,然而,对象其自身却可以修改(指针不能变,对象内存域中的值可以变)。

  不能因为某数据是final就认为在编译时可知的,如果使用随机数初始化在编译时不可知。

空白final

  被声明为final但又未给初始值的域,提高了灵活性,必须在域的定义处或每个构造器中用表达式对final进行赋值。

final参数

  Java允许在参数列表中将参数声明为final,意味着方法中无法更改引用指向。可以读参数,无法修改参数,主要用来向匿名内部类传递数据。

7.7.2 final方法

  1. 锁定方法,防止任何继承类修改它的含义,使方法形为不变,不会被覆盖。
  2. (早期)使用final方法效率高。

final和private关键字

  类中所有的private方法都是隐式地指定为final的。

  这会造成混淆,如果你覆盖一个private方法(隐含final),似乎是奏效的。“覆盖”只有在某方法是基类的接口的一部分时才会出现(能向上转型为基类并调用相同方法)。如果某方法为private,它就不是基类的接口的一部分。如果在导出类中以相同名称生成public、protected或包访问权限方法,此时没有覆盖该方法,仅是生成新方法。由于private无法触及而且有效隐藏,只看成它归属类的组织结构,其他情况不考虑。

7.7.3 final类

  当将某个类定义为final,表明不打算继承该类,且不允许别人这样做。该类设计永不变动,并且不希望它有子类。final类中的方法也是隐式final的,无法覆盖。

7.8 初始化及类的加载

  Java中的所有事物都是对象。每个类的编译文件都存在于它自己的独立文件中。该文件只有需要使用时才被加载。一般来说”类的代码在初次使用时才加载”。

  初次使用指:

  1. 创建类的第一个对象(创建对象调用构造器,构造器也是隐式static,准确的说,类是在任何static成员被访问时加载)。
  2. 访问static域或static方法。

7.8.1 继承与初始化

class A{
private int i = 9;
protected int j;
A(){
System.out.println("i = " + i + ", j = " + j);
j = 39;
}
private static int x1 = printInit("static A.x1 initialized");
static int printInit(String s){
System.out.println(s);
return 47;
}
} class B extends A{
private int k = printInit("B.k initialized");
public B(){
System.out.println("k = " + k);
System.out.println("j = " + j);
}
private static int x2 = printInit("static B.x2 initialized");
public static void main(String[] args){
System.out.println("B constructor");
B b = new B();
}
}

输出

static A.x1 initialized-------------父类静态成员初始化
static B.x2 initialized-------------子类静态成员初始化
B constructor-----------------------子类main(静态)打印语句
//此时声明B b = new B();
父类普通成员初始化i=9
i = 9, j = 0------------------------父类构造器打印语句
父类构造器中初始化j=39
B.k initialized---------------------子类普通成员初始化k=47
k = 47------------------------------子类构造器打印语句
j = 39 子类构造器打印语句

  初始化过程如下:

父类静态-子类静态-父类构造-父类变量-子类构造-子类变量

  1. 在B上运行Java时,发生的第一件事就是试图访问B.main()(一个static方法),于是加载器开始启动并找出B类的编译代码(在名为B.class的文件中)。

  2. 在对B.class加载过程中,编译器注意到B有一个基类A,于是它继续进行加载A。不管你是否打算产生一个该基类对象,这都要发生。

    2.1 如果该基类还有其自身的基类,那么第二个基类被加载,以此类推。

  3. 根基类(A类)中的static初始化被执行。

    3.1 然后是下一个导出类的static初始化,以此类推。

  4. 到此为止,必要的类都已加载完毕,对象可以被创建。

    4.1 首先,基类(A类)对象所有的基本类型都被设为默认值,对象引用设为null。

    4.2 基类(A类)构造器被调用。

    4.3 基类(A类)构造器和导出类(B类)构造器一样,以相同顺序执行。

    4.4 在基类构造器完成之后,实例变量按照其次续被初始化。

    4.5 最后构造器的其余部分被执行。

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

  1. Java编程思想第七章复用类

    7.1组合语法 在一个类中引入多个对象,以提高代码的复用性与功能. 7.2继承语法 使用继承子类可以获得,导出类可以获得基类的成员(变量与方法). 注:这里注意权限控制,若基类中的成员为默认权限,只有 ...

  2. Java编程思想——第17章 容器深入研究 读书笔记(三)

    七.队列 排队,先进先出. 除并发应用外Queue只有两个实现:LinkedList,PriorityQueue.他们的差异在于排序而非性能. 一些常用方法: 继承自Collection的方法: ad ...

  3. Java编程思想——第17章 容器深入研究(two)

    六.队列 排队,先进先出.除并发应用外Queue只有两个实现:LinkedList,PriorityQueue.他们的差异在于排序而非性能. 一些常用方法: 继承自Collection的方法: add ...

  4. Java编程思想 第21章 并发

    这是在2013年的笔记整理.现在重新拿出来,放在网上,重新总结下. 两种基本的线程实现方式 以及中断 package thread; /** * * @author zjf * @create_tim ...

  5. java编程思想笔记(第一章)

    Alan Kay 第一个定义了面向对象的语言 1.万物皆对象 2.程序是对象的集合,他们彼此通过发送消息来调用对方. 3.每个对象都拥有由其他对象所构成的存储 4.每个对象都拥有其类型(TYpe) 5 ...

  6. 《Java编程思想》笔记 第七章 复用类

    1.组合 将其他类的对象引用置于新的类中. 3.继承 extends 从已知的一个类中派生出新的一个类,叫子类.子类实现了父类所有 非私有化 非静态 的属性和方法,并能根据自己的实际需求扩展出新的行为 ...

  7. 《java编程思想》P125-P140(第七章复用类部分)

    1.类的成员默认的是包访问权限.允许包内成员访问 2.super.scrub() 调用基类的scrub方法 3.继承并不是复制基类的接口.当创建了一个导出类(子类)对象时,该对象包含了一个基类的子对象 ...

  8. 初读"Thinking in Java"读书笔记之第七章 --- 复用类

    组合语法 将对象引用置于新类中,即形成类的组合. 引用初始化方法 在定义处初始化. 在类的构造器中初始化. 在使用这些对象之前,进行"惰性初始化". 使用实例初始化. 继承语法 J ...

  9. Java编程思想学习(七) 抽象类和接口

    1.抽象类和抽象方法 抽象方法:不完整的,仅有声明而没有方法体. abstract void f(); 抽象类:包含抽象方法的类.(若一个类包含一个或多个抽象方法,则该类必须限定为抽象的.) 1.用抽 ...

随机推荐

  1. Solution -「CF 510E」Fox And Dinner

    \(\mathcal{Description}\)   Link.   给定正整数集合 \(\{a_n\}\),求一种把这些数放置在任意多个圆环上的方案,使得每个环的大小大于 \(2\) 且环上相邻两 ...

  2. Hive之同比环比的计算

    Hive系列文章 Hive表的基本操作 Hive中的集合数据类型 Hive动态分区详解 hive中orc格式表的数据导入 Java通过jdbc连接hive 通过HiveServer2访问Hive Sp ...

  3. 【第二十四期】golang 一年经验开发 富途

    他们家是按题目来的,从一个小题目慢慢延伸着问,由浅入深,问到你换题为止. 第一题 给了一个网址,解释一下浏览器填入这个网址后发生了什么? TCP为什么要三次握手四次挥手? 502是什么? 如果出现50 ...

  4. 继承及super关键字

    继承 继承的本质是对某一批类的抽象,从而实现对世界更好的建模 extend的意思是"扩展",子类是父类的扩展. Java中类只有单继承,没有多继承:儿子只能有一个亲生爸爸,一个爸爸 ...

  5. log4j的替换方案

    去年12月份,随着log4j暴露出高危漏洞,对于 Java 开发人员来说不是一个好消息,对于 Ops 来说更是如此.前者必须使用固定的 Log4J 版本重新打包他们的应用程序,而后者必须重新部署.但对 ...

  6. [题解]USACO 5.2.1 Snail Trails

    链接:http://cerberus.delos.com:791/usacoprob2?S=snail&a=uzElkgTaI9d 描述:有障碍的棋盘上的搜索,求从左上角出发最多经过多少个格子 ...

  7. pycharm创建模板

    用pycharm构造作者模板 模板,就是创建一个文件时自动生成模板内容. 这里用pycharm创建作者模板,步骤如下: File-->Settings Editor-->File and ...

  8. Linux:査看文件的详细信息

    Linux中stat是査看文件详细信息的命令. 1.命令格式: stat [选项] 文件名/目录名 2.选项: -f:査看文件所在文件系统信息,而不是査看文件信息. 3. 案例 案例1:査看文件的详细 ...

  9. HDFS的优缺点

    HDFS是一个分布式文件存储系统,前身来自于Google发布的大数据三驾马车之一GFS (Google File System). HDFS的优点: 1.高容错 hdfs具有很高的容错性,数据自动保存 ...

  10. C# 题目

    题目 http://blog.zhaojie.me/2011/03/my-interview-questions-for-dotnet-programmers.html 1.考察对常量和自读字段 初始 ...