nee*_*rle 6 java polymorphism inheritance
我最近开始使用JAVA编程并且有一个问题要问.假设我有一个SuperClass和一个SubClass,它扩展了SuperClass并尝试覆盖SuperClass中定义的方法,如下所示:
public class SuperClass{
public void method1(int val){
System.out.println("This is method in SuperClass.Val is:" + val);
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试在我的SubClass中扩展SuperClass并使用一个例外覆盖该方法,而不是int在method1中声明的类型,我使用参数的类型Integer,如下所示:
public class SubClass extends SuperClass{
@Override
public void method1(Integer val){ ///compiler gives an error
}
}
Run Code Online (Sandbox Code Playgroud)
编译器不允许使用SubClass方法的声明(我正在使用eclipse IDE).为什么会这样?整数本质上是int的包装,那为什么禁止这样的声明呢?
谢谢
正如您可能已经理解的那样,正式的解释是这两个函数具有不同的签名(正如 Andrew Tobilko 已经指出的那样),因此一个函数可能不会覆盖另一个函数。
因此,我认为通过问这个问题,您真正想问的是“为什么会这样”,或者“为什么编译器不能弄清楚事情以便允许我这样做”。
所以,实际的解释如下:
这是因为你可能在某个地方有一些方法(甚至是一些不相关的类),它接受 aSuperClass作为参数,并尝试method1()像这样调用它:
public void someMethod( SuperClass s )
{
s.method1( 7 );
}
Run Code Online (Sandbox Code Playgroud)
当编译器发现它时,它将7作为参数传递给method1(),而不会传递包装的7. 然而,s可能不是真正的实例SuperClass,它可能是实例SubClass,如下所示:
/* some code somewhere */
someMethod( new SubClass() );
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为 OOP 中有一个称为里氏替换原则的原则,它说:
如果 S 是 T 的子类型,则类型 T 的对象可以替换为类型 S 的对象(即类型 S 的对象可以替换类型 T 的对象),而不改变该程序的任何所需属性(正确性、执行的任务) , ETC。)。
new ArrayList<String>()这与允许您将 a 分配给类型变量的原则相同List<String>,没有它,OOP 中什么都不起作用。
因此,编译器必须传递一个普通的原语7,但 的接收方法SubClass将需要一个wrapped 7,这是行不通的。因此,语言规定这种隐式转换是无效的,以确保不会出现这种无意义的情况。
修正案
你可能会问:“为什么它不起作用?” 答案是,java中的原语对应于底层硬件的机器数据类型,而包装的原语是对象。因此,在机器堆栈上, a7将由值为 的机器字表示7,而wrapped7将由类似 的东西表示0x46d7c8fe,它是指向包含wrapped 的对象的指针7。