CoreJava 笔记总结-第五章 继承

文章目录

  • 第五章 继承
    • 类、超类和子类
      • 定义子类
      • 覆盖方法
      • 子类构造器
      • 多态
      • 阻止继承: `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. 不要滥用反射

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/311386.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WTM系列视频教程:WebApi

文字摘要&#xff1a;“今天跟大家聊聊WTM中的WebApi&#xff0c;WebApi直接继承Controller Base&#xff0c; 他实际上比普通的Controller要更简单&#xff0c;流程更短&#xff0c;因为它不需要处理关于界面的问题。”“实际上如果我们使用普通Controller返回Json&#xff0c…

《C++ Primer》2.1.3节练习

#include <iostream> using namespace std;int main() {cout << "2\x4d\012";cout << "2\tM\n";return 0; }//\x4d输出M //\012输出换行 //\t输出制表符

CoreJava 笔记总结-第六章 接口、lambda表达式与内部类

文章目录第六章 接口、lambda表达式与内部类接口接口的概念接口的属性接口与抽象类静态和私有方法默认方法解决默认方法冲突接口与回调Comparator接口对象克隆lambda表达式函数式接口方法引用构造器引用变量作用域处理lambda表达式再谈Comparator类内部类使用内部类访问对象的状…

【复杂系统迁移 .NET Core平台系列】之静态文件

源宝导读&#xff1a;微软跨平台技术框架—.NET Core已经日趋成熟&#xff0c;已经具备了支撑大型系统稳定运行的条件。本文将介绍明源云ERP平台从.NET Framework向.NET Core迁移过程中的实践经验。一、背景随着ERP的产品线越来越多&#xff0c;业务关联也日益复杂&#xff0c;…

[Abp vNext 源码分析] - 19. 多租户

一、简介ABP vNext 原生支持多租户体系&#xff0c;可以让开发人员快速地基于框架开发 SaaS 系统。ABP vNext 实现多租户的思路也非常简单&#xff0c;通过一个 TenantId 来分割各个租户的数据&#xff0c;并且在查询的时候使用统一的全局过滤器(类似于软删除)来筛选数据。关于…

HTMLCSS 超简单的前端设计入门-2!

文章目录图片元素img元素和a元素连用和map元素和figure元素多媒体元素videoaudio列表元素有序列表无序列表定义列表容器元素div元素语义化容器元素元素包含关系为网页添加样式CSS术语解释选择器声明块CSS代码书写位置常见样式声明选择器简单选择器选择器的组合选择器的并列层叠…

八数码问题I-bfs和map标记

解题思路&#xff1a; bfs&#xff0c;将棋盘转化成一个整数表示其状态&#xff0c;比如我们到到达的状态是815736402&#xff0c;而样例给的输入状态是264137058&#xff0c;因为这些整数过大&#xff0c;标记数组开不下&#xff0c;所以可以用map来代替数组&#xff0c;写得时…

一个迷你ASP.NET Core框架的实现(下)

【框架内幕】| 作者 / Edison Zhou这是恰童鞋骚年的第196篇原创文章上一篇我们了解了AspNetCore.Mini这个项目的背景及项目结构和流程&#xff0c;这一篇我们继续解析几个核心对象。本文整理自A大&#xff08;蒋金楠&#xff09;的主题分享&#xff0c;点击本文底部“阅读原文”…

CoreJava 笔记总结-第七章 异常,断言和日志

文章目录第七章 异常,断言和日志处理错误异常的分类声明检查型异常如何抛出异常创建异常类捕获异常捕获单个异常捕获多个异常再次抛出异常和异常链finally子句try-with-Resource语句分析堆栈轨迹元素使用异常的技巧使用断言使用断言完成参数检查日志基本日志高级日志调试技巧第…

根据后序和中序求二叉树的先序

代码如下&#xff1a; #include <iostream> using namespace std; const int N 1010; int in_order[N], post_order[N], lch[N], rch[N];int build(int inL, int inR, int postL, int postR) {if (inL > inR)return 0;int root post_order[postR];int k inL;while…

CoreJava 笔记总结-第九章 集合

第九章 集合 文章目录第九章 集合Java集合框架集合接口与实现分离Collection接口迭代器泛型实用方法集合框架中的接口具体集合链表数组列表散列集树集优先队列映射映射的基本操作更新映射条目映射视图弱散列试图链接散列集与映射枚举集与映射标识散列映射视图与包装器小集合子范…

30多岁程序员老W,无奈选择转行!问题出在哪?

作者&#xff1a;邹溪源&#xff0c;长沙资深互联网从业者&#xff0c;架构师社区特邀嘉宾&#xff01;一有一天&#xff0c;一位同事跟我说&#xff1a;老w已经改行做美缝去了&#xff0c;你怎么看&#xff1f;我想了想&#xff0c;说&#xff1a;他大概终于做出了眼下最符合他…

一维前缀和

代码如下&#xff1a; #include <iostream> using namespace std; const int N 1010; int a[N], s[N];int main() {int n;cin >> n;for (int i 1; i < n; i) {cin >> a[i];//原数组s[i] s[i - 1] a[i];}for (int i 1; i < n; i)cout << s[…

HttpClientFactory的套路,你知多少?

背景ASP.NET Core 在 2.1 之后推出了具有弹性 HTTP 请求能力的 HttpClient 工厂类 HttpClientFactory。替换的初衷还是简单摆一下&#xff1a;① using(var client new HttpClient()) 调用的 Dispose() 方法并不会立即释放底层 Socket 连接&#xff0c;新建 Socket 需要时间&a…

CoreJava 笔记总结-第十二章 并发-1

第十二章 并发 线程 package chapter12_concurrent.threads;public class ThreadsTest {public static final int DELAY 10;public static final int STEPS 100;public static final double MAX_AMOUNT 1000;public static void main(String[] args) {var bank new Bank(…

走迷宫-双向bfs解法

双向bfs适用于知道起点和终点的状态下使用&#xff0c;从起点和终点两个方向开始进行搜索&#xff0c;可以非常大的提高单个bfs的搜索效率同样&#xff0c;实现也是通过队列的方式&#xff0c;可以设置两个队列&#xff0c;一个队列保存从起点开始搜索的状态&#xff0c;另一个…

.NET Core开发实战(第16课:选项数据热更新:让服务感知配置的变化)--学习笔记...

16 | 选项数据热更新&#xff1a;让服务感知配置的变化选项框架还有两个关键类型&#xff1a;1、IOptionsMonitor2、IOptionsSnapshot场景&#xff1a;1、范围作用域类型使用 IOptinsSnapshot2、单例服务使用 IOptionsMonitor通过代码更新选项&#xff1a;IPostConfigureOption…

CoreJava 笔记总结-第十二章 并发-2

文章目录第十二章 并发synchronized关键字同步块监视器概念volatile字段final变量原子性死锁线程安全的集合阻塞队列映射条目的原子更新对并发散列映射的批操作并行数组算法同步包装器任务和线程池Callable, FutureExecutor执行器fork-in框架异步计算可完成Future组合可完成Fut…

八数码问题II-bfs和map标记

问题描述&#xff1a; 在33的棋盘上&#xff0c;摆有八个棋子&#xff0c;每个棋子上标有1至8的某一数字。棋盘中留有一个空格&#xff0c;空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是&#xff1a; 给出一种初始布局&#xff08;初始状态&#xff09;和目标布…

华为任职资格_看了华为的任职资格体系,你就明白员工为啥这么拼?

提到华为的18万奋斗者&#xff0c;职场上没人不竖起大拇指。而优秀人才的背后&#xff0c;就像任正非曾说过的那样&#xff0c;华为的成功&#xff0c;很大意义上讲就是人力资源的成功。华为的人力资源管理最有代表性的&#xff0c;除了狼性文化和薪酬绩效外&#xff0c;就是任…