重载方法优先级

时间:2010-02-14 21:01:19

标签: java overloading invocation

我有一个名为Element的基类。其他一些类(如Label和Image)都扩展了这个类。

我现在有一个调度类,它有以下方法:

public class Dispatcher {
    public static AbstractPropertyEditor<Label> createEditor(Label e) {
    ...
    }

    public static AbstractPropertyEditor<Element> createEditor(Element e) {
    ...
    }
}

如果现在我有一个Label实例(扩展了Element)并且我想将它传递给createEditor(),为什么最通用的方法(第二个)被调用?调用大多数特定的方法(createEditor(Label e))会不正常?

我绝对需要使用Element-param的方法来“捕获”a)实现Element但在此调度类中没有自己的特定方法的所有类。

我正在使用Java 6,如何“修复”这个?

编辑:好的,我不得不承认它根本不是关于泛型的。但那是我第一次遇到它的地方。

感谢和问候

5 个答案:

答案 0 :(得分:6)

你为什么不:

  • make Element抽象类,提供默认的createEditor()实现
  • 使Label覆盖createEditor()

因此,您将不需要静态实用程序,并将实现您的目标。

如果您需要Element作为界面,那么:

  • createEditor()定义为Element
  • 的方法
  • 定义EditorFactory界面
  • 提供DefaultEditorFactoryListEditorFactory
  • Element

    的实现者中使用适当的工厂
    public Editor createEditor() {
         editorFactory.createEditor(this);
    }
    

具体EditorFactory在初始化期间或通过某种依赖注入实例化。


根据您的具体问题 - 这取决于您在那里编译的类型。如果您致电createEditor(obj),则取决于Element obj = ..还是Label obj = ..

答案 1 :(得分:2)

这与泛型无关,而且与方法重载有关。在Java中,调用的方法签名是在编译时确定的,而不是在运行时确定的,因此您必须在运行时进行检查和转换。

所以替换这个:

 Element label = getLabel();
 AbstractPropertyEditor<?> editor = createEditor(label);   

有了这个:

 Element label = getLabel();
 AbtractPropertyEditor<?> editor;
 if(label instanceof Label) {
      editor = createEditor((Label) label);
 } else {
      editor = createEditor(label);
 }

另一种(更标准/更好)解决方法是让createEditor(Element)方法检查类型并使用强制转换方法调用子类型。但是,如果对声明的方法执行此操作,则返回参数会出现问题。

答案 2 :(得分:1)

来自Java Language Specification

  

调用方法时(第15.12节),   实际参数的数量(以及任何   显式类型参数)和   参数的编译时类型   使用在编译时,到   确定方法的签名   将被调用(§15.12.2)。如果   要调用的方法是   实例方法,实际方法为   被调用将在运行时确定   时间,使用动态方法查找   (§15.12.4)。

答案 3 :(得分:0)

既然你可能在做:

Element element = new Label();

由编译器决定。

答案 4 :(得分:0)

这是重载方法的一个示例。 尽管运行时的实际对象是Label而不是Element,但是 选择哪个重载方法调用(换句话说,签名的 方法)不是在运行时动态决定的。引用类型(不是对象类型)确定调用哪个重载方法!

实施例

public class Car {    
}

public class Toyota extends Car {    
}

public class MyCar {

    public void run(Car c) {
        System.out.println("Run any Car");
    }

    public void run(Toyota t) {
        System.out.println("Run Toyota Car");
    }

    public static void main(String[] args) {
        MyCar myCar = new MyCar();

        Car c1 = new Car();
        myCar.run(c1); // Output: Run any Car

        Toyota c2 = new Toyota();
        myCar.run(c2); // Output: Run Toyota Car

        Car c3 = new Toyota();
        myCar.run(c3); // Output: Run any Car    
    }
}

所以,在你的情况下

Element obj1 = new Label();
Dispatcher.createEditor(obj); // Method with Element argument is called 
                              // as you are passing Element 

Label obj2 = new Label();
Dispatcher.createEditor(obj); // Method with Label argument is called 
                              // as you are passing Label

另一方面,重写的方法调用在运行时发生,它取决于对象类型(换句话说,堆上实际实例的类型)