【问题标题】:Java Generics: Comparing the class of Object o to <E>Java 泛型:将 Object o 的类与 <E> 进行比较
【发布时间】:2023-03-22 01:24:01
【问题描述】:

假设我有以下课程:

public class Test<E> {
    public boolean sameClassAs(Object o) {
        // TODO help!
    }
}

如何检查o 是否与E 相同?

Test<String> test = new Test<String>();
test.sameClassAs("a string"); // returns true;
test.sameClassAs(4); // returns false;

我无法从 (Object o) 更改方法签名,因为我正在覆盖超类,因此无法选择我的方法签名。

我也不想继续尝试强制转换,然后在失败时捕获产生的异常。

【问题讨论】:

    标签: java generics


    【解决方案1】:

    Test 的实例没有关于 E 在运行时的信息。因此,您需要将Class&lt;E&gt; 传递给Test 的构造函数。

    public class Test<E> {
        private final Class<E> clazz;
        public Test(Class<E> clazz) {
            if (clazz == null) {
                throw new NullPointerException();
            }
            this.clazz = clazz;
        }
        // To make things easier on clients:
        public static <T> Test<T> create(Class<T> clazz) {
            return new Test<T>(clazz);
        }
        public boolean sameClassAs(Object o) {
            return o != null && o.getClass() == clazz;
        }
    }
    

    如果您想要“instanceof”关系,请使用 Class.isAssignableFrom 而不是 Class 比较。请注意,E 需要是非泛型类型,出于同样的原因,Test 需要 Class 对象。

    有关 Java API 中的示例,请参阅 java.util.Collections.checkedSet 和类似内容。

    【讨论】:

    • 我宁愿将类与等号进行比较。还是有特殊原因使用 == ?
    • 它们是等价的。 IMO == 更容易阅读(尽管它确实意味着读者必须了解类型)。内联之前速度要快一些。现在,我似乎没有测试的是 null clazz。
    【解决方案2】:

    我一直使用的方法如下。这是一种痛苦,有点难看,但我还没有找到更好的。您必须在构造时传递类类型,因为当泛型被编译时,类信息会丢失。

    public class Test<E> {
        private Class<E> clazz;
        public Test(Class<E> clazz) {
           this.clazz = clazz;
        }
        public boolean sameClassAs(Object o) {
            return this.clazz.isInstance(o);
        }
    }
    

    【讨论】:

      【解决方案3】:

      我只能让它像这样工作:

      public class Test<E> {  
      
          private E e;  
      
          public void setE(E e) {  
              this.e = e;  
          }
      
          public boolean sameClassAs(Object o) {  
      
              return (o.getClass().equals(e.getClass()));  
          }
      
          public boolean sameClassAs2(Object o) {  
              return e.getClass().isInstance(o);  
          }
      }
      

      【讨论】:

        【解决方案4】:

        我只是想做同样的事情,我刚刚意识到的一个巧妙的技巧是你可以尝试强制转换,如果强制转换失败,则会抛出 ClassCastException。你可以抓住它,然后做任何事情。

        所以你的 sameClassAs 方法应该如下所示:

        public boolean sameClassAs(Object o) {
            boolean same = false;
            try {
                E t = (E)o;
                same = true;
            } catch (ClassCastException e) {
                // same is false, nothing else to do
            } finally {
                return same;
            }
        }
        

        【讨论】:

        • 不,不会的。那是未经检查的演员表。它永远不会抛出异常。在运行时,"t" 具有 E 的擦除类型,它只是 Object,因此没有执行强制转换。
        • 你是对的。这将节省我以后大量的故障排除,因为编译似乎很好。
        猜你喜欢
        • 2015-01-31
        • 2019-05-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多