本章重点:

  • 继承
  • 多态与动态绑定
  • Object类
  • 对象包装器&自动打包

继承

涉及到的概念:
超类(superclass)、子类(subclass)
extends关键字
super关键字
多态(polymorphism)、动态绑定(dynamic binding)

重点:

  1. 如果子类的构造器没有显式调用超类的构造器,则自动调用超类默认构造器; 如果超类没有不带参数的构造器,并且子类的构造器中又没有显式地调用超类的其他构造器,则将报告错误.
  2. super关键字: 一是调用超类的方法,二是调用超类的构造器.
  3. polymorphism: 一个对象变量可以引用多种实际类型的现象.
  4. dynamic binding: 在运行时能够自动地选择调用哪个方法的现象. Java中dynamic binding是默认的处理方式, 除非用final标记.

继承层次

Java 不支持多继承. 采用 单继承+接口.


polymorphism & dynamic binding

polymorphism

多态示例:

Employee e;
e = new Employee(...); // Employee object expected
e = new Manager(...);  // OK, Manager can be used as wellEmployee[] staff = new Employee[3];
Manager boss = new Manager(...);
staff[0] = boss;  // OKManager m = staff[i];  // ERROR

WARN

package corejava.inheritance;/*** Created by guolong.fan on 15/4/21.*/
public class ArrayStoreExceptionTest {public static void main(String[] args) {Integer[] ints = new Integer[10];ints[0] = 10;Object[] objs = ints;        // OK!objs[0] = new Object();System.out.println(ints[0]);}} /**Exception in thread "main" java.lang.ArrayStoreException: java.lang.Object at corejava.inheritance.ArrayStoreExceptionTest.main(ArrayStoreExceptionTest.java:12)*/

dynamic binding

调用对象方法的执行过程:

  1. 编译器查看对象的声明类型和方法名。比如方法f,编译器会一一列举类中及其超类中的所有访问权限为public且名为f的方法。
  2. 编译器查看调用方法时提供的参数类型,这个过程是overloading resolution。首先寻找参数完全匹配的方法,找到直接选择;次之,选择可以转化与之匹配的方法,没有的话,编译
    如果找到参数类型完全匹配,直接选择;次之,没有则选择可以转换与之匹配的方法;
  3. private、static、final方法,编译器可以准确地知道调用哪个方法,即静态绑定(static binding)。
  4. dynamic binding的原理是JVM预先给每个类创建了一个方法表(method table).

小细节:

  • Java SE5.0开始支持协变。

final类和 final方法

final类可以阻止继承,final方法不可override.

强制转换与 instanceof

强制转换:

double x = 3.405;
int nx = (int)x; // 1. OKEmployee staff = new Manager(...);
Manager boss = (Manager) staff;  // 2. OK

继承链进行向下转换,Java运行时系统运行下面的程序,会产生ClassCastException异常.

Employee staff = new Employee(...);
Manager boss = (Manager) staff;  // ERROR

总结:

