子类对象的方法不能直接访问超类的私有域,尽管每个子类对象都拥有这个私有域,但是在子类的方法中却不能直接访问这个域。只有超类的方法才能够访问私有部分。如果子类一定要访问父类私有域,就必须借助共有的接口。调用超类的方法,如果这个方法在子类中也有,那就必须用super。子类用可以增加自己的部分,覆盖超类的部分方法,但是绝对不能删除继承的任何域和方法。
使用super调用超类构造器的语句必须是子类构造器的第一局话。如果子类的构造器没有现实的调用超类的构造器,那么系统自动的调用超类默认的构造器,就是没有参数的那个构造器,如果超类没有不带参数的构造器,并且在子类的构造器中又没有显示的调用超类的其他构造器,那么编译器就会提示错误。
一个对象变量可以引用多种实际类型的现象被称为多态,在运行时能够自动的选择调用哪个方法的现象叫做动态绑定。方法的名字和参数列表成为方法的签名,不过返回类型不是签名的一部分,在覆盖方法的时候,一定要保证返回类型的兼容性。现在允许子类将覆盖方法的返回类型定义为原返回类型的子类型。
在覆盖一个方法的时候,子类方法不能低于超类方法的可见性。特别是父类方法是public,那么子类方法一定要声明为public。
阻止继承要用 final类和方法。域也可以声明为final,对于final域来说,构造对象之后就不允许改变他们的值了。不过如果将类声明为final,只有其中的方法自动的成为final,而不包括域。
抽象类
public abstract String getDescription();加上abstract就不需要实现这个方法了,包含一个或多个抽象方法的类本身必须声明为抽象的。抽象方法起着占位的作用,他们的具体实现在子类中。扩展抽象类有两种选择,1 在子类中定义部分抽象方法或者抽象方法也不定义,这样就必须把子类也定义为抽象类,2,是定义全部抽象方法,这样一来子类就不是抽象的了。类即使不含抽象方法,也可以将类声明为抽象类。除了抽象方法外,抽象类还可以包含具体数据和具体方法。抽象类不能被实例化。但是可以定义一个抽象类对象,不过他只能引用它的非抽象子类的对象。由于不能构造抽象类的对象,所以抽象类变量引用的永远不是抽象类对象,而是引用的一个非抽象子类的对象,而在这些对象里面的方法一定都是具体的了。
归纳一下JAVA用于控制可见性的4个访问修饰符
private 只对本类可见
protect 对本包和所有子类可见
默认是对本包可见
public 对所有类可见。
Equals方法
在子类中定义equals方法是,首先调用超类的equals方法,如果检测失败,对象就不可能相等,如果超类中的域都相等,然后就需要比较子类中的实例域。
如果子类能够拥有自己的相等的概念,则对称性需求将强制采用getClass进行检测。
如果超类决定相等的概念,那么就可以使用instanceof进行检测,这样可以在不同子类的对象之间进行相等的比较。
编写完美的equals方法的建议
1. 显式参数命名为otherObject,稍后需要将它转换成另一个叫做other的变量。
2.检测this与ohterObject是否引用同一对象,if(this==otherObject) return TRUE; 这条语句只是一个优化,实际上,这是一种经常采用的形式,因为计算这个等式要比一个一个的比较类中的域要付出的代价小得多。
3.检测otherObject是否为null,如果为null,返回FALSE,这项检测是很必要的。 if(otherObject==null) return FALSE
4.检测this与otherobject是否属于同一类,如果equals得语义在每个子类中有所改变,就用getcLASS检测, if(getClass()!=otherobjec.getClass()) return false
如果所有的子类都拥有同一的语义,就是用InstanceOf 检测,if(!(otherObject instanceOf ClassName)) return false
5.将otherObject转换为相应的类类型变量, ClassName other = (ClassName)otherObject
6.现在开始对所有需要比较的域进行比较。使用==比较基本类型域,使用equals比较对象域,如果所有的域都匹配,就返回TRUE,否则就FALSE
如果在子类中重新定义equals就要在其中包含调用super.equals(other)
对于数组类型的域,可以使用静态的Arrays.equals方法检测相应的数组元素是否相等。
hashCode方法定义在object中,因此每个对象都有一个默认的散列吗,其值为对象的储存地址。
如果重新定义equals方法,就必须重新定义hashcode方法,以便用户可以将对象插入到散列列表中。equals必须和hashcode定义一致,如果equals返回TRUE,那么那么两个对象的hashcode就必须具有相同的值。如果存在数组类型的域,就可以使用静态的arrays.hascode方法计算一个散列吗,这个散列码有数组元素的散列吗组成。
Object的equals方法是比较两个对象是否相等,如果两个对象指向同一块存储区域,方法返回TRUE,否则方法返回FALSE,在自定义类中应该覆盖这个方法
object的clone方法是创建一个对象的副本,为新实例分配存储空间,并将当前的对象复制到这个存储区域中区。
对象包装器类是不可变的,即一旦构造了包装器,就不允许改变其中的值。而且还是final类,不允许有子类。
可变参数数量
方法指针
Method类中有一个invoke方法,允许调用包装在当前Method对象中的方法。class中的getMethod方法要给出方法名字,已经想查找方法的参数类型。
对象的克隆是创建一个新对象,且新对象的状态与原始对象的状态相同,对克隆的新对象进行修改时,不会影响原始对象的状态。
接口绝对不能含有实例域也不能在接口中实现方法,静态方法也不能有,但是可以有常量和静态域。提供实例域和实现方法的任务应该在实现接口的那个类来完成。
instanceof也可以检查这个对象是否实现了一个接口。接口中的方法自动的被设置为public一样,接口中的域将被自动设置为public static final
默认的克隆是浅拷贝,就是对象里面的基本类型域可以被拷贝,但是如果对象里面还有对象引用的话,那么克隆后的新对象里面的对象引用跟原来对象里面的对象引用是指向同一个地址的。也就是没有克隆包含在对象中的内部对象。
即使clone的默认实现能够满足需求,也应该实现cloneable接口,将clone重新定义为public,之前是保护的,并调用super.clone(),下面是一个例子
class Employee implements Cloneable{
public Employee clone() throws CloneNotSupportedException
{return (Employee) super.clone();
}}//浅拷贝
/*深拷贝*/
class Employee implements Cloneable{
public Employee clone() throw CloneNotSupportedException
{
Employee cloned= (Employee)super.clone();
cloned.hierDay=(Date) hireDay.clone();
return cloned;
}}
javax.swing.Timer是一个给定周期间隔,然后重复调用执行一个方法的类,给定的参数有两个,第一个是时间间隔,第二个是实现了ActionListener的对象。
Tookkit.getDefaultToolkit().beep();
内部类
内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据
内部类可以对同一保重的其他类隐藏起来。
想定义一个回调函数不想编写大量代码的时候,使用匿名内部类比较便捷。
在内部类里面可以这样引用外围类 OuterClass.this
在外围类的作用域之外,可以这样引用内部类 OuterClass.InnerClass 比如 TalkingClock jabberer = new TalkingClock(1000,true); TalkingClock.TimerPrinter listener = jabberer.new TimePrinter();这里TalkingClock是外围类,Timeprinter是内部类。
在一个方法中声明类就是局部类,不能用public,private进行声明。他的作用域被限定在声明这个局部类的块中。这样对外部世界可以完全的隐藏起来,出来声明的方法知道这个类外,其他没有任何方法知道这个局部类的存在。
局部类不仅可以访问包含他们的外部类,还可以访问包含他们的方法的局部变量,不过局部类访问方法中的局部变量的话,必须把局部变量声明为final,为什么这样可以查看Java核心第一卷227页。
匿名内部类
是将局部内部类的使用再深入了一步。只创建这个类的一个对象,而不必命名了。用于构建对象的任何参数都要被放在超类名后面的括号里面,语法格式为
SuperTyper object=new SuperTyper(construction parameters){
inner class methods and data
} supertyper可以是接口,那么后面就要实现他,也可以是类,那么后面的匿名类就要扩展他。由于构造器的名字必须与类名相同,而匿名类没有名字,所以匿名类不能有构造器。而是把构造器参数传给超类构造器。尤其是在内部类实现接口的时候不能有任何构造参数。
静态内部类
把内部类声明为static可以取消产生的引用,就是不再引用外围类对象,也不需要引用任何其他的对象。只有内部类可以声明为私有或者静态。如果内部类对象在静态方法中构造,那么就必须使用静态内部类。