1、上转型:顾名思义就是子类对象向上转为父类对象。
著名的里氏替换原则就描述了这个现象。
里氏替换原则: “派生类(子类)对象能够替换其基类(超类)对象被使用。”
下转型:父类对象向下转为子类对象。
public class ClassA {
}
class SubClassA extends ClassA {
}
class Test {
public static void main(String args[]) {
ClassA a1;
ClassA a2 = new ClassA();
SubClassA suba1 = new SubClassA();
SubClassA suba2;
a1 = suba1;// 上转型
suba2=(SubClassA) a2;//
}
}
从语法上可以看出 上转型比较简单,而下转型需要对父类对象进行强制类型转换。
事实上,上转型是安全的,而下转型是不安全的。可以这样理解:上转型是有子类转型为父类,是一个由多到少的过程,虽然会丢失,但不存在安全问题。下转型是由少到多,多出来的那一部分没有相应的实现,这就是问题所在。
根据上面提到的里氏替换原则还可以解释一个现象:子类重写父类中的方法,该方法的访问权限不能低于其在父类中的权限。联系下面一段代码,做一下解释---》
class A {
public void Action() {
System.out.println("父类的Action()");
}
}
class SubA extends A {
public void Action() {
System.out.println("子类的Action()");
}
}
public class Test {
public static void main(String args[]) {
A a = new SubA();
a.Action();
}
}
A a=new SubA();发生了上述的上转型。然后调用了对象a的Action()方法。输出结果为:子类的Action()。得到这样的结果是在我们意料之中的。
但是当我们把SubA类中的Action方法改成小于父类方法的public权限(如:protected或者private)时,就会报错。这是因为保证在上转型后能够访问到子类中的方法。
2、最近看到一段代码,拓展了我心中的上转型概念。从实现了某个接口的对象得到对此接口得引用,与上转型为这个对象的基类,实质上是一样的。
上代码:
class Parcel4 {
private class PContents implements Contents {
private int i = 11;
public int value() {
return i;
}
}
protected class PDestination implements Destination {
private String label;
private PDestination(String whereTo) {
label = whereTo;
}
public String readLabel() {
return label;
}
}
public Destination destination(String s) {
return new PDestination(s);
}
public Contents contents() {
return new PContents();
}
}
public class TestParcel {
public static void main(String[] args) {
Parcel4 p = new Parcel4();
Contents c1 = p.contents();//!!!!PContents对象上转型为Contents接口。
Destination d = p.destination("Tasmania");
}
}
这段代码还体现了一个使用内部类的作用 :与PDestination,PContents都实现了相应的接口,但与PDestination相比,PContents的访问权限是private的,所以能将对接口Contents的实现很好地封装在类Parcel4中。
这很好理解,可以做一个对比:在简单的实现接口方法时,它们的权限必须为public(参见以下代码),那么对于方法和接口中的域的访问便是开放的。而使用内部类可以使访问实现的接口的方法和域变成private的,虽然要增加一些步骤。
public interface ss {
int a=0;
int aaa();
}
class S implements ss{
@Override
public int aaa() {
System.out.println(a);
return 0;
// TODO Auto-generated method stub
}
}
3、通过父类引用是不能调用其子类中新增的方法的。