a.extends
表明正在构造的新类派生于一个已存在的类。
b.覆盖方法
子类的getting方法不能够直接的访问超类的私有域。只能借助父类公有的接口。
借助公有接口时,为避免方法冲突,需要用关键字super调用超类方法。
\\eg:
public double getting(){
return super.getting();
}
c.子类构造器
子类构造器不能访问父类的私有域,所欲必须利用父类的构造器对这部分私有域进行初始化。使用super调用构造器的语句必须是子类构造器的第一条语句。
如果子类的构造器没有显式的调用超类的构造器,则将自动地调用超类默认(无参)的构造器。如果此时超类中没有无参的构造器,则将报错。
d.super作用
本类this与超类super使用方法相似,但两者并不相同,this一般作为隐式参数被引用,而super则作为调用超类方法关键字。
e.多态
一个对象变量可以指示多种实际类型的现象被称为多态。
可以将一个子类对象赋给超类变量,但不可以将一个超类的引用赋给子类变量。
子类数组的引用可以转换成超类数组的引用,而不需要采用强制类型转换。
f.动态绑定
在运行时能够自动的选择调用哪个方法的现象称为动态绑定。
-
虚拟机提取对象的实际类型的方法表。
-
虚拟机搜索定义对应方法签名的类。
-
虚拟机调用的方法。
g.方法调用步骤
-
编译器查看对象及其超类的声明类型和方法名。
-
编译器查看调用方法时提供的参数类型。
-
如果是private方法,static方法,final方法或者构造器,编译器实现静态绑定调用。如果调用方法依赖于隐式参数的实际类型,则实现动态绑定调用。
-
当程序运行,并且采用动态绑定调用方法时,虚拟机一定调用与对象所引用的实际类型最合适的那个类的方法。
h.重写
在重写方法是,一定要保证返回类型的兼容性。允许子类将覆盖方法的返回类型定义为原返回类型的子类型。覆盖方法的时候,子类方法不能低于超类方法的可见性。
i.final
不允许扩展的类被称为final类。
-
将方法或类声明为final主要目的:确保它们不会在子类中改变语义。
-
如果一个方法没有被覆盖并且很短,编译器就能够对它进行优化处理,这个过程称为内联。
j.强制类型转换
在暂时忽视对象的实际类型之后,使用对象的全部功能。
-
只能在继承层次内进行类型转换。
-
在将超类转换成子类之前,应该使用 instanceof 进行类型测试。
-
在一般情况下,应该尽量少用类型转换和 instanceof 运算符。
k.抽象类
如果自下而上在类的继承层次结构中上移,位于上层的类更具有通用性,甚至更加抽象。祖先类一般只作为派生其他类的基类,而不作为想使用的特定的实例类。
-
为了提高程序的清晰度,包含一个或多个抽象方法的类本身必须被声明为抽象的。
-
抽象类可以包含具体数据和具体方法,建议尽量将通用的域和方法放在超类中。
-
类即使不含抽象方法,也可以将类声明成抽象类。
-
抽象类不能被实例化,但可以创建一个具体子类的对象。
l.受保护访问 protected
声明允许子类访问的方法和域。影响封装需谨慎使用。
m.所有类的超类:Object
n.equals方法
Object类中的equals方法用于检测一个对象是否等于另外一个对象。
-
这个方法将判断两个对象是否具有相同的引用。如果有,则相等。
-
经常需要检测两个对象状态的相等性,如果两个对象的状态相等,则相等。
为防备对象为null的情况,需要使用 Object.equals 方法。
o.相等测试与继承
equals特性:自反性;对称性;传递性;一致性;对于任意非空引用x,x.equals(null) 应该返回 false。
-
如果子类能够拥有自己的相等概念,则对称性需求将强制采用 getClass 进行检测。
-
如果由超类决定相等的概念,那么可以使用 instanceof 进行检测,这样可以在不同子类的对象之间进行相等的比较。
编写完美equals方法:
-
显式参数命名为 otherObject,稍后需要将它转换成另一个叫做other的变量。
-
检测 this 与 otherObject 是否引用同一个对象:
if(this == otherObject) return true;(优化语句)
-
检测 otherObject 是否为null,如果为null,返回false。
-
比较 this 与 otherObject 是否属于同一个类。
-
如果 equals 的语义在每个子类中有所改变,就使用 getClass 检测: if(getClass() != otherObject.getClass() return false;
-
如果所有的子类都拥有统一的语义,就使用 instanceof 检测:
if(!(otherObject instanceof ClassName)) return false;
-
将 otherObject 转换为相应的类类型变量:
ClassName other = (ClassName) otherObject
-
现在开始对所有需要比较的域进行比较。使用 == 比较基本类型域,使用 equals 比较对象域。如果所有域都匹配,则返回true;否则返回false。
return field1 == other.field1 && Objects.equals(field2, other.field2);
如果在子类中重新定义equals,就要在其中包含调用super.equals(other)。
为了避免发生类型错误,可以使用 @Override 对覆盖超类的方法进行标记。如果出现了错误,并且正在定义一个新方法,就会给出错误报告。
p.hashCode方法
如果重新定义 equals 方法,就必须重新定义 hastCode 方法,以便用户可以将对象插入散列表中。
//法1
public int hastCode(){
return 7 * Objects.hastCode(name)
+ 11 * Double.hastCode(salary) //静态方法避免创建Double对象
+ 13 * Objects.hastCode(hireDay);
}
//法2
public int hastCode(){
return Object.hast(name, salary, hireDay); //散列组合方法
}
Equals 与 hashCode 的定义必须一致:如果 x.equals(y) 返回true,那么 x.hastCode() 与 y.hastCode() 值必须相同。
q.toSring方法
用于返回表示对象值的字符串,是一种非常有用的调试工具。应该给每一个类增加 toString 方法,将子类域的描述加入。
r.泛型数组列表
动态更改数组大小
ArrayList 类是一个采用类型参数的泛型类。声明与构造:ArrayList <classname> name = new ArrayList();
-
add方法:可以将元素添加到数组列表中,如果add时内部数组已经满了,数组列表将自动创建一个更大的数组,并将所有的对象拷贝到此处。
-
如果能够估计可能存储的元素数量,就可以在填充数组之前调用 ensureCapacity() 方法;只是拥有为保存100个元素的潜力。
-
如果确定数组列表大小不再发生变化时,就可以调用 trimToSize 方法,将存储区域的大小调整为当前元素所需要的存储空间数目。
-
不必指出数组的大小
-
使用 add 将任意多的元素添加到数组中
-
使用 size() 代替 length 计算元素的数目
-
使用 a.get(i) 代替 a[i]访问元素
s.参数数量可变的方法
参考 main 方法 public static void main(String...args){}
‘…’ 表明这个方法可以接收任意数量的对象。等同于String[] arg
t.枚举型
避免错误值的输入,比如星期八,十三月份。
enum Size
{
SMALL("S"), MEDIUM("M"), LARGE("L"), EXTRA_LARGE("XL");//枚举值
private Size(String abbreviation) { this.abbreviation = abbreviation;}//构造器构造缩写
public String getAbbreviation() {return abbreviation; }//获取缩写
private String abbreviation;//实现缩写,不实现则无缩写
}
u.继承设计技巧
-
将公共操作和域放在超类
-
不要使用受保护的域
-
用继承实现“is-a”关系
-
除非所有继承的方法都有意义,否则不要使用继承
-
在覆盖方法时,不要改变行为的内涵
-
使用多态,而非类型信息
-
不要过多使用反射