复用类

复用代码是Java众多引人注目的功能之一。但想要成为极具革命性的语言,仅仅能够复制代码并对之加以改变是不够的,它还必须能够做更多的事情。

组合语法

将现有类的对象的引用置于新类中。被视为“has-a”(拥有)关系。如果是动态发生称为“聚合”。

在使用对像的引用前必须要赋值

  1. 在定义对象的地方。
  2. 在类的构造器中。
  3. 就在正要使用对象这前,称为“惰性初始化”。
  4. 使用实例初始化(块语句)

继承语句

  1. 关键字extends。子类继承父类,子类继承了父类的所有域和方法(尽管是prviate,但不能访问)
  2. Java中规定,创建一个类除非已经明确指出要从其他类中继承,否则就会隐式地从Java的标准根类Object进行继承。
  3. Java中规定要求继承只能是单根继承,即一个子类只能有一个父类(基类,超类),一个类可以有多个子类。
  4. 如果子类(导出类)只覆盖基类的方法,即导出类和基类是完全相同的类型,因为他们具有完全相同的接口(方法),能接受的所有的消息都是一样的。结果可以用导出类对象来完全代替基类对像,这种被视为纯粹替代,通常称为替代原则。在某种意义上这是一种处理继承的理想方法。这种情况下的基类和导出类之间的关系称为“is-a”(是一个)。如果在导出类中添加了新的方法,即可以发给导出类的对象的消息就不一定能够发给基类的对象了,这种情况下我们可以描述为“is-like-a”(像一个)关系
  • 基类初始化

当创建一个导出类的对象时,该对象包含一个基类的子对象。这个子对像与你用基类直接创建的对象是一样的。二者区别在于,后者来自外部,而基类来自子对象的被包装在导出类对象的内部。

对基类的子对象正确初始化也是至关重要的,而且也仅有一种方法来保证这一点:在构造器中调用基类构造器来执行初始化,而基类构造器具有执行基类初始化所需要的所有知识和能力。Java会自动在导出类的构造器中插入对基类构造器的调用。

class Art{
	 Art(){
 		print("Art constructor");
 	}
}

class Drawing entends Art{
	 Drawing(){
 		print("Drawing constructor");
 	}
}

public class Cartoon entends Drawing{
	 Cartoon(){
 		print("Cartoon constructor");
 	}
 	 
 	 pubilc static void main(String[] args){
 		 Cartoon x = new Cartoon();
 	 }
}

//log
Art constructor
Drawing constructor
Cartoon constructor

可以发现,构建过程是从基类“向外”扩散的,所以基类是在导出类构造器可以访问它之前,就已经完成了初始化。

当基类没有默认构造器时,需要在导出类中显性的调用基类的构造方法,并传入相应的参数列表。使用super关键字,表示超类的意思。

class Art{
	 Art(int i){
 		print("Art constructor");
 	}
}

class Drawing entends Art{
	 Drawing(){
	 	super(1); // 显性的调用基类的构造方法
 		print("Drawing constructor");
 	}
}

通过super关键字调用基类的构造方法的代码语句必须在导出类的构造方法中,并放在第一句。

  • 方法覆盖
  1. 方法名、方法参数列表的类型和顺序,返回值类型相同或是基类方法返回值类型的导出类(协变返回类型
  2. 要覆写基类的方法,可以用注解@Override来明确标示是重写基类的方法,利用编译器来帮忙做检查。
  3. 方法覆盖,重写后的方法的访问权限不能小于基类的。(pubilc-protected-包访问权限-private)否则编译错误不通过。private修饰的方法是不能被重写的。
  4. 在导出类中定义了与父类方法同名的方法,如果不满足重写,则这是导出类的一个新的方法,不会屏蔽基类的方法。
  • 向上转型
    将导出类的对象的引用赋值给基类类型的变量引用。这种转型是安全的,因为基类的接口不可能比导出类的接口更窄,即能发送给导出类的对象的消息都可以发送给基类的对象的消息。

  • 初始化顺序

当基类和导出类中有静态子句和非静态子句实例来初始化变量时,他们的初始化顺序为:

  1. 基类的静态子句(多个时按定义顺序)- 导出类的静态子句(多个时按定义顺序)。这执行一下,虚拟机第一次加载类的时候。
  2. 当基类和导出类的所有静态子句都执行完后在到基类的非静态子句(多个时按定义顺序)- 导出类的非静态子句(多个时按定义顺序)。
  • 清理
    清理顺序和变量定义的相反,先导出类再到基类。

组合与继承的选择

在复用类的时候选择组合还是继承?可以根据自己的需要来问自己,我需要将一个对象向上转型吗?如果需要,则使用继承,如果不需要则使用组合。在想要向上转型时反复问自己,真的需要向上转型吗?

关键字final

  • final数据
  1. 编译时常量。只能是基本数据类型,并在定义时已经明确赋值并知道具体的值。
  2. 一个在运行时被初始化的值,而你不希望它被改变。
  3. final用作基本数据类型时表示值不能改变。
  4. final用作对象引用时表示不能把另外一个对象的引用赋值给它,即它不能“放弃”原来关联的对象而去关联别的对象。但对像的数据时可以改变的。
  5. final说明的是它是一个常量,static强调的时只有一份。所以一个即为static又为fianl的的域只占据一段不能改变的存储空间。
  6. 空白final:是指被声明为final但又为给定初始值的域。但无论什么情况,编译器都确保空白final在使用前必须被初始化。
    例 private final int i ;
  7. final参数,方法的参数被定义为final,说明方法只能访问该参数的值不能修改改参数变量的值。
  • final方法
  1. 方法使用fina的是想把方法锁定,以防任何继承类修改它的含义(通过覆盖,即final不能被覆盖重写)
  2. 类中所有private的方法都隐式的指定为final的。导出类由于无法取用private的方法,所以也就无法覆盖它
  • final类
  1. 将类声明为final的,表明了该类是最终类,即没有子类,所以不能有任何类继承他。
  2. final类的域可以根据个人的意愿来选择是不是为final,不论类是否被定义为final相同的规则都适用于定义为final的域。
  3. final类是被禁止继承的,所以类的所有方法都隐式指定为final的,因为无法覆盖他们
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值