向上转型与向下转型是 Java 中关于父子对象转换的两个概念。
假如我们有如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| public class Animals { public int age = 0;
public void eat(){ System.out.println("Eat..."); } }
public class Dog extends Animals { public int age = 10;
@Override public void eat(){ System.out.println("eat bone..."); }
public void bark(){ System.out.println("dog bark..."); } }
public class Cat extends Animals{ public int age = 2; @Override public void eat(){ System.out.println("eat fish..."); }
public void sleep(){ System.out.println("cat sleep..."); } }
|
- 向上转型:
Animals a = new Cat()
- 向下转型:
Cat cat = (Cat) a
- 注意:只有向上转型的变量才能向下转型。此时实例 a 就拥有子类自己定义的特有方法
cat.sleep()
为什么要向上转型
假设我们有一个宠物店类,其中有一个统计宠物数量的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class AnimalsShop { private List<Animals> list = new ArrayList<Animals>(); public void add(Animals a){ list.add(a); }
public int getSize(){ return list.size(); } public Animals getAnimal(int position){ return list.get(position); } }
|
因此可以发现,使用向上转型的方式能够提高代码的灵活性和可扩展性。比如在上述代码中,我们不必关心宠物的具体类型,便可以直接传入 AnimalsShop 类中进行数量统计。
为什么要向下转型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| public interface Electronics{
}
public class Thinkpad implements Electronics{
public void boot(){ System.out.println("welcome,I am Thinkpad"); }
public void program(){ System.out.println("using Thinkpad program"); }
}
public class Mouse implements Electronics{
public void move(){ System.out.println("move the mouse"); }
public void onClick(){ System.out.println("a click of the mouse"); }
}
public class ShopCar{
private List<Electronics> mlist = new ArrayList<Electronics>();
public void add(Electronics electronics){ mlist.add(electronics); }
public int getSize(){ return mlist.size(); }
public Electronics getListItem(int position){ return mlist.get(position); } }
public class Test{
public static final int THINKPAD = 0; public static final int MOUSE = 1;
public static void main(String[] args){
ShopCar shopcar = new ShopCar(); shopcar.add(new Thinkpad()); shopcar.add(new Mouse()); shopcar.add(new Keyboard());
System.out.println("购物车存放的电子产品数量为 ——> "+shopcar.getSize());
Thinkpad thinkpad = (Thinkpad)shopcar.getListItem(THINKPAD); thinkpad.boot(); thinkpad.program();
System.out.println("-------------------");
Mouse mouse = (Mouse)shopcar.getListItem(MOUSE); mouse.move(); mouse.onClick();
System.out.println("-------------------"); }
}
|
很多时候,我们需要把很多种类的实例对象,全部扔到一个集合。比如把Thinkpad笔记本,Mouse鼠标等实例对象,全部扔到一个 Shopcar 购物车集合,但是不可能给每个种类都用一个独立的集合去存放。这个时候我们应该寻找到一个标准来统一这些实例,接口就是一个标准。上面提到的笔记本电脑、鼠标都是电子产品,我们将其抽象为一个 Electronic 接口。
同时,我们把很多种类的实例对象,全部扔到存放其父类对象的集合。经过了这个过程,子类实例已经赋值给了父类引用(即完成了向上转型)但在这个过程中,子类丢失了其特有的方法,如果我们想要重新找回这些丢失的方法,就要用到向下转型,就像下面这段代码。
1 2 3 4
| Thinkpad thinkpad = (Thinkpad)shopcar.getListItem(THINKPAD); thinkpad.boot(); thinkpad.program();
|
参考文章: