Java 使用继承的重载方法
我有两门课:Java 使用继承的重载方法,java,inheritance,methods,numbers,integer,Java,Inheritance,Methods,Numbers,Integer,我有两门课: public class ClassA { public void method(Number n) { System.out.println("ClassA: " + n + " " + n.getClass()); } } 以及: 但当我跑步时: ClassA a = new ClassB(); a.method(3); 我得到: ClassA: 3 class java.lang.Integer 我的问题是,为什么不使用ClassB的方
public class ClassA {
public void method(Number n) {
System.out.println("ClassA: " + n + " " + n.getClass());
}
}
以及:
但当我跑步时:
ClassA a = new ClassB();
a.method(3);
我得到:
ClassA: 3 class java.lang.Integer
我的问题是,为什么不使用ClassB的方法
a
是ClassB
的一个实例,ClassB
的method()
有一个Integer
参数…,因为参数中的数字和整数创建了两个不同的方法签名。因此,类B只有两种不同的方法可供使用。您的问题源于以下事实(引用自官方Java继承教程):
在子类中,可以重载从超类继承的方法。这种重载方法既不隐藏也不重写超类方法,它们是新方法,是子类特有的`
有关更多详细信息,请参阅官方Java教程:
因为数字3自动装箱为整数 请参阅下面的链接: 一般规则:参数被隐式加宽以匹配方法参数。
从一个包装类扩展到另一个包装类是不合法的。因为这两个操作有不同的参数(参数)类型(即使它们是子类),它们被认为是不同的(不同于C)。您没有用第二个方法覆盖第一个方法。相反,您最终得到了类B,它现在有两个方法
public void method(Number n) and
public void method(Integer n)
默认情况下,当您执行此操作时,方法(3)3被强制转换为整数对象。
您可以通过调用
a.method((Number)3); //this would call the second method/operation.
您还可以通过使用反射来迭代类B的方法来验证这一点
我的问题是,为什么不使用ClassB的方法
不是真的。使用的方法是ClassB
的方法,它继承自ClassA
我认为造成这种混乱的主要原因是,该方法实际上并没有被覆盖,而是被重载。尽管
Integer
是Number
的一个子类型,但由于方法参数在Java中是不变的,因此方法public void方法(Integer d)
不会覆盖方法public void方法(Number n)
。因此,ClassB
最终有两个(重载)方法
静态绑定用于重载方法,具有最特定参数类型的方法由编译器选择。但是在这种情况下,为什么编译器选择公共无效方法(数字n)
而不是公共无效方法(整数d)
。这是因为您用来调用该方法的引用的类型是ClassA
ClassA a = new ClassB(); //instance is of ClassB (runtime info)
a.method(3); //but the reference of type ClassA (compiletime info)
ClassA
拥有的唯一方法是public void方法(编号n)
,因此编译器会选择这种方法。请记住,此处预期的参数类型是Number
,但实际参数,即传递的整数3,会自动装箱到类型integer
。它之所以有效是因为方法参数在Java中是协变的
现在,我想很清楚为什么它会打印
ClassA:3类java.lang.Integer
a是ClassA类型,因此ClassB中的方法对于实例a不可见,除非它被声明为ClassB
ClassB a = new ClassB();
将产生您的预期输出。Number是整数的超类型。因此,您传入的任何内容都将自动装箱到相应的子类型,并将调用ClassA中的方法。试着传球
a.method(3.0f) // Float
a.method(3.0) // Double
为了清除,我在
classA
和classB
中都添加了show()
方法
public void show() {
System.out.println(getClass());
}
我这样叫,
// Case 1
ClassA a = new ClassB();
a.method(3);// ClassA: 3 class java.lang.Integer
a.show(); // class ClassB
// Case 2
ClassB b = new ClassB();
b.method(3);// ClassB: 3 class java.lang.Integer
b.show(); // class ClassB
这里方法(数字n)和方法(整数d)具有不同的签名。
它不是压倒一切的。它超载了
但是show()方法是方法重写
在案例1中,
对象A只能访问类A的方法。a是classA类型,classB中的方法不可见。
这就是调用classA方法的原因。
但对于被重写的show()方法,调用类B的show()方法
在案例2中,
类A和B的两个方法都可以通过对象B访问,因为类B扩展了类A
Class A a = new ClassB();
a.method(3);
但是假设您有一个方法,其中“a”和“3”作为参数传递给您,并且您仍然执行相同的代码
public void foo(A a, Number n)
{
a.method(n);
}
编译器不知道您是要传递类A还是类B(或数字或整数)。它仍然必须解决该方法,以便可以对a.method的返回值进行类型检查。我对此问题进行了一些研究,并提出了解决方案,以消除您的混淆。希望它能帮助你理解 请查看以下代码:
class A {
public void func(Number obj){
System.out.println("In a func");
}
public void func(Integer obj){
System.out.println("In b func");
}
}
class B extends A {
}
public class X {
public static void main(String s[]){
B b = new B();
b.func(3);
A a = new B();
a.func(3);
}
}
class A {
public void func(Number obj){
System.out.println("In a func");
}
public void func(Integer obj){
System.out.println("In b func");
}
}
class B extends A {
public void func(Number obj){
System.out.println("In a func of class B");
}
public void func(Integer obj){
System.out.println("In b func of class B");
}
}
public class X {
public static void main(String s[]){
B b = new B();
b.func(3);
A a = new B();
a.func(3);
}
}
class A {
public void func(Number obj){
System.out.println("In a func");
}
}
class B extends A {
public void func(Integer obj){
System.out.println("In b func");
}
}
public class X {
public static void main(String s[]){
B b = new B();
b.func(3);
A a = new B();
a.func(3);
}
}
如果运行此代码,您将获得以下输出:
“在b函数中”
“在b函数中” 在这种情况下,有4种方法:
class A {
public void func(Number obj){
System.out.println("In a func");
}
public void func(Integer obj){
System.out.println("In b func");
}
}
class B extends A {
public void func(Number obj){
System.out.println("In a func of class B");
}
public void func(Integer obj){
System.out.println("In b func of class B");
}
}
public class X {
public static void main(String s[]){
B b = new B();
b.func(3);
A a = new B();
a.func(3);
}
}
class A {
public void func(Number obj){
System.out.println("In a func");
}
}
class B extends A {
public void func(Integer obj){
System.out.println("In b func");
}
}
public class X {
public static void main(String s[]){
B b = new B();
b.func(3);
A a = new B();
a.func(3);
}
}
ClassA a = new ClassB();
a.method(3);