ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

第五章 继承

2022-01-08 10:04:23  阅读:115  来源: 互联网

标签:5.1 数组 继承 子类 int 第五章 超类 方法


目录

5.1 类、超类与子类

5.1.1 定义子类

5.1.2 覆盖方法

5.1.3 子类的构造器

5.1.4 继承层次

5.1.5 多态

5.1.6 阻止继承:final类和方法

5.1.7 强制类型转换

5.1.9 抽象类

5.1.10 受保护访问

5.2 Object:所有类的超类

5.2.1 Object类型的变量

5.2.2 equals方法

5.2.3 相等测试与继承(难)

5.2.4 hashoCde方法

5.2.5 toString方法

5.3 泛型数组列表

5.3.1 声明数组列表

5.3.2 访问数组列表元素

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

5.4 对象包装器与自动装箱

5.5 参数数量可变的方法

5.6 枚举类

5.7 反射

5.7.2 声明异常入门

5.8 继承的设计技巧


5.1 类、超类与子类

5.1.1 定义子类

使用关键字 extends 表示继承

在Java中,所有继承都是公共继承,而没有C++中的私有继承和保护继承

关键字 extends 表明正在构造的新类派生于一个已存在的类,这个已存在的类称为超类、基类或父类;新类称为子类、派苏类或孩子类

通过扩展超类定义子类时,只需要指出子类与超类的不同之处

public class Manager extends Employee{
    priavte double bonus;
    ...
    public void setBonus(double bonus){
        this.bonus = bonus;
}
}

5.1.2 覆盖方法

超类中的有些方法对子类Manager并不一定适用,为此需要一个新的方法来覆盖超类中的这个方法

当我们希望调用超类中的某个方法,而不是子类中的该方法时,可以使用关键字 super 来解决这个问题

super.getSalary();

在子类中可以增加字段、增加方法或覆盖超类的方法,但是继承不会删除任何字段和方法

5.1.3 子类的构造器

public Manager(String name,double salary,int year,int month,int day){
    super(name,salary,year,month,day);
    bonus = 0;
}
//super关键字在这里表示:“调用超类中带有n、s、year、month、day参数的构造器方法”
//由于Manager不能访问Employee的私有字段,所以必须通过调用一个构造器来初始化参数

使用super调用构造器的语句,必须是子类构造器的第一条语句

如果子类的构造器没有显式地调用超类的构造器,将自动地调用超类的无参数构造器

5.1.4 继承层次

Java不像C++那样支持多重继承,但是它提供了接口实现多重继承的功能

5.1.5 多态

is-a规则:可以用来判断是否应该将数据设计为继承关系

  • 子类的每个对象也是超类的对象
  • 程序中出现超类的地方都可以用子类对象替换,可以将子类对象赋给超类对象,反之不行

5.1.6 阻止继承:final类和方法

不允许扩展的类被称为final类,如果在定义类的时候使用了final修饰符就表明了这个类是final类

类中的某个特定方法也可以被声明为final。如果这样做,子类就不能覆盖这个方法(final类中的所有方法自动地成为final类)

将方法或类声明为final的主要原因是:确保它们不会在子类中改变语义

5.1.7 强制类型转换

Manager boss = (Manager)e;

进行强制类型转换的唯一原因是:要在暂时忽视对象的实际类型之后使用对象的全部功能

5.1.9 抽象类

使用 abstract 关键字可以声明一个方法,但是不需要实现它

包含一个或多个抽象方法的类本身必须声明为抽象类

抽象方法充当着占位方法的角色,它们在子类中具体实现。

即使不包含抽象方法,也可以将类声明为抽象类

扩展抽象类可以有两种方法:

1、在子类中保留着抽象类中的部分或所有的抽象方法仍未定义,同时将子类标记为抽象类

2、定义全部的方法

抽象类不能实例化

5.1.10 受保护访问

Java中的四个访问修饰符

  • private:仅对本类可见
  • public:对外部完全可见
  • protected:对本包和所有子类可见
  • 默认,无修饰符:对本包可见

5.2 Object:所有类的超类

Object类是Java中所有类的始祖,在Java中每个类都扩展了Object,但是并不需要显式的写出来

5.2.1 Object类型的变量

可以使用Object类型的变量引用任何类型的变量

在Java中,只有基本类型不是对象;所有的数组类型,不管是对象数组还是基本类型的数组都扩展了Object类

5.2.2 equals方法

Object类中的 equals 方法用于检测一个对象是否等于另外一个对象。Object类中实现的 equals 方法将确定两个对象引用是否相等

在子类中定义 equals 方法时,首先调用超类的 equals。如果检测失败,对象就不可能相等(超类的方法检测两个对象是否属于同一个类)

5.2.3 相等测试与继承(难)

Java语言规范要求 equals 方法具有下面的特性:

  1. 自反性:对于任何非空引用x,x.equals(x)返回true
  2. 对称性:对于任何引用x和y,当且仅当y.equals(x)返回true时,x.equals(y)返回true
  3. 传递性
  4. 一致性:如果x和y引用的对象没有发生变化,反复调用x.equals(y)应该返回同样的结果
  5. 对于任何的非空引用x,x.equals(null)应该返回false
java.util.Arrays;

static boolean equals(xxx[] a,xxx[] b);
//如果两个数组的长度相等,并且对应的位置上的数据元素也相同,则返回true
//数组的元素类型可以是Object,int,long等

java.util.objects

static boolean equals(Object a,Object b);
//如果a和b都是null,返回true;如果只有其中之一为null,则返回false;否则返回a.equals(b)

5.2.4 hashoCde方法

