Java核心技术 第五章 继承

继承的基本思想是可以基于已有的类创建新的类;
反射是指在程序运行期间更多的了解类及其属性的能力;

5.1 类,超类和子类

  1. is-a关系是继承的一个明显特征;
  2. 关键字extends表示继承;
public class Manager extends Employee
{
	added methods and fields
	}
  1. Java中所有的继承都是公共继承;
  2. 可以使用super关键字调用超类方法;
  3. 由于子类不能访问超类的私有字段,但可以通过特殊语法super()来调用构造器初始化这些私有字段,super()调用构造器语句必须是子类构造器的第一条语句。
  4. 子类没有显示调用超类构造器,将自动调用超类的无参构造器,子类没有显式调用又没有无参构造器JAVA编译器就会会报错;
  5. 一个对象变量可以指示多种实际类型的现象称为多态
  6. 在运行时能够自动的选择适当的方法,称为动态绑定
  7. 由一个公共超类派生出来的所有类的集合称为继承层次;继承层次中从某个特定的类到其祖先的路径称为该类的继承链
  8. is-a规则的另一种表述是替换原则,他指出程序中出现超类对象的任何地方都可以使用子类对象替换;
  9. 不能将超类的应用赋值给子类对象;“不是所有的员工都是经理”;
  10. java中子类引用的数组可以转换成超类引用的数组,而不需要使用强制类型转换;
  11. 再覆盖一个方法的时候,子类方法不能低于超类方法的可见性;
  12. 不允许扩展的类称为final类;final类中的方法自动称为final,不包括字段。
  13. 类中的方法被声明为final,子类就不能覆盖这个方法;
  14. 进行强制类型转换的唯一原因是:要在暂时忽视对象的实际类型之后使用对象的全部功能;
  15. 一个良好的程序设计习惯:在进行强制类型转换之前先查看是否能够成功的转换;
if (staff[1]) instanof Manger)
{
 boss =(Manger) staff[1];
 ...
 }
  • 只能在继承层次内进行强制转换;
  • 在将超类强制转换成子类之前,应该使用instanceof进行检查;
  • 一般境况下最好尽量少用强制类型转换和instanceof

5.1.9 抽象类

  1. 包含一个或多个抽象方法的类本身必须被声明为抽象的 abstract
  2. 抽象方法充当着占位方法的角色,他们在子类中具体实现;
  3. 扩展抽象类可以有两种选择,一种是在子类中保留抽象类中部分或所有方法仍未定义,这样就必须将子类也标记为抽象类;另一种是定义全部方法,这样子类就不是抽象类了。
  4. 抽象类不能实例化;
  5. 可以定义一个抽象类的实例变量,但只能引用非抽象子类的对象;
  6. 如果省略超类中的抽象方法,只在子类中定义方法,就不能使用超类变量调用子类方法;

5.1.10 受保护访问

  1. 最好将类中的字段标记为private,而方法标记为public
  2. 限制超类中的某个方法只允许子类访问,或者希望允许子类的方法访问超类的某个字段,可以声明为protected
  3. 保护字段只能由同一个包中的类访问;

Object:所有类的超类

  1. 如果没有明确的指出超类,object就被认为是这个类的超类;
  2. 可以使用object类型的变量引用任何类型的对象;但是要想对对象进行具体的操作,还需要清楚对象的原始类型,并进行相应的强制类型转换;
  3. 在java中只有基本类型不是对象;
  4. object类中的equals方法通过确定两个对象引用是否相等来检测一个对象是否等于另一个对象;
  5. equals方法要求具有以下特性:1.自反性;2.对称性;3.传递性;4.一致性;5.对于任何非空引用x,xequals(null)应该返回false
  6. 如果隐式和显示的参数不属于同一个类,equals方法将如何处理呢?
  • 如果子类可以有自己的相等性概念,则对称性需求将强制使用getclass检测;
  • 如果由超类决定相等性需求。那么就可以使用instanceof检测,这样可以哦在不同子类的对象之间进行相等性比较。
  1. 编写一个完美的equals方法的建议;
    1. 显示参数命名为otherObject,稍后需将他强制转换为另一个名为other的变量;
    2. 检测thisotherObject是否相等:if (this==otherObject) return true;
    3. 检测otherObject是否为null,如果为null,返回false。这项检测是很有必要的:if (otherObject==null) return false ;
    4. 比较thisotherObject的类。如果equals语义可以在子类中改变,就使用getClass检测;如果所有子类都有i相同的相等性语义,可以使用instanceof检测;
    5. otherObject强制转换为相印类型的变量;ClassName other=(Classname)otherObject
    6. 现在根据相等性概念要求来比较字段,基本类型用==,对象字段用object.equals,如果在子类重新定义equals,就要在其中包含一个super.equals(other)调用;
  2. hashCode方法: **散列码(hash Code)**是有对象导出的一个整型值,不同对象基本上不会相同;
  3. equalshashCode定义必须相容:如果x.equals(y)返回true,那么x.hashcode()y.hashcode()返回相同的值;
  4. toString方法:返回表示对象值的一个字符串,设计子类的程序员应该定义自己的toString方法,并加入子类的字段 ;

