文章目录

  • 第五章 继承
    • 类、超类和子类
      • 定义子类
      • 覆盖方法
      • 子类构造器
      • 多态
      • 阻止继承: `final`类和方法
      • 强制类型转换
      • 抽象类
      • 受保护访问
    • 访问控制修饰符小结
    • `Object`: 所有类的超类
      • `Object`类型的变量
      • `equals`方法
      • 相等测试与继承
      • `hashCode`方法
      • `toString`方法
    • ==泛型数组列表==
      • 声明数组列表
      • 访问数组列表元素
      • 类型化与原始数组列表的兼容性
    • 对象包装器与自动装箱
    • 参数数量可变的方法
    • 枚举类
    • 反射
      • `Class`类
      • 声明异常入门
      • 利用反射分析类的能力
    • 继承的设计技巧

第五章 继承

类、超类和子类

定义子类

  • extend: 该关键字表示继承
public class Manager extends Employee // java中所有的继承都是公共继承
{added methods and fields
}
  • extend: 表示正在构造的类派生于一个已存在的类.这个已存在的类称为超类(基类,父类). 新类称为子类(派生类, 孩子类)
  • 子类比超类拥有更多的功能
  • 设计类: 最一般的类放在超类中, 更特殊的方法放入子类

覆盖方法

  • super: 调用超类方法

    public class Manager extends Employee
    {public double getSalary(){double baseSalary = super.getSalary();return baseSalary + bonus;}
    }
    

子类构造器

  • 由于Manager构造器不能访问Emplyee类的私有字段, 所以通过super来调用初始化这些私有字段

    public Manager(String name, double salary, int year, int month, int day)
    {super(name, salary, year, month, day);//必须放在第一句bonus = 0;
    }
    
  • this: 1. 隐式参数的引用 2. 调用该类的其他构造器

    super: 1. 调用其他超类的方法 2. 调用超类的构造器


多态

  • 多态: 一个变量能够指示多种实际类型的现象
Manager boss = new Manager(...)
Employee[] staff = new Employee[3];
staff[0] = boss;
  • 上面的例子中boss, staff[0]指示同一个对象, 但是编译器只将staff[0]看成一个Emplyee对象
  • 子类引用的数组可以转换成超类引用的数组
Manager[] managers = new Manager[10];
Employee[] staff = managers;
  • 重载解析: 选择所有名字相同的方法中存在一个与提供参数完全相匹配的方法
  • 签名: 方法的名字和参数列表. 返回类型不是签名的一部分
  • 在覆盖一个方法时,子类方法不能低于超类方法的可见性.e.g.: 超类为public, 子类也必须为public

阻止继承: final类和方法

  • final类: 不允许扩展的类, 其中的方法自动设置成为fianl方法, 不包括字段
  • final方法: 子类不能覆盖的方法
  • fianl字段: 构造对象后就不允许改变其值

强制类型转换

  • Manager boss = (Manager) staff[0];

  • Manager boss = (Manager) staff[1]; // ERROR 抛出异常: ClassCastException

  • if (staff[1] instanceof Manager){boss = (Manager) staff[1];....
    }//查看能否强制类型转换成功
    
  • 继承层次: 由一个公共类派生出来所有类的集合

    1. 只能在继承层次类进行强制类型转换
    2. 在将超类强制类型转换为子类之前, 应该用instanceof进行检查

抽象类

  • 位于上层的类更具有一般性,更加抽象

  • 包含一个及以上抽象方法的类必须声明为抽象类

  • public abstract class Person
    {...public abstract String getDescription();
    }
    
  • 抽象类也可以包含字段和具体方法

  • 抽象类不能实例化. new Person("dvsj"); //ERROR

  • 可以定义一个抽象类的对象变量, 引用非抽象子类的对象