散列码(hash code)是由对象导出的一个整型值。散列码是没有规律的。如果x和y是不同的对象,x.hashCode()与y.hashCode()基本上不会相同

由于hashCode方法定义在Object类中,因此每个对象都有一个默认的散列码,其值由对象的存储地址得出

字符串的散列码由内容导出

数组类型的散列码由数组元素的散列码组成

5.2.5 toString方法

toString方法:返回表示对象值的一个字符串

绝大多数的方法都遵循这样的格式:类的名字,随后是一对方括号括起来的字段值

java.lang.Object;

Class getClass();
//返回包含对象信息的类对象
boolean equals(Object otherObject);
//比较两个对象是否相等,比较内容为对象指向的空间。要在自定义的类中覆盖这个方法
String toString();
//返回表示该对象值的字符串。要在自定义的类中覆盖这个方法

java.lang.Class;

String getName();
//返回这个类的名字
Class getSuperclass();
//以Class对象的形式返回这个类的超类

5.3 泛型数组列表

ArrayList类类似于数组,但在添加或删除元素时,可以自动调整数组容量

5.3.1 声明数组列表

java.util.ArrayList;

ArrayList<E>();  //构造一个空数组列表
ArrayList<E>(int initialCapaity);  //用指定容量构造一个空数组列表
boolean add(E obj);  //在数组列表的末尾追加一个元素,永远返回true
int size();  //返回当前存储在数组列表中的元素个数

void ensureCapacity(int capacity);  
//确保数组列表在不重新分配内部存储数组的情况下,有足够的容量存储给定数量的元素

void trimToSize();  //将数组列表的存储容量削减至当前大小

5.3.2 访问数组列表元素

数组列表自动扩展容器的便利增加了访问元素语法的复杂程度,要使用get和set方法访问或改变数组的元素

java.util.ArrayList;  //以类E为例

E set(int index,E obj);  //将值obj放置在数组列表的指定索引位置,返回之前的内容
E get(int index);  //得到指定索引位置存储的值
void add(int index,E obj);  //后移元素,并将obj插入到指定索引位置
E remove(int index);  //删除位置的元素,并将后面的元素前移。返回删除的元素

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

5.4 对象包装器与自动装箱

所有的基本类型都有一个与之对应的类Ingeter类对应类型int。这些类称为包装器。

包装器是不可变的,一旦构造了包装器,就不允许更改包装在其中的值。同时,包装器类还是final,因此不能派生它的子类。

var list = new ArrayList<Integer>
//声明Integer的数组列表,但是不能使用 ArrayList<int> 进行声明

自动装箱与自动拆箱

  • 包装器类型可以声明为null,所以自动装箱有可能会抛出一个NullPointerException异常
  • 如果在一个表达式中混合使用Integer和Double类型,Integer值会拆箱,提升为double,再装箱为Double
  • 装箱和拆箱是编译器的工作
java.lang.Integer;

int intValue();  //将这个Integer对象的值作为一个int返回(覆盖了Number类中的intValue类)
static String toString(int i);  //返回一个新的String对象,表示指定数值i的十进制表示
static String toString(int i,int radix);  //返回数值i基于radix参数指定进制的表示

static int parseInt(String s);
static int parseInt(String s,int radix);
//返回字符串s表示的整数,指定字符串必须表示一个十进制整数,或者radix参数指定进制的表示

static Integer valueOf(String s);
static Integer valueOf(String s,int radix);
//返回一个新的Integer对象,用字符串s表示的整数初始化。指定的字符串必须表示一个十进制整数,或者radix参数指定进制的表示

java.text.NUmberFormat
Number parse(String s);  //返回数字值,假设给定的String表示的一个数值

5.5 参数数量可变的方法

//来看看printf方法的定义:
public class PrintStream{
    public PrintStream printf(String fmt,Object... args)
    {
        return format(fmt,args);
}
}

这里的省略号“...”是Java代码的一部分,表明这个方法可以接收任意数量的对象(除fmt参数外)

//一个简单的例代码
public static double max(double... values){
    double largest = Double.NEGATIVE_INFINITY;
    for(double v : values)if(v>largest) largest = v;
    return largest;
}

5.6 枚举类

public enum Size { SMALL,MEDIUM,LARGE,EXTRA_LARGE }

这个声明定义的类型为一个类,它刚好有4个实例,不可能构造新的对象

如果需要的话,可以为枚举类型增加构造器、方法和字段

public enum Size{
    SMALL("S"),MEDIUM("M"),LARGE("L"),EXTRA_LARGE("XL");

    private String abbreviation;
    
    private Size(String abbreviation) { this.abbreviation = abbreviation; }
    public String getAbbreviation() { return abbreviation; }
}

枚举的构造器总是私有的,可以省略private修饰符

所有的枚举类型都是Enum类的子类

java.lang.Enum; //假设存在一个枚举类型E
static Enum valueOf(Class enumClass,String name);  //返回给定类中有指定名字的枚举常量
String toString();  //返回枚举常量名
int ordinal();  //返回枚举常量在enum声明中的位置,位置从0开始计数
int compareTo(E other);
//如果枚举常量出现在other之前,返回一个负整数;如果this==other,则返回0;否则返回一个正整数。枚举常量的出现次序在enum声明中给出

5.7 反射

5.7.2 声明异常入门

异常有两种类型:非检查型异常和检查型异常。

对于检查型异常,编译器将会检查你是否知道这个异常并做好准备来处理后果;对于非检查型异常,如越界错误或访问null引用,都属于非检查型异常。

5.8 继承的设计技巧

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

标签:5.1,数组,继承,子类,int,第五章,超类,方法
来源: https://blog.csdn.net/qq_52876054/article/details/122034834

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有