  1. 只能在继承层次内进行类型转换,尽量避免强制转换.
  2. 如有必要,在将超类转换为子类前,应该使用instanceof进行检查.
if (staff instanceof Manager) {boss = (Manager) staff;...
}

Object类

Object类是 Java 中所有类的最终祖先. 在 Java 中只有基本类型不是对象.

equals 方法

典型的equals方法的写法:

// super class
class Employee {...@Overridepublic boolean equals(Object otherObject) {// 1. a quick test to see if the objects are identicalif (this == otherObject) return true;// 2. must return false if the explicit parameter is nullif (otherObject == null) return false;// 3.1 if the classes don't match, they can't be equalif (getClass() != otherObject.getClass()) {return false;}// or 3.2 如果所有的子类都拥有统一的语义,则使用instanceof检测.if (!(otherObject instanceof ClassName)) return false;// 4. now we know otherObject is a non-null EmployeeEmployee other = (Employee) otherObject;// 5. test whether the fields have identical valuesreturn name.equals(other.name)&& salary == other.salary&& hireDay.equals(other.hireDay);}
}// sub class
Class Manager extends Employee {...@Overridepublic boolean equals(Object otherObject) {if (!super.equals(otherObject)) return false;// super.equals checked that this and otherObject belong to the same classManager other = (Manager) otherObject;// test whether the fields have identical values in subclassreturn bonus = other.bonus;}
}

hashCode 方法

Object 类中的 hashCode 默认实现是对象的存储地址. 当一个类重新定义了 equals 方法时,就必须重新定义 hashCode 方法, 且 equals 与 hashCode 的定义必须保持一致.

class Employee {public int hashCode() {return 7 * name.hashCode +11 * new Double(salary).hashCode +13 * hireDay.hashCode();}...
}

如果存在数组类型的域,可以使用静态的 Arrays.hashCode 计算 hash,这个散列码由数组元素的散列码组成.

toString 方法

典型写法:

public class Employee {public String toString() {return getClass().getName()+ "[name=" + name+ ",salary=" + salary + ",hireDay=" + hireDay+ "]";}...
}public Manager extends Employee {public String toString() {return super.toString()+ "[bonus=" + bonus+ "]";}
}

x.toString()"" + x 等价. Object 类的 toString()className@hashCode.

int[] luckyNumbers = {2, 3, 5, 7, 11, 13};
String s = "" + luckyNumbers;  // [I@hashCode// 打印单维数组
String s = Arrays.toString(luckyNumbers); // "[2,3,5,7,11,13]"
// 打印多维数组
String s = Arrays.deepToString(luckyNumbers); 

对象包装器&自动打包

  1. Java 的基本类型都有与之对应的包装器(wrapper).
  2. Wrapper 是 final 类,并且是不可变的(即一单生成对象,对象本身不可变).
  3. Java 泛型不支持 基本类型,可以使用 wrapper.
  4. autoboxing & autounboxing 是编译器行为,而不是 JVM. 编译器通过添加相关代码得以实现(new Integer(), Integer.intValue()).
  5. String->Integer(int x = Integer.parseInt(s));

下列情况不会发生 unboxing.

Integer a = 1000;
Integer b = 1000;
if (a == b) ... // may equal, 自动打包要求 boolean、byte、char<=127, 介于-128~127的short和int被包装到固定的对象中.

因为 Java 中基本类型是不可变的,所以要求 wrapper 也是不可变的.

public static void triple(int x) { // won't workx = 3 * x;
}public static void triple(Integer x) { // won't workx = 3 * x; // 因为 Integer 对象是不可变的.
}

Integer.parseInt 与 Integer.valueOf 的区别:

public static int parseInt(java.lang.String s, int i) throws java.lang.NumberFormatException { /* compiled code */ }public static int parseInt(java.lang.String s) throws java.lang.NumberFormatException { /* compiled code */ }public static java.lang.Integer valueOf(java.lang.String s, int i) throws java.lang.NumberFormatException { /* compiled code */ }public static java.lang.Integer valueOf(java.lang.String s) throws java.lang.NumberFormatException { /* compiled code */ }

继承设计的技巧

  1. 将公共操作和域放在超类.
  2. 不要使用受保护的域.
  3. 使用继承实现 "is-a" relation.
  4. 除非所有继承的方法都有意义,否则不要使用继承.
  5. 在override时不要改变预期的行为.
  6. 使用多态, 而非类型信息(避免类型判断),是代码更加易于扩展.

转载于:https://www.cnblogs.com/nil2inf/p/4469213.html

Core Java笔记 2.继承相关推荐

  1. (十)Core Java 面向对象(封装,继承,多态,接口) -02 (96)

     目录 :        24 ). 面向对象(聚集关系) 25 ). 面向对象(子父类中变量的特点) 26 ). 面向对象(子父类中函数的特点-覆盖) 27 ).  面向对象(子父类中构造函数的特点 ...

  2. 【java笔记】继承

    继承:基于已有的类创建新的类,使新的类复用或已有类的字段和方法,并增加或覆盖一些新的方法(字段). 父类/基类/超类:已有的类 子类:继承的类 定义:extends public class B ex ...

  3. Core Java笔记------来自达内项目经理穆笛

      前言 1 一·基础知识 二·定义,关键字和类型 三·表达式和控制流 四·数组 五·对象和类 六·高级语言特性 七·异常 八·图形用户接口 九·AWT(Abstract Window Toolkit ...

  4. java笔记_继承(八)

    8.1继承概述 class Student{String name;int age;void study(){System.out.println("Study...");} } ...

  5. Core Java笔记 6.部署应用程序

    本章重点: JAR 文件 Java Resource 应用程序的配置 JAR 文件 JAR 可以将 Java 应用程序打包,JAR 文件可以包含类文件,也可以包含资源文件. JAR 文件采用 ZIP ...

  6. 【java笔记】继承与多态

    多态性的前提:extends继承或者implements实现 继承与多态: 定义:同一个操作被不同类型对象调用时可能产生不同 的行为 解释:如果一个类有很多子类,并且这些子类都重写了父类中的某个方法, ...

  7. [读书笔记]Core Java: Volume I - Fundamentals Chapter 8

    Title: Core Java - Volume I Fundamentals Edition: Eleventh Edition Author: Cay S. Horstmann 读书笔记:对原书 ...

  8. Core Java 8 读书笔记-Networking编程

    Core Java 8 读书笔记-Networking编程 作者:老九-技术大黍 原文:Core Java 8th Edition 社交:知乎 公众号:老九学堂(新人有惊喜) 特别声明:原创不易,未经 ...

  9. [读书笔记]Core Java: Volume I - Fundamentals Chapter 1

    Title: Core Java - Volume I Fundamentals Edition: Eleventh Edition Author: Cay S. Horstmann 文章目录 Pre ...

最新文章

  1. python-pcl GPU、输入输出模块教程翻译
  2. 杠上Spark、Flink?Kafka为何转型流数据平台
  3. android如何根据机顶盒区分用户,Android 上手机跟机顶盒应用开发的区别
  4. XML文档类型定义DTD
  5. 虚拟机 centos 6.5 扩展根目录分区大小
  6. 因果推断 - 基础知识
  7. 用 JavaScript 的方式理解递归
  8. go-plugin入门
  9. 保存ResultSet中的数据(Java Source Code)
  10. 谜底是计算机的谜语英语,英语谜语(Riddle)  谜底
  11. Codeforces Round #280 (Div. 2) D. Vanya and Computer Game 二分
  12. linux maven安装与入门
  13. 《神经网络与深度学习》课程笔记(2)-- 神经网络基础之逻辑回归
  14. 7限制cpu使用_macOS限制CPU或进程使用率
  15. 才意识到自己“奇葩”的360,会不会有些晚?
  16. 利用Cydia Substrate Hook移动MM支付
  17. 类和对象7:构造和析构方法
  18. 笔记-中项/高项学习期间的错题笔记1
  19. 新星计划、原力计划新动态,大波的奖牌来袭速来领取
  20. 用for循环输出俄文的“字母表”

热门文章

  1. Java学习笔记之:Java JDBC
  2. SQL注入—我是如何一步步攻破一家互联网公司的
  3. winform下载网页源码
  4. NET中winform与webform互相通讯实例,CS调用BS页面的JS函数---转载
  5. hibernate插入DB时间
  6. eclipse 插件开发过程中遇到的一堆问题(急待解决)
  7. android 怎么加链接地址,Android TextView添加超链接的方法示例
  8. Ubuntu 11.10更新源地址列表更改方法及下载
  9. Windows下使用gvim
  10. 计算机到计算机 临时网络,电脑如何设置临时网络