【问题标题】:Access static method on generic class访问泛型类的静态方法
【发布时间】:2011-08-19 08:09:42
【问题描述】:

我想访问一个类的静态方法,但将该类传入泛型。

我做了以下事情:

class Base{
  public static String getStaticName(){
    return "Base";
  }
}


class Child extends Base{
  public static String getStaticName(){
    return "Child";
  }
}

class StaticAccessor{
  public static <T extends Base>String getName(Class<T> clazz){
    return T.getStaticName();
  }
}

StaticAccessor.getName() // --> "Base"

这将返回“Base”,但我想要的是“Child”任何人没有反思的建议?

【问题讨论】:

    标签: java generics methods static


    【解决方案1】:

    我不相信你可以不反思就做到这一点。

    看来您应该做的不是使用静态方法。您正在使用继承,但静态方法不遵循继承规则。

    【讨论】:

      【解决方案2】:

      如果您可以在静态访问器中传递对象实例而不是 Class,那么,有一个简单而优雅的解决方案:

      public class Test {
      
          static class Base {
              public static String getStaticName() { return "Base"; }
              public String myOverridable() { return Base.getStaticName(); };
          }
      
          static class Child extends Base {
              public static String getStaticName() { return "Child"; }
              @Override
              public String myOverridable() { return Child.getStaticName(); };
          }
      
          static class StaticAccessor {
              public static <T extends Base>String getName(T instance) {
                  return instance.myOverridable();
          }
      
      }
      
      
          public static void main(String[] args) {
      
              Base b = new Base();
              Child c = new Child();
      
              System.out.println(StaticAccessor.getName(b));
              System.out.println(StaticAccessor.getName(c));
      
          }
      
      }
      

      输出是:

      Base
      Child
      

      【讨论】:

      • 是的,这只是使用多态性来获取名称。最初的例子似乎暗示它应该在没有任何 Object 实例的情况下工作,并且只针对 Class 工作。我想在示例中您可以只在对象实例本身上调用 getName 方法。
      • @planetjones 不,您不能在实例本身上调用 getStaticName(),因为它在两种情况下都只会返回“Base”。
      • 抱歉,我的意思是针对对象调用方法,即 myOverridable() 可以直接针对 b 或 c 调用。
      【解决方案3】:

      没有反射就无法做到这一点,因为 T 类型在运行时被擦除(这意味着它将减少到其下限,即 Base)。

      由于您确实可以访问Class&lt;T&gt;,因此您可以通过反射来做到这一点,但是:

      return (String) clazz.getMethod("getStaticName").invoke(null);
      

      请注意,我认为这样的代码是代码异味,而且非常脆弱。你能告诉我们你为什么需要它吗?

      【讨论】:

      • 更简单:返回 clazz.getSimpleName();
      • @Nathan:是的,如果实现将永远是这样的。
      • 正确。我的建议只有在 getStaticName() 方法的目的是返回类的简单(或二进制/规范)名称时才有效。
      • @joachimSauer 能否请您更好地解释一下“...T 类型在运行时被擦除”。
      猜你喜欢
      • 2012-02-27
      • 2020-05-07
      • 2010-11-24
      • 2010-10-16
      • 2014-07-06
      • 2012-02-10
      • 2010-10-30
      • 1970-01-01
      相关资源
      最近更新 更多