第七章 复用类(组合和继承)

7.1组合语法

组合:在新类中使用现有类的对象。新类是由现有类的对象所组成的,所以这种方式成为组合

1.对于非基本类型的对象,必须将其引用放置在新类中

toString 当编译器需要我们提供字符串 而我们提供的是对象时,会自动调用对象的toStirng方法

对象初始化的位置:

1.在定义对象的地方   这意味着他们总是能够在构造器被调用之前被初始化

2.在构造器进行初始化

3.在使用对象之前初始化    惰性初始化

4.使用实例初始化

7.2继承语法

当创建一个类时总是在继承,对于java如果我们不指定继承 那么类就继承了Object

extends 意思是延伸     继承就是使用该关键词来描述类间的关系

class A extends B { 

}

这么做时 A将从B拿到所有的域和方法   除了private 修饰的成员或者域 

调用父类中的方法 使用关键词 super     super.scrub();

7.2.1初始化基类

当我们创建子类对象时,该对象就会包含一个基类的对象

这个对象和你直接用基类创建的对象是一样的  差别在于 基类子对象被包含在导出类(子类)对象内部,直接new 出的对象来自于外部

java在初始化导出类对象时,会自动调用基类构造器 来创建子类

public class C {

     public C(){

         Log.e("bac","--c--");

      }

}

public class B  extends C {

     public B(){

         Log.e("bac","--b--");

      }

}

public class A  extends B{

        public A() {

          Log.e("bac", "--a--");

        }

}

我们初始化A a = new A()

打印log如下:  --c--      

                         --b--   

                          --a--

正如打印所看到的  调用构造器 目的就是初始化  当子类对象初始化时 基类对象也进行了初始化

整个过程是从基类“向外”扩散的,所以基类在导出类构造器可以访问前就已经先完成了初始化

a 对象中包含 b 对象

b对象包含 c对象

带参数的构造器

基类


编译器会强制要求 子类构造器必须调用super(int  k),而且要放第一行

7.3代理

代理是继承与组合间的中庸之道 

代理的形式:我们将一个成员对象置于所需构建的类中(组合),但与此同时将新类中暴露该成员对象的所有方法(好像继承似的)

简单的举个例子:


基类c 有自己的各种行为


B继承c将会拥有和c相同的行为,B对象同时会在内部包含c实例
代理将会持有C对象,同时模仿C的行为,但是使用C对象本身来调用这些方法

好处在哪里? 

1.我们可以不停的更换实现功能的类 把C换成B D F 都行 灵活

2.更强的控制力 我们可以屏蔽掉 不需要的方法 只提供C类中部分接口行为 

7.4结合使用组合和集成(略过...)

7.4.1确保正确清理

一般情况下是将垃圾回收交给GC来处理,但是当有特叔情况时,需要自己处理手动释放一些内存,例如我们自己写些释放资源的方法,在finally中释放资源  

但是有一点需要注意 不要使用finalize()方法    在资源释放时一定要注意使用资源的地方的,,,要判断处理 避免出现异常

7.4.2名称屏蔽

java的基类拥有多个重载方法,那么子类中重新定义该方法名称对基类中的方法没有屏蔽效果,毫无影响,重载机制是可以正常工作的

java中一般使用注解 @override 来表示 子类中该方法 重写基类中的相同特征的方法,

添加该注解后 当你重载该方法,而不是重写时,编译器会提示你错误

7.5 在组合与继承之间选择

组合和继承都在新类中添加子类对象

组合显示的放置子类对象并操作

继承隐士的添加子类对象并操作(调用基类的构造器 导出类对象中包含基类对象)

二者的区别在哪里?

组合:如果想在新类中使用现有类的功能,而不是接口,在新类中嵌入某个对象,让其实现新类的功能,由新类提供接口,而不是使用嵌入对象的接口。一般情况下我们会,使用privte修饰的对象

某些情况下,使用public 修饰嵌入对象,也是很方便的,比如 

public class Car{

    public  Engine engine;

      public Car(){

             engine = new Engine;

       }

}

public class  Engine{

public void  start(){}

public void   stop(){}

public void  go(){}

public void  back(){}

}

main(){

      Car  car = new Car();

      car.engine.start();//    这种情况下 看起来代码也很简单明了,                                            有助于客户端程序猿对代码组合的理解

}

其实看是来是这样的:似乎应不应该使用组合很明显,餐馆类 需要厨师类实现功能,但他很显然并不需要厨师接口,他只负责自己的接口  比如 产出菜品的接口

继承:使用一个现有的类,来开发一个特有版本的类,通常意味着使用一个通用类,来根据需要创建一个特殊的类。

is-a关系 是一个...是一种典型的继承关系     

has-a 拥有一个 是典型的组合关系

7.6 protected关键字

1. 控制包访问权限

2.控制子类访问权限

7.7 向上转型

“为新的类提供方法”并不是继承中最关键的一面,更重要的则是一种与基类的关系,简单来说 就是 导出类属于基类类型

将导出类对象指向基类引用 称之为向上转型

7.7.1为什么称为向上转型

