初学Java-继承和多态
1:Java中子类继承父类的东西分以下两种情况
a:若子类和父类在一个package中,子类继承父类的public,protected和默认访问级别的成员变量和成员方法
b:若子类和父类不在一个package中,子类继承父类的public,protected访问级别的成员变量和成员方法
2:所有的Java类都直接或间接地继承了java.lang.Object类,这个类中定义了所有Java对象都具有的相同行为
java.lang
类 Object
java.lang.Object
public class Object
类 Object
是类层次结构的根类。每个类都使用 Object
作为超类。所有对象(包括数组)都实现这个类的方法。
- 从以下版本开始:
- JDK1.0
- 另请参见:
Class
构造方法摘要 | |
---|---|
Object() |
方法摘要 | |
---|---|
protected Object |
clone() 创建并返回此对象的一个副本。 |
boolean |
equals(Object obj) 指示其他某个对象是否与此对象“相等”。 |
protected void |
finalize() 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。 |
Class<?> |
getClass() 返回此 Object 的运行时类。 |
int |
hashCode() 返回该对象的哈希码值。 |
void |
notify() 唤醒在此对象监视器上等待的单个线程。 |
void |
notifyAll() 唤醒在此对象监视器上等待的所有线程。 |
String |
toString() 返回该对象的字符串表示。 |
void |
wait() 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。 |
void |
wait(long timeout) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。 |
void |
wait(long timeout, int nanos) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待。 |
3:Java中方法重载,和C++类似,要求两个方法若是重载方法的话,则
a:方法名称相同
b:想法的形参不同,包括形参个数不同或者形参类型不同
c:若仅返回值不同不算方法重载,即重载的方法可以返回值不同
d:方法的修饰符可以不相同,参考 c
4:方法覆盖:如果在子类中定义的一个方法,其名称,返回类型和参数签名正好和父类中的某个方法的名称,返回类型及参数签名相匹配,那么可以说子类的方法覆盖了父类的方法
覆盖方法必须满足一下10点约束条件:
a:子类方法的名称、参数签名和返回类型必须和父类方法的名称、参数签名和返回类型一致。
b:子类方法不能缩小父类方法的访问权限。例如父类的public方法子类就不能声明成private形式的
c:子类方法不能抛出比父类方法更多的异常。子类方法抛出的异常必须和父类方法抛出的异常相同,或者子类方法抛出的异常类是父类方法抛出的异常类的子类
d:方法覆盖只存在于子类和父类之间(包括直接父类和间接父类),在同一个类中方法只能被重载,不能被覆盖
e:子类可以定义与父类的静态方法同名的静态方法,以便在子类中隐藏父类的静态方法。子类的这个静态方法必须满足一下几点要求。这里是隐藏而不是覆盖的原因是,运行时
Java虚拟机把静态方法和所声明的类绑定,而把实例方法和所属的实例类绑定。
f:父类的私有方法不能被子类覆盖。
g:父类的抽象方法可以被子类通过以下两种途径覆盖:一是子类实现父类的抽象方法;二是子类重新声明父类的抽象方法
h:父类的非抽象方法可以被覆盖为抽象方法
下面是对多态的总结:可以分为编译时多态和运行时多态(参考D:\JavaWorkplace\TestAbsract.java)
1:编译时多态,主要有两点(其实不用考虑)
a:编译时,Java引用类型的变量根据声明的类型来处理,下面举例说明
class Base{
public void method{System.out.println("Base");}
}
public class Sub extends Base{
public void method(){System.out.println("Sub");}
public void method2(){System.out.println("SubMethod2");}
public static void main(String args[]){
Base sub=new Sub();
sub.method2();
}
}
根据编译时医用类型判断 方法,此时编译错误,因为sub变量被看做是Base类型的实例,而Base类并没有method2()方法
b:Java编译器允许在具有直接或者间接继承关系的类之间进行类型转换,对于向上进行类型转换,不必使用强制类型转换;对于向下转型,必须进行强制类型转换。
2:运行时多态,主要是以下3点
a:对于一个引用类型的变量,运行时Java虚拟机按照它们实际引用的对象来处理
例如把上例中 sub.method2()换成sub.method()的话,实际打印的是 Sub,
b:在运行时,子类的对象可以转换为父类类型,而父类的对象实际上无法转换为子类类型。因为通俗的讲,父类拥有的成员子类肯定也有,而子类拥有的成员父类不一定有。
c:在运行时环境中,通过引用类型变量来访问所引用对象的方法和属性时,Java虚拟机采用以下绑定规则
1:实例方法与引用变量实际引用的对象的方法绑定,这种绑定属于动态绑定,因为是在运行时由Java虚拟机动态决定的
2:静态方法与引用变量所声明的类型的方法绑定,这种绑定属于静态绑定,因为实际上在编译阶段就已经作了绑定。
3:成员变量(包括静态变量和实例变量)与引用变量所实际声明的类型的成员变量绑定,这种绑定属于静态绑定,因为实际上在编译阶段就已经作了绑定。