为什么我的原始类型参数方法不覆盖包装类型参数的 super class 方法?
Why doesn't my primitive-type-argumented method override the wrapper-type-argumented super class method?
public class WrapperClasses{
void overloadedMethod(Number N){
System.out.println("Number Class Type");
}
void overloadedMethod(Double D){
System.out.println("Double Wrapper Class Type");
}
void overloadedMethod(Long L){
System.out.println("Long Wrapper Class Type");
}
public static void main(String[] args){
int i = 21;
WrapperClasses wr = new WrapperClasses();
//wr.overloadedMethod(i);
}
}
class mine extends WrapperClasses{
void overloadedMethod(int N){
System.out.println("Integer Class Type");
}
public static void main(String[] args){
int i = 21;
WrapperClasses wr = new mine();
wr.overloadedMethod(i);
}
}
这会打印 Number Class Type
.
我了解包装器class方法重载的规则:
- 如果您将原始数据类型作为参数传递给方法
调用时,编译器首先检查采用
与参数相同的数据类型。
- 如果这样的方法不存在,那么它会检查一个方法
采用比传递的更大的原始数据类型的定义
数据类型。即,它尝试执行自动加宽转换
传递的数据类型。
- 如果无法进行自动扩展转换,则会检查
方法定义,它将相应的包装器 class 类型作为
争论。即,它尝试执行自动装箱转换。
- 如果这样的方法不存在,那么它会检查一个方法
将超级 class 类型(数字或对象类型)作为参数。
- 如果这样的方法也不存在,那么编译器给出一个
编译时错误。
根据规则 1,它应该打印 Integer Class Type
。我在这里错过了什么?
方法重载决议是在编译时确定的,基于变量的编译时类型,该变量持有对您为其调用方法的实例的引用。
void overloadedMethod(int N)
只定义在子classmine
中。因此,当您在类型为基 class WrapperClasses
的引用上调用方法时,只能考虑基 class 的方法进行重载解析。
您传递给该方法的 int
参数与基础 class 的 3 个方法中的任何一个都不匹配,但在装箱到 Integer
之后,它匹配void overloadedMethod(Number N)
方法。
如果您将代码更改为
int i = 21;
mine wr = new mine();
wr.overloadedMethod(i);
它将执行void overloadedMethod(int N)
。
在语言规范级别,这是因为参数为原始类型和包装原始类型的方法不被视为 override-equivalent。 (一种奇特的说法 "they just don't because the language spec says so")。
但从逻辑上讲,它们也不应该,至少在 subint
参数的情况下 class "overriding" super[=26= 中的包装参数].
根据里氏替换原则,subclasses 中的方法必须接受至少 superclass 中的方法接受的所有参数。
如果superclass方法接受包裹的class,它可以接受null
。如果subclass方法只允许接受int
,它不能接受null,所以它是不可替代的。
多态性由 JVM 在运行时执行。为此,这两个方法必须具有相同的运行时签名。
在协变 [=18=] 类型的情况下,编译器生成桥接方法以允许这种情况发生,但是,Java 语言规范不需要这样的桥接方法用于包装器与基元.
这可能有多种原因,但最有可能是向后兼容性。 Java 1.0 没有这样做,即使十多年后添加了自动装箱,也不允许破坏旧代码。即包装器和原语相互重载,而不是覆盖,所以他们现在不能。
public class WrapperClasses{
void overloadedMethod(Number N){
System.out.println("Number Class Type");
}
void overloadedMethod(Double D){
System.out.println("Double Wrapper Class Type");
}
void overloadedMethod(Long L){
System.out.println("Long Wrapper Class Type");
}
public static void main(String[] args){
int i = 21;
WrapperClasses wr = new WrapperClasses();
//wr.overloadedMethod(i);
}
}
class mine extends WrapperClasses{
void overloadedMethod(int N){
System.out.println("Integer Class Type");
}
public static void main(String[] args){
int i = 21;
WrapperClasses wr = new mine();
wr.overloadedMethod(i);
}
}
这会打印 Number Class Type
.
我了解包装器class方法重载的规则:
- 如果您将原始数据类型作为参数传递给方法 调用时,编译器首先检查采用 与参数相同的数据类型。
- 如果这样的方法不存在,那么它会检查一个方法 采用比传递的更大的原始数据类型的定义 数据类型。即,它尝试执行自动加宽转换 传递的数据类型。
- 如果无法进行自动扩展转换,则会检查 方法定义,它将相应的包装器 class 类型作为 争论。即,它尝试执行自动装箱转换。
- 如果这样的方法不存在,那么它会检查一个方法 将超级 class 类型(数字或对象类型)作为参数。
- 如果这样的方法也不存在,那么编译器给出一个 编译时错误。
根据规则 1,它应该打印 Integer Class Type
。我在这里错过了什么?
方法重载决议是在编译时确定的,基于变量的编译时类型,该变量持有对您为其调用方法的实例的引用。
void overloadedMethod(int N)
只定义在子classmine
中。因此,当您在类型为基 class WrapperClasses
的引用上调用方法时,只能考虑基 class 的方法进行重载解析。
您传递给该方法的 int
参数与基础 class 的 3 个方法中的任何一个都不匹配,但在装箱到 Integer
之后,它匹配void overloadedMethod(Number N)
方法。
如果您将代码更改为
int i = 21;
mine wr = new mine();
wr.overloadedMethod(i);
它将执行void overloadedMethod(int N)
。
在语言规范级别,这是因为参数为原始类型和包装原始类型的方法不被视为 override-equivalent。 (一种奇特的说法 "they just don't because the language spec says so")。
但从逻辑上讲,它们也不应该,至少在 subint
参数的情况下 class "overriding" super[=26= 中的包装参数].
根据里氏替换原则,subclasses 中的方法必须接受至少 superclass 中的方法接受的所有参数。
如果superclass方法接受包裹的class,它可以接受null
。如果subclass方法只允许接受int
,它不能接受null,所以它是不可替代的。
多态性由 JVM 在运行时执行。为此,这两个方法必须具有相同的运行时签名。
在协变 [=18=] 类型的情况下,编译器生成桥接方法以允许这种情况发生,但是,Java 语言规范不需要这样的桥接方法用于包装器与基元.
这可能有多种原因,但最有可能是向后兼容性。 Java 1.0 没有这样做,即使十多年后添加了自动装箱,也不允许破坏旧代码。即包装器和原语相互重载,而不是覆盖,所以他们现在不能。