Person p = new Student("Alice");
package chapter5_inheritance.abstruct_classes;public abstract class Person {//抽象类public abstract String getDescription();//抽象方法private String name;public Person(String name) {this.name = name;}public String getName() {//抽象类中也可以由方法return name;}
}package chapter5_inheritance.abstruct_classes;public class Student extends Person {private String major;/*** @param name  the student's name* @param major the student's major*/public Student(String name, String major) {super(name); // 继承Personthis.major = major;//隐式参数的引用}public String getDescription() { // 对应抽象类中的抽象方法return "A student major in " + major;}
}package chapter5_inheritance.abstruct_classes;import java.time.LocalDate;public class Employee extends Person
{private double salary;private LocalDate hireDay;public Employee(String name, double salary, int year, int month, int day) {super(name);this.salary = salary;hireDay = LocalDate.of(year, month, day);}public double getSalary() {return salary;}public LocalDate getHireDay() {return hireDay;}public void raiseSalary(double byPercent) {double delta = salary * byPercent / 100;salary += delta;}public String getDescription() {return String.format("An employee with a salary of %.2f", salary);}
}package chapter5_inheritance.abstruct_classes;public class Person_test {public static void main(String[] args) {/* 声明为Person类型 */var people = new Person[2];/* 每一个Person类型的people[i] 声明为对应子类类型 */people[0] = new Student("oukunnan", "Software Engineering");people[1] = new Employee("vfjh", 1500.0, 1259, 5, 12);/* 注意点 类型 参数: 实参数组 */for (Person p : people) {System.out.println(p.getName() + ", " + p.getDescription());}}
}

受保护访问

  • protected: 限制超类中某个方法只允许子类访问, 希望允许子类的方法访问超类的某个字段
  • 保护字段只能由同一个包中的类访问

访问控制修饰符小结

  1. private: 仅对本类可见
  2. public: 对外部完全可见
  3. protected: 对本包和所有子类可见
  4. 无: 对本包可见, 不需要修饰符

Object: 所有类的超类

Object类型的变量

  • 可以使用object类型的变量引用任何类型的对象
Object obj = new Employee("sbjd", 2000);
  • 只能作为各种值的一个泛型容器, 进行具体操作需要强制类型转换
Employee e = (Employee)obj;
  • 只有基本类型不是对象: 数值, 字符, 布尔类型的值

equals方法

  • 该方法确定两个对象的引用是否相等
public boolean equals(Object otherObject) {if (this == otherObject) {return true;}//判引用if (otherObject == null) {return false;}//判空if (getClass() != otherObject.getClass()) {return false;}//判对象所属类是否相等Employee other = (Employee) otherObject;//调用Object.equals()而不是name.equals(other.name)为了防备name, hireDay为null情况return Objects.equals(name, other.name) && salary == other.salary&& Objects.equals(hireDay, other.hireDay);
}
  • 子类中: if(!super.equals(otherObject)) return false; ...

相等测试与继承

  • equals方法要求: 自反性, 对称性, 传递性, 一致性
  • 比较数组元素是否相等, 使用静态方法Arrays.equals
  • @Override标记要覆盖超类的那些子类方法

hashCode方法

  • 散列码: 值由对象的储存地址得出
  • 字符串的散列码时由内容导出的
  • Object.hasCode: null安全的方法
  • Object.hash():组合多个散列值, 这个方法对于各个参数调用Object.hasCode()
  • Arrays.hashCode:数组类型字段计算散列码
  • hasCode, equals方法必须兼容

toString方法

  • x.toString() 等价于 "" + x
  • System.out.println(x)会自动调用x.toString()
  • 对于数组: Arrays.toString, Arrays.deepToString

泛型数组列表

  • ArrayList类: 类似于数组, 在添加或者删除数组元素时可以自动调整数组容量
  • 它是一个有类型参数的泛型类

声明数组列表

  • 以下三种声明方式等价
ArrayList<Employee> staff = new ArrayList<Employee>();
ArrayList<Employee> staff = new ArrayList<>(); // 菱形语法
var staff = new ArrayList<Employee>();
  • add: 将元素添加到列表中
  • ensureCapacity: 确保数组列表在不重新分配内部储存数组的情况下有足够容量储存给定数量的元素
  • trimToSize: 将数组列表的存储容量消减到当前大小
  • size: staff.size() 等价于数组的a.length, 表示实际包含元素个数

访问数组列表元素

  • get: 得到指定索引位置的值
  • set: 重新设置索引位置已经存在的值
  • add(int index, E obj):后移元素从而插入obj到指定位置
  • remov(int index): 删除指定索引位置的元素, 后面的元素前移
  • toArray: 将数组元素拷贝到一个数组中
list.toArray(a); //将数组列表list中的元素拷贝到数组a中

类型化与原始数组列表的兼容性

  • public class EmployeeDB
    {public void update(ArrayList list){...}public ArrayList find(String query) {...}
    
  • 可以将类型化的数组列表传递给update, 不需要强制类型转换

  • 但是原始ArrayList赋给类型化ArrayList会有警告, 强制类型转换也不可以消除警告,会引发类型转换有误的另一个警告

  • @SuppressWarning("unchecked") ArrayList<Employee> result = (ArrayList<Employee>) emplyeeDB.find(x);
    
  • 用以上注解标记问题不太严重的强制类型转换的变量


对象包装器与自动装箱

  • 包装器: 所有的基本类型对应的类(Integer, Double, Long, Float, Short, Byte, Character, Boolean)

  • 包装器类是final, 不能派生子类

  • 尖括号中的类型参数不允许是基本类型, 可以这样var list = new ArrayList<Integer>();

  • 自动装箱:

    list.add(3) --> list.add(Integer.valueOf(3))
    
  • 自动拆箱:

int n = list.get(i); --> list.get(i).intValue();
  • Integer a = 1000;
    Integer b = 1000;
    if (a == b) ..//通常失败
    

    ==运算符比较的是对象是否占有相同的内存位置

  • -128~127之间的short, int被包装到固定的对象中, 上面的比较就会成功


参数数量可变的方法

  • ...: 是Java代码的一部分, 表示这个方法可以接受任意数量的对象

    public class PrintStream
    {public PrintStream printf(String fmt, Object... args){return format(fmt, args);}
    }
    
  • printf方法接受两个参数, 一个是格式化字符串, 另一个是Object[]数组, 其中保存着所有其他参数(整数或者其他基本类型的值会自动装箱为对象), Object...参数类型和Object[]完全一样


枚举类

  • public enum Size { SMALL, MEDIUM, LARGE, EXTRA_LARG};
  • 枚举构造器总是私有的
  • 所有枚举类型都是Enum的子类
  • values: 返回一个包含全部枚举值的数组

反射

  • 反射: 能够分析类能力的程序

Class

  • getClass: 返回类的名字
  • forName: 获得类名对应的Class对象
  • T.class: 代表匹配的类对象
  • Class实际上是泛型类, Employee.class-->Class<Employee>

声明异常入门

  • 处理器处理抛出的异常
  • 异常分为
    1. 非检查型异常
    2. 检查型异常

利用反射分析类的能力

  • java.lang.reflect包中有三个类Field, Method, Constructor分别用于描述类的字段,方法和构造器, 这三个类都有一个gteName方法, 返回其名称
  • Class类中的getFields, getMethods, getConstructors 方法返回这个类支持的公共字段,方法和构造器的数组, 其中包括超类的公共成员
  • Class类中的getDeclaredFields, getDeclareMethods, getDeclaredConstructors 方法返回这个类声明的全部字段,方法和构造器,包括私有成员,包成员,受保护成员,不包括超类成员
package chapter5_inheritance;import java.util.*;
import java.lang.reflect.*;public class reflection {public static void main(String[] args)throws ReflectiveOperationException{// read class name from command line args or user inputString name;if (args.length > 0) name = args[0];else{var in = new Scanner(System.in);System.out.println("Enter class name (e.g. java.util.Date): ");name = in.next();}// print class name and superclass name (if != Object)Class cl = Class.forName(name);Class supercl = cl.getSuperclass();String modifiers = Modifier.toString(cl.getModifiers());if (modifiers.length() > 0) System.out.print(modifiers + " ");System.out.print("class " + name);if (supercl != null && supercl != Object.class) System.out.print(" extends "+ supercl.getName());System.out.print("\n{\n");printConstructors(cl);System.out.println();printMethods(cl);System.out.println();printFields(cl);System.out.println("}");}/*** Prints all constructors of a class* @param cl a class*/public static void printConstructors(Class cl){Constructor[] constructors = cl.getDeclaredConstructors();for (Constructor c : constructors){String name = c.getName();System.out.print("   ");String modifiers = Modifier.toString(c.getModifiers());if (modifiers.length() > 0) System.out.print(modifiers + " ");System.out.print(name + "(");// print parameter typesClass[] paramTypes = c.getParameterTypes();for (int j = 0; j < paramTypes.length; j++){if (j > 0) System.out.print(", ");System.out.print(paramTypes[j].getName());}System.out.println(");");}}/*** Prints all methods of a class* @param cl a class*/public static void printMethods(Class cl){Method[] methods = cl.getDeclaredMethods();for (Method m : methods){Class retType = m.getReturnType();String name = m.getName();System.out.print("   ");// print modifiers, return type and method nameString modifiers = Modifier.toString(m.getModifiers());if (modifiers.length() > 0) System.out.print(modifiers + " ");System.out.print(retType.getName() + " " + name + "(");// print parameter typesClass[] paramTypes = m.getParameterTypes();for (int j = 0; j < paramTypes.length; j++){if (j > 0) System.out.print(", ");System.out.print(paramTypes[j].getName());}System.out.println(");");}}/*** Prints all fields of a class* @param cl a class*/public static void printFields(Class cl){Field[] fields = cl.getDeclaredFields();for (Field f : fields){Class type = f.getType();String name = f.getName();System.out.print("   ");String modifiers = Modifier.toString(f.getModifiers());if (modifiers.length() > 0) System.out.print(modifiers + " ");System.out.println(type.getName() + " " + name + ";");}}
}/*
Enter class name (e.g. java.util.Date):
java.lang.Double
public final class java.lang.Double extends java.lang.Number
{public java.lang.Double(double);public java.lang.Double(java.lang.String);public boolean equals(java.lang.Object);public static java.lang.String toString(double);public java.lang.String toString();public int hashCode();public static int hashCode(double);public static double min(double, double);public static double max(double, double);public static native long doubleToRawLongBits(double);public static long doubleToLongBits(double);public static native double longBitsToDouble(long);public volatile int compareTo(java.lang.Object);public int compareTo(java.lang.Double);public byte byteValue();public short shortValue();public int intValue();public long longValue();public float floatValue();public double doubleValue();public static java.lang.Double valueOf(java.lang.String);public static java.lang.Double valueOf(double);public static java.lang.String toHexString(double);public static int compare(double, double);public static boolean isNaN(double);public boolean isNaN();public static boolean isInfinite(double);public boolean isInfinite();public static boolean isFinite(double);public static double sum(double, double);public static double parseDouble(java.lang.String);public static final double POSITIVE_INFINITY;public static final double NEGATIVE_INFINITY;public static final double NaN;public static final double MAX_VALUE;public static final double MIN_NORMAL;public static final double MIN_VALUE;public static final int MAX_EXPONENT;public static final int MIN_EXPONENT;public static final int SIZE;public static final int BYTES;public static final java.lang.Class TYPE;private final double value;private static final long serialVersionUID;
}
*/

继承的设计技巧

  1. 将公共操作和字段放在超类中
  2. 不要使用受保护的字段
  3. 使用继承实现"is-a"关系
  4. 除非所有继承方法都有意义, 否则不要使用继承
  5. 在覆盖方法时,不要改变预期的行为
  6. 使用多态, 而不要使用类型信息
  7. 不要滥用反射

CoreJava 笔记总结-第五章 继承相关推荐

  1. 《Java 核心技术 卷1》 笔记 第五章 继承(3)

    5.1.6 抽象类 有时候我们无法说出具体是什么,只能用于标识一个类型,比如图形,就可作为抽象类.虽然无法具体描述图形,但是图形通常都有面积.周长.这种时候就可用抽象类标识. 抽象类使用abstrac ...

  2. 机器学习理论《统计学习方法》学习笔记:第五章 决策树

    机器学习理论<统计学习方法>学习笔记:第五章 决策树 决策树 5.1 决策树模型与学习 5.1.1 决策树模型 5.1.2 决策树与if-then规则 5.1.3 决策树与条件概率分布 5 ...

  3. CoreJava 笔记总结-第三章 Java的基本程序设计结构

    CoreJava 笔记总结 文章目录 CoreJava 笔记总结 第三章 Java的基本程序设计结构 数据类型 1. 整型 2. 浮点类型 3. char类型 4. boolean类型 变量与常量 1 ...

  4. 【Python自然语言处理】读书笔记:第五章:分类和标注词汇

    jupyter 版请见我的github:https://github.com/JackKuo666/Python_nlp_notes [Python自然语言处理]读书笔记:第五章:分类和标注词汇 本章 ...

  5. R语言实战笔记--第十五章 处理缺失数据

    R语言实战笔记–第十五章 处理缺失数据 标签(空格分隔): R语言 处理缺失数据 VIM mice 缺失值(NA),是导致我们计算错误的一大来源,处理缺失数据在实际的应用中有着较为重要的作用. 基本方 ...

  6. 概率论与数理统计系列笔记之第五章——统计量及其分布

    概率论与数理统计笔记(第五章--统计量及其分布) 对于统计专业来说,书本知识总有遗忘,翻看教材又太麻烦,于是打算记下笔记与自己的一些思考,主要参考用书是茆诗松老师编写的<概率论与数理统计教程&g ...

  7. 黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第五章 WEB黑客(3)暴力破解目录与文件位置

    黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第五章 WEB黑客(3)暴力破解目录与文件位置 文章目录 黑帽python第二版(Black Hat P ...

  8. Python入门:对Excel数据处理的学习笔记【第五章】列表类型处理技术

    注:该学习笔记是根据曾志贤老师编写的<从Excel到Python,用Python轻松处理Excel数据>所学习整理的笔记. 第五章 列表类型处理技术 列表是Python中最基础的数据结构. ...

  9. 李弘毅机器学习笔记:第五章—分类

    李弘毅机器学习笔记:第五章-分类 例子(神奇宝贝属性预测) 分类概念 神奇宝贝的属性(水.电.草)预测 回归模型 vs 概率模型 回归模型 其他模型(理想替代品) 概率模型实现原理 盒子抽球概率举例 ...

最新文章

  1. C 语言编程 — size_t 的意义与作用
  2. foxmail提示不知道这样的主机_开车上八楼停车场,坡道拐弯会车要这样做,知道了不吃亏...
  3. 计算机网络考试成绩分析报告,成绩分析报告范文_成绩分析总结与反思
  4. php postgresql win,Windows PHP上的PostgreSQL问题
  5. jsp内置对象作业3-application用户注册
  6. java 上文件传示例_Java解压缩文件示例
  7. Javascript 中的map/reduce
  8. 不用登陆QQ也能使用QQ截图工具
  9. STM32之WiFi模块的功能、选型及使用
  10. 基于STM32的RFID射频识别技术 韦根协议C语言驱动解码程序
  11. 【Java面试题】一次完整的Http请求过程(非常详细)
  12. cwber获取html,qq飞车手游CW、CWW、WCW怎么触发方法
  13. Java流程控制:用for循环打印一个三角形
  14. 第05课:Redis 实际应用中的异常场景及其根因分析和解决方案
  15. 浪涌、群脉冲、ESD等级标准
  16. c语言贪心算法找零问题,贪心算法-找零问题-实验报告
  17. (线段树)P5459 [BJOI2016]回转寿司
  18. 确定sw1开关信号输入端口_老电工教大家变频器,怎么接入浮球液位调节信号
  19. 如何把手机证件照压缩到10K?手机怎么压缩照片到10K?
  20. countupjs,一个有趣的数字翻滚动画

热门文章

  1. java之解析DNS的SRV记录
  2. linux之自己总结学习linux的资源推荐
  3. (8)小白又如何?3分钟搞定一个 C# 知识点
  4. python简介及环境安装
  5. encodingaeskey java,消息体签名与加解密-开发者QA
  6. php调用数据库中的图片地址显示不出来,图片显示不出来,但是数据库里有显示...
  7. java多核的利用率_java利用FutureTask、ExecutorService 在多核时代充分利用CPU运算
  8. 一滴水从高处落下来,会不会砸死人?
  9. 拖延的本质是逃避!| 今日最佳
  10. 程序员新人怎样在复杂代码中找 bug?