JAVA笔记 第五章 继承
第五章 继承
类 超类 子类
对于第四章的 Employee类,经理的办公,工资形式不同,可以创建个新类 Manager,但可以重用Employee中的部分代码,将所有域保留下来。
子类
由继承 E类来定义Manager 类的格式,关键字 extends 表继承,构造的新类派生于一个已存在的类。
定义子类
1 |
|
其中:
已存在的类称为超类 ( superclass)、 基类(base class) 或父类(parent class); 新类称为子类(subclass)、 派生类 (derivedclass) 或孩子类(child class)。 父子类并没有优劣性。
**
1 |
|
tip:Manager类就包括了 Employee的所有实例域和新实例域bonus。
(但是调用超类的私有域,要依照超类的方法或者基于此新建子类方法)——见覆盖方法
一般思路,将通用功能放到超类,特殊用途放到子类。
覆盖方法
修改/覆盖(override) 超类原有的方法
1 |
|
原因:对于超类的私有域,只有超类的方法可以访问,子类的方法无法访问
但子类可以通过借助共有接口(超类方法) 来间接访问
1 |
|
原因:程序认为你调用的是 M类的getSalary 而不是 超类的,就会无限调用自己。
1 |
|
子类构造器
1 |
|
super关键词:*调用超类 含有name—day 参数的构造器 *的简写形式
如果没有显式调用,会默认用超类的。
类似this关键字~
继承层次
继承并不仅限于一个层次。 例如, 可以由 Manager 类派生 Executive 类。由一个公共超类派生出来的所有类的集合被称为继承层次(inheritance hierarchy), 如图 5-1 所示。在继承 层次中, 从某个特定的类到其祖先的路径被称为该类的继承链 (inheritance chain)0
阻止继承
有时候,可能希望阻止人们利用某个类定义子类。不允许扩展的类被称为 final 类。
1 |
|
抽象类
1 |
|
表述为一个抽象的大类
Employee和student在逻辑上都是通过抽象类拓展出来的。
还是不太理解抽象方法(好像在接口中会阐述)
Object
object是所有java类的始祖,每个类都是由他扩展出来的
1 |
|
equals方法
Object 类中的 equals 方法用于检测一个对象是否等于另外一个对象。在 Object 类中,这
个方法将判断两个对象是否具有相同的引用。引用相同,它们是相同
1 |
|
1 |
|
1 |
|
- == 对于引用类型,比较的是两个对象 引用地址的值;对于基本类型,比较的是值
- equals(Object x) 比较的是引用的地址值
- getClass()返回一个对象所属的类 不判断继承关系
- instanceof比较一个对象是否是该类的实例
hashcode方法
散列码( hash code ) 是由对象导出的一个整型值。 散列码是没有规律的。如果 x 和 y 是
两个不同的对象, x.hashCode( ) 与 y.hashCode( ) 基本上不会相同。
由于 hashCode 方法定义在 Object 类中, 因此每个对象都有一个默认的散列码,其值为对象的存储地址。
Equals 与 hashCode 的定义必须一致:如果 x.equals(y) 返回 true, 那么 x.hashCode( ) 就必须与 y.hashCode( ) 具有相同的值。 例如, 如果用定义的 Employee.equals 比较雇员的 ID, 那
么 hashCode 方法就需要散列 ID,而不是雇员的姓名或存储地址。
tostring方法
在 Object 中还有一个重要的方法, 就是 toString 方法, 它用于返回表示对象值的字符
串。
绝大多数(但不是全部)的 toString方法都遵循这样的格式:类的名字,随后是一对方括
号括起来的域值。
eg:boss.toString(): equals.Manager[name=Carl Cracker,salary=80000.0,hireDay=1987-12-15][bonus=5000.0]
泛型数组列表
一般java的数组是静态的,一旦确定大小就很难更改。在 Java 中, 解决这个问题最简单的方法是使用 Java 中另外一个被称为** ArrayList 的类。它使用起来有点像数组,但在添加或删除元素时, 具有自动调节数组容量**的
功能,而不需要为此编写任何代码。
下面声明和构造一个保存 *Employee *对象的数组列表:
ArrayList
或 ArrayList
菱形语法类似 var,自动检查这个变量是什么泛型类型填在<>中。(尖括号的类型参数不能是基本类型)
常见方法
对象包装器与自动装箱
有时, 需要将 int 这样的基本类型转换为对象。 所有的基本类型都冇一个与之对应的类。
这些类称为包装器 ( wrapper **)
这些对象包装器类
拥有很明显的名字:Integer、Long、Float、Double、Short、Byte、Character 、Void 和 **Boolean。 且为final类,无法定义子类
**
自动装箱(autoboxing)和自动拆箱(autowrapping)
细节内容在第八章泛型会讲到,现在先忽视罢
如果想搭一个int的泛型数组,因为<>的限制,可以用Integer类来做
ArrayList
且Integer支持自动装箱和拆包
装箱: list.add(3);编译器自动认识为 list.add (Integer.value0f(3));
拆包:int n = list.get(i); → int n = list.get(i).intValue();
也支持在算术表达中进行这两种操作:
IInteger n = 3; n++;
补充:如果在一个条件表达式中混合使用 Integer 和 Double 类型,** Integer 值就会拆箱,
提升为 double基本类型**, 再装箱为 Double:
Integer n = 1;
Double
x = 2.0;
System.out.println(true ? n : x); // Prints 1.0
参数数量可变的方法
public static double max (double… values)
{
double largest = Double.NECATIVEJNFINITY;
for (double v : values) if (v > largest) largest = v;
return largest;
}
可以像下面这样调用这个方法:
double m = max(3.1, 40.4, -5);
编译器将 new double[ ] {3.1, 40.4,-5} 传递给 max 方法。
反射
能够分析类能力的程序称为反射(reflective )。反射机制的功能极其强大,在下面可以看
到, 反射机制可以用来:
•在运行时分析类的能力。
•在运行时查看对象, 例如, 编写一个 toString 方法供所有类使用。
•实现通用的数组操作代码。
•利用 Method 对象, 这个对象很像中的函数指针
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!