【问题标题】:Java parametric signature resolutionJava参数签名解析
【发布时间】:2012-11-10 18:25:29
【问题描述】:

为什么这段代码打印的是 2.0 而不是 1.0?

abstract class B<T extends Number> {
    abstract Number f(T j);
}

class A<T extends Number> extends B<T> {
    public Number f(Float j) {
        return 1f;
    }

    public Number f(T j) {
        return j;
    }
}

public class J {
    public static void main(String[] args) {
        B<Float> a = new A<>();
        Number r = a.f(2f);
        System.out.println(r);
    }
}

【问题讨论】:

    标签: java oop generics inheritance


    【解决方案1】:

    你在期待什么。您在 B 类中只声明了一个方法:

    abstract Number f(T j);
    

    A类中的方法

    public Number f(Float j);
    

    不会覆盖前者。他们有不同的签名。所以方法

    public Number f(T j) {
        return j;
    }
    

    被调用。

    【讨论】:

    • 我天真地期待它使用更严格的签名 f(Float) 而不是 f(T extends Number) 调用方法
    【解决方案2】:

    所以这里问题的核心是您已将变量a 声明为B 类型。由于B 类只有一种方法,所以这是获胜的方法。但是,在您的main 中,如果您将a 的类型更改为A 类型,您会注意到它不会编译,因为它不明确。但是,如果您确实将类A 中的方法更改为接受原语,并且在main() 方法中将变量a 定义为A 类型,则会导致1.0。即,以下将导致打印1.0

    class A<T extends Number> extends B<T> {
        public Number f(float j) {
            return 1f;
        }
    
        public Number f(T j) {
            return j;
        }
    }
    
    
    public class J {
        public static void main(String[] args) {
            A<Float> a = new A<>();
            Number r = a.f(2f);
            System.out.println(r);
        }
    }
    

    【讨论】:

      【解决方案3】:

      在您下面的代码中

      abstract class B<T extends Number> {
       abstract Number f(T j);
      }
      
      class A<T extends Number> extends B<T> {
          public Number f(Float j) //this method does not override the superclass method
      
          {
              return 1f;
          }
      
          public Number f(T j) {
              return j;
          }
      }
      
      public class J {
          public static void main(String[] args) {
              B<Float> a = new A<>();
              Number r = a.f(2f);
              System.out.println(r);
          }
      }
      

      当调用 a.f(2f) 时,它会调用

      public Number f(T j)
      {
      return j;
      }
      

      返回 j 因此提供的输出是 2.0

      【讨论】:

      • 好的,但是为什么不覆盖超类方法?
      【解决方案4】:

      floatFloat 不同。

      自动装箱使其感觉相同,但一个主要区别是您不能将null 传递给float 参数。

      我建议在你重写的方法上使用@Override 注解,这样编译器会告诉你签名是否正确

      【讨论】:

        猜你喜欢
        • 2013-10-09
        • 2011-10-05
        • 2013-05-19
        • 2012-10-05
        • 1970-01-01
        • 2021-01-31
        • 2021-02-03
        • 2015-10-12
        • 1970-01-01
        相关资源
        最近更新 更多