今天学习写MapReduce的时候,遇到下面这样的一个代码:
如图所见,context.getInputSplit() 返回的是 InputSplit 类型,而 InputSplit 是父类,FileSplit 是子类,我们知道,Java里,父类不能够强制转换成子类,那为什么这里又可以呢?
带着这个疑问,我做了一个小实验,详见下面代码:
Father类:
public abstract class Father {
public void sayFather() {
System.out.println("Father");
}
public abstract void abstractSayFather();
}
Son类:
public abstract class Son extends Father{
@Override
public void sayFather(){
System.out.println("The son say Father");
}
public void saySon(){
System.out.println("son!!");
}
//实现父类抽象方法
@Override
public void abstractSayFather() {};
public GrandSon getGrandSon() {
GrandSon g = new GrandSon();
return g;
}
}
Brother类:
public class Brother extends Father{
public void sayBrother() {
System.out.println("say Brother !!!!");
}
@Override
public void abstractSayFather() {
System.out.println("I am Brother ,This fun is extends Father!!!");
};
}
OtherPeople类:
public abstract class OtherPeople {
public void sayOtherPeople() {
System.out.println("OtherPeople !!!");
}
}
GrandSon类:
public class GrandSon {
public void sayGrand() {
System.out.println("Grand Son !!");
}
}
主程序,运行的坑和注释都写在代码里面了,请详细看:
public class TestMain {
private Father f4;
private Son s4;
private GrandSon g4;
//字类可以强制转换成父类
public void demo1(Father f4) {
//注意这里!父类可强制转换成子类,而且!s4, , f4 并没有实例化!!!
this.s4 = (Son) f4;
System.out.println("1 ----------------------------");
//注意这里!这里s4虽然是从父类转换过来,但是不可以使用到子类的方法!!
this.s4.saySon();
}
public void run() {
//Son 为抽象类,但是这里却可以 new Son() 但是一定要加大括号,括号里面可以重写方法,也可以什么都不写,如下面这里
Father f1 = new Son() {
@Override
public void sayFather() {
System.out.println("执行sayFather方法:");
super.sayFather();
}
};
f1.sayFather();
System.out.println(f1.toString()); //打印结果为 TestMain$1@1b6d3586
System.out.println("2 ---------------------------------------");
//大括号里面什么都不写
Father f2 = new Son(){}; // 这里并没有报错
Father f3 = new Son(){
public void sayFatherFun2() {
System.out.println("在这里,可以甚至可以新建一个新的函数");
System.out.println("say father function 2 !!!!");
}
};
//这里报错,虽然上面写了 sayFatherFun2 方法,但是并不能够使用,只可以使用Son类的方法
//f3.sayFatherFun2;
System.out.println(f2.toString()); //打印结果类似为 TestMain$2@1b6d3586
System.out.println(f3.toString()); //打印结果类似为 TestMain$3@4554617c
System.out.println("3 ---------------------------------------");
//注意这里!f2 为父类 Father,但是可以强制转换成子类 son 并且可以直接调用子类 son 的方法 getGrandSon() !!!! 对g4进行了实例化!!!!
this.g4 = ((Son)f3).getGrandSon(); // 正常执行
//运行报错,因为 在 main 方法里 f4 已经是 Brother 的实例了!!!
//this.g4 = ((Son)f4).getGrandSon();
this.g4.sayGrand();
System.out.println(this.g4.toString()); //可以见到打印出 GrandSon的实例
System.out.println("4 ---------------------------------------");
//报错,OtherPeople为毫不相干的类!!!
//((OtherPeople)f4).sayOtherPeople();
}
public static void main(String[] args) {
TestMain test = new TestMain();
//下面代码执行异常!报空指针异常!!因为 test.f4 还没有实例!!
//test.demo1(test.f4);
//执行正常 子类转成父类,只能够用父类的方法了
test.f4 = new Brother();
//执行正常
test.f4.abstractSayFather();
//执行异常,test.f4 已经实例化了,虽然引用是Fahter,但是实例是 Brother,不能够强制转成son类!!!
//test.demo1(test.f4);
test.run();
}
}
运行结果:
Java多态的坑!!!多踩踩!!!