传统的类继承图是这样的,所以当导出类或转换成基类是由下向上转化,所以称为向上转型

向上转型是安全的 子类转换成父类,会造成子类特有的方法丢失或特有成员变量的丢失,但不会产生任何不良后果,转换成父类只能使用父类的成员变量与父类接口(只允许子类对象使用继承自父类的接口与成员变量)。

7.7.2 再论组合与继承

类就是一种封装 将数据与方法封装在一起

继承很重要但是并不意味着我们需要常常用他,事实上我们应该更多的使用组合,如何判断是否应该使用继承请参照两个标准

1.是 is-a 关系 还是 has-a关系

2.是否需要向上转型 (如果不需要就没有必要使用)

7.8 final关键字

final 使用在数据前做修饰

用在基本类型前面表明数据的值不必变

一个在运行时被初始化的值,不希望它被改变

final修饰对象引用 对象引用不可变,对象引用不可以在指向其他对象,已经指向的对象本身是可以改变的(对数组同样有效,数组也是对象)

(不管是修饰对象引用还是基本数据类型,都必须要初始化)

空白final

修饰引用或基本数据了类型,但并不初始化,在使用这些引用或者基本类型 必须要在使用前初始化

java允许空白final   (final 修饰成员变量但是并未初始化)

要求必须在使用前进行初始化,在构造方法之前包括构造方法进行初始....

搞清楚初始化的位置

final参数

java允许在参数列表中将参数指明为final  

这意味着参数引用指向的对象将无法修改

这样子的

这种特性主要用来处理匿名内部类的数据传递

7.8.2 final 方法

使用final修饰方法的原因:

1.把方法锁定 防止继承类修改它(final修饰后 将无法重写方法 可以进行重载)

2.提高代码执行效率(在就的jvm中),但是最近看法的jvm中已经不建议这么做了,jvm和编译器会帮你处理效率问题

java早期版本,当编译器发现final来修饰方法时,就会跳过插入代码这种正常方式而执行方法回调机制,并且以方法体中的实际代码的副本来代替方法调用,这将消除方法调用的开销

final和private关键字

类中所有private方法都隐式的指定是final.在private 方法前添加 final是没有额外意义的

private修饰的方法,不属于基类接口逇一部分,他仅仅是隐藏在类中的一部分代码,如果你在导出类中使用 public protected+相同基类private的方法名 其实并没有覆盖private方法,只是产生了一个新方法

final使用在类前面做修饰

将final放在class 前做修饰,表明该类无法进行继承

当类被指定为final 其实隐式的将该类中所有的方法指定为final

7.8.4有关final的忠告

要考虑清楚是否要想使用者提供相应的方法调用,不能太松弛,也不能苛刻

7.9 初始化及类的加载

java中的类的初始化与加载:类的代码在初次使用时才加载的,通常是加载发生于创建类的第一个对象之时,但是当访问static域或static方法时,也会发生加载

这里注意:构造器也是static  只是static关键词没有显示出来,更准确的说,类是在其任何static成员被访问时,加载的

7.9.1继承与初始化

class A extends B{

}

class B extends C{

}

main(){

A  a  =  new A ();

}

类的初始化如下: 加载器开始启动并加载A类的编译代码(A.class),进行加载过程中,发现它还有一个基类(由extends可知),于是就继续进行加载B类的编译代码,不管是否打算产生一个基类对象,这是又发现B类的基类c,于是就开始加载C类的编译代码,根基类的Static初始化被执行,然后是子类的初始化

静态成员初始化以后,类加载完毕,可以生产对象了,对象中的基本类型都被设置为默认值,对象引用设置为null-通过将对象内存设置为二进制的0而生成的,然后构造器别调用,从基类依次到子类。

生成A对象 我们总结写:先加载类的.class编译代码,由于类是导出类,所以加载基类.class,生成Class对象,这个过程中初始化基类的static成员,生成导出类的Class对象,然后是导出类的static成员初始化。接着生成对象,先生成基类对象 即先初始化基类中的成员变量以及对象引用(非static)为默认值,调用构造器方法,然后在生成子类对象,即初始化子类对象的成员变量

基类
子类


打印日志

7.10 总结

组合是将现有类型作为新类型底层实现的一部分加以复用

继承就是依靠现有类来实现一个特殊的现有类,复用现有类的接口

代理是介于继承与组合之间的,利用先用类型来实现,复用的现有类型接口。

在使用是多使用组合和代理 少使用继承

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,567评论 18 399
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,594评论 18 139
  • 我们在行走,前进 挣扎着不愿放弃 然而,现实总是造化弄人 你越想拥有的东西 它偏偏不肯让你如意 于是,终于丢掉了对...
    安木心violet阅读 271评论 0 0
  • 2015年8月,贵州贵安新区成立行政审批局,推出“三个一”(审批一颗章、服务一张网、规范一清单)相对集中行政许可权...
    云上好公仆阅读 113评论 0 0
  • 昨夜听风掠古城,今朝瓦舍雪似尘,千骑万骑不忍驰,闲看落花叠叠沉。
    你是我的小情歌阅读 143评论 0 0