第七章 复用类

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

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

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. 2、网络并发编程--套接字编程、黏包问题、struct模块、制作简易报头、上传文件数据

    昨日内容回顾 面向对象复习(json序列化类) 对象.类.父类的概念 三大特性:封装 继承 多态 双下开头的方法(达到某个条件自动触发) __init__:对象实例化自动触发 __str__:对象执行 ...

  2. [LeetCode]4.寻找两个正序数组的中位数(Java)

    原题地址: median-of-two-sorted-arrays 题目描述: 示例 1: 输入:nums1 = [1,3], nums2 = [2] 输出:2.00000 解释:合并数组 = [1, ...

  3. k8s-ingress增加跨域问题

    第一种: kubectl get ingresses. -n rrzhibo-admin test-rrzb-apiadmin-gateway-http-ingress -o yaml apiVers ...

  4. PostgreSQL VACUUM 之深入浅出 (四)

    VACUUM 参数优化 上面已经介绍过了以下设置表级 AUTOVACUUM 相关参数和 autovacuum_max_workers: ALTER TABLE pgbench_accounts SET ...

  5. Stroke

    // A simple blur shader, weighted on alphauniform sampler2D texture;void main(){    float radius = 0 ...

  6. [题解]RQNOJ PID85 三个袋子

    链接:http://www.rqnoj.cn/problem/85 思路:一个排列问题,递推式很简单,f(n+1)=3*f(n)-1 ,由此可以推出通项公式,f(n)=0.5*3^(n-1)+0.5 ...

  7. RFC2889错误帧过滤测试----网络测试仪实操

    一.简介 RFC 2889为LAN交换设备的基准测试提供了方法学,它将RFC 2544中为网络互联设备基准测试所定义的方法学扩展到了交换设备,提供了交换机转发性能(Forwarding Perform ...

  8. 技术管理进阶——为什么Leader的话有时候你听不懂

    原创不易,求分享.求一键三连 Hi,各位亲爱的小伙伴,小钗公号遵循日复盘->周复盘->月复盘->季度复盘->年总结策略,所以某类型文章到后期才会成体系. 今天这篇文章属于「月复 ...

  9. tunneling socket could not be established, cause=connect ECONNREFUSED 127.0.0.1:56281 npm ERR! network This is most likely not a problem with npm itself npm ERR! network and is related to network

    tunneling socket could not be established, cause=connect ECONNREFUSED 127.0.0.1:56281npm ERR! networ ...

  10. P4-可编程语言代码学习

    (1).behavioral-model 简称bmv2 P4程序首先经过p4c-bm模块编译成JSON格式的配置文件,然后将配置文件载入到bmv2中,转化成能实现交换机功能的数据结构. behavio ...