5.3 泛型数组列表

  1. java允许运行时确定数组大小;
  2. ArrayList是一个有类型参数的泛型类,为了指定数组列表保存的元素对象的类型,需要用一对尖括号将类名括起来追加到ArrayList后面;
  3. 在java 10中可以用var关键字以避免重复写类名;
  4. 如果没有使用var关键字,可以省去右边的类型参数,这称为菱形语法
  5. 使用add方法可以将元素添加到数组列表中;如果调用add方法而内部数组已经满了,数组列表会自动创建一个更大的数组,并将所有对象拷贝到较大数组中;
  6. 如果已经知道或能够估计出数组可能储存的元素数量,就可以在填充数组之前调用ensureCapacity方法,节省开销;这与分配一个新数组不同;
  7. size方法将返回数组列表中包含的实际元素个数;
  8. 一旦能确定数组列表大小保持恒定不再变化,就可以调用trimToSize方法,将储存块的容量调整为当前所需储存空间,垃圾回收器将回收多余存储空间;确认不变时在调用,以免增大开销;
  9. ArrayList是一个实用工具类,访问和改变数组元素需用getset方法;

5.4对象包装器和自动装箱

  1. 所有的基本类型都有一个与之对应的类,通常这些类被称为包装器
  2. 包装器类是不可可变的,包装器还是final,因此不能派生他们的子类;
  3. 尖括号中的参数不允许是基本类型;
  4. 由于每个值分别包装在对象中,所以ArraryList<>效率远低于[];
  5. 装箱拆箱编译器要做的工作;

5.5参数数量可变的方法

  1. 可以提供参数数量可变的方法,有时称为“变参”方法;
  2. 省略号...是javaj代码的一部分,它表明和这个方法可以接受任意数量的对象,对于printf的实现者来说,Object...参数类型和Object[]完全一样;

5.6枚举类

5.7 反射

  1. 能够分析类能力的程序称为反射
  2. java运行时系统始终为所有对象维护一个运行时类型标识,这个信息会跟踪每个对象所属的类,虚拟机利用运行时类型信息选择要执行的正确的方法;可以使用一个特殊的类访问这些信息Class类;
  3. Object类中的getClass()方法将返回一个Class类型的实例;
  4. 一个Class对象实际上表示的是一个类型,可这能是类,也可能不是类。例如,int不是类,但int.class是一个Class类型的对象。
  5. 虚拟机为每一个类型管理一个唯一的Class对象,因此,可以利用==运算符实现两个类对象的比较;
  6. 还可以使用静态方法forName获得类名对应的Class对象:
String className=" java.util.Random";
Class cl=Class.forName(className);
  1. 如果有一个Class类型的对象,可以用他来构造类的实例。调用getConstructor方法将得到一个Constructor类型的对象,然后使用一个newInstance方法来构造一个实例;如果这个类没有无参数构造器,getConstructor方法会抛出一个异常。
var className ="java.util.Random";
Class cl=Class.forName(className);
Object obj=cl.getConstructor().newInstance();

5.7.2声明异常入门

  1. 异常有两种类型:非检查型异常和检查型异常;
  2. 如果一个方法包含一条可能抛出检查型异常的语句,则在方法名前增加一个throws子句;
  3. 只要你调用了一个可能抛出检查型异常的方法而没有提供相应的异常处理器,编译器就会报错;

5.7.4利用反射分析类的能力

  1. java.lang.reflect包中有三个类FieldMethodConstructor分别用于描述类的字段,方法和构造器。
  2. 详情见代码ReflectionTest.java

5.7.5使用反射在运行时分析对象

  1. 利用反射机制可以查看在编译时还不知道的对象字段;利用Field类中的get方法
  2. 只能对可以访问的字段使用getset方法;
  3. 反射机制的默认行为受限于Java的访问控制,不过可以调用Field,Method,Constructor,对象的setAaccessible方法覆盖java的访问控制;f.setAccessible(true)

5.7.6使用反射编写泛型数组代码

5.7.7调用任意方法和构造器

  1. 建议仅在绝对必要的时候才在你自己的程序中使用Method对象。

5.8 继承的设计技巧

  1. 将公共操作和字段放在超类中;
  2. 不要使用受保护的字段;
  3. 使用继承实现is-a关系;
  4. 除非所有继承的方法都有意义,否则不要使用继承;
  5. 在覆盖方法时不要改变预期的行为;
  6. 使用多态而不用使用类型信息;
  7. 不要滥用反射;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MightKai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值