【问题标题】:Can you do method overloading with generics and only change the generic type of the method signature?您可以使用泛型进行方法重载并且只更改方法签名的泛型类型吗?
【发布时间】:2011-11-05 17:59:33
【问题描述】:

如果您不使用 Java 泛型,我相信在同一个类中不可能有两个仅在返回类型上有所不同的方法。

换句话说,这将是非法

public HappyEmotion foo(T emotion) {
    // do something
}   

public SadEmotion foo(T emotion) {
    // do something else
}   

在重载返回可能实现不同接口的泛型类型的方法时也是如此,例如如果以下两个方法存在于同一个类定义中:

public <T extends Happy> T foo(T emotion) {
    // do something
}   

public <T extends Sad> T foo(T emotion) {
    // do something else
}   

这是否违法?

【问题讨论】:

  • 你试过编译吗? (符合标准的)编译器会立即告诉您什么是合法的,什么是非法的。一个更好的问题是“为什么......非法?”如果你不明白原因。

标签: java oop generics overloading


【解决方案1】:

这是合法的,因为输入参数也因类型而异..

因此,以下是合法的,

public <T extends Happy> T foo(T emotion) {
    // do something
}   

public <T extends Sad> T foo(T emotion) {
    // do something else
}

但跟随不是,

public <T extends Happy> String foo(T emotion) {
    // do something
}   

public <T extends Happy> T foo(T emotion) {
    // do something else
} 

谢谢...

【讨论】:

    【解决方案2】:

    这运行得很好。

    public class Main {
        public static void main(String[] args){
            Main main = new Main();
            main.foo("hello");
            main.foo(new Integer(5));
        }
    
        public <T extends String> T foo(T emotion) {
            return (T) "test";
        }
    
        public <T extends Integer> T foo(T emotion) {
            Integer integer = 5;
            return (T) integer;
        } 
    }
    

    【讨论】:

      【解决方案3】:

      它会编译,但问题在于 Happy 或 Sad 是否是另一个的超类。

      例如,以下编译:

      public <T extends Number> T sayHi() {
          System.out.println("number");
          return null;
      }
      
      public <T extends Integer> T sayHi() {
          System.out.println("integer");
          return null;
      }
      

      但是,当您尝试编译以下内容时会遇到问题:

      Integer test = sayHi();
      

      在这种情况下,您根本无法将&lt;Integer&gt; 添加到前面,因为 Integer 仍然是 Number 和 Integer。

      但是以下编译

      Double test2 = <Double>sayHi();
      

      所以基本上只要 Sad 对象不能是 Happy 对象的实例,反之亦然,只要您在方法名称前使用 or 调用它,您的代码就应该可以工作。

      【讨论】:

      • 你怎么能写两个方法签名相同但返回类型不同的方法并说它可以编译,这完全违反了方法重载的概念
      【解决方案4】:

      您可以使用泛型来区分Java中的方法。 JVM 看不到这种类型,但只要参数或返回类型不同,它仍将在 Sun/Oracle 编译器中编译。这不适用于 IBM/eclipse 编译器。

      这表明您希望发生在字节码级别。 http://vanillajava.blogspot.com/2011/02/with-generics-return-type-is-part-of.html

      【讨论】:

        【解决方案5】:

        正如其他人所说,这是合法的。但是,我想指出当类型相互扩展时会发生什么。

        假设我们有两个接口(也适用于类,只需更改签名):

        interface Emotion {}
        interface Happy extends Emotion {}
        

        还有两个功能:

        <T extends Emotion> void foo(T obj) {} // Referred as foo1
        <T extends Happy> void foo(T obj) {} // Referred as foo2
        

        如果一个对象符合 Emotion,JVM 将选择 foo1。 如果一个对象符合 Happy,JVM 将选择 foo2 而不是 foo1。 注意优先顺序。这就是 JVM 解决歧义的方式。但是,这仅在您将泛型参数作为参数传递时才有效。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多