【问题标题】:checking type of reference in generics java检查泛型java中的引用类型
【发布时间】:2016-09-27 07:04:11
【问题描述】:

我目前正在用 java(基于回合的 RPG)构建游戏,并且在库存 UI 中遇到问题。也许我的问题是众所周知的或者有一个简单的解决方案,但是我没有接受过任何培训,我仍然会问这个问题。

在选择一个项目后显示库存时,我检查该项目是否实现了SpecificItemWorker 接口,即作用于必须传递给其takeAction() 方法的特定GameObject。在选择必须传递的对象时,我会显示所有可能的候选对象供用户选择。例如,假设用户选择了一个UpgradeParchment,它作用于任何实现Upgradable 接口的对象。在这里,我启动了一个ItemSelector,它显示了库存中实现Upgradable 的所有项目。但是对于不同的类,对象需要实现的接口才能成为可能的候选对象会有所不同。(请注意,某些对象作用于游戏环境而不是特定对象,但我们在这里不考虑这种情况。 )。现在不是在switch case 语句中硬编码可能的接口,我希望它是动态的。我尝试使用泛型,但它不允许检查对象是否是类型参数的instanceof . 以下代码给出了编译错误:

package ui;

import objects.Collectable;

public class ItemSelector<T> {
    public void test(Collectable ob) {
        if (ob instanceof T) {// compile error
            // do work
        }
    }
}

有人知道如何实现吗?感谢您的帮助。

寻求快速回复, 谢谢。

编辑: testAction() 方法中的参数将是 Collectable 类型,因为在我的库存类中,只有一个 Collectable 对象列表。同样,在我的测试方法中,我已经更新了类型。虽然它是次要的更改,不便之处见谅。Collectable也是一个接口。

【问题讨论】:

    标签: java generics types reference instanceof


    【解决方案1】:

    由于运行时类型擦除,您需要向类提供所谓的类型令牌

    public class ItemSelector<T> {
        private final Class<T> clazz;
        public ItemSelector(Class<T> clazz) {
            this.clazz = clazz;
        }
    
        public void test(GameObject ob) {
            if (clazz.isInstance(ob)) {// use token to check type
                // do work
            }
        }
    }
    

    这需要将类对象传递给构造函数,通常通过传递类字面量,例如MyClass.class

    【讨论】:

      【解决方案2】:

      有一种方法可以使用 class.getTypeName() 检查类型。

      我假设 SpecificItemWorker 是一个游戏对象,如代码所示。

      package stackoverflow.question39718130;
      
      public class SpecificItemWorker extends GameObject {
      }
      

      package stackoverflow.question39718130;
      
      public class ItemSelector<T> {
      
          private T t;
      
          public ItemSelector(final T t) {
              this.t = t;
          }
      
          public T getT() {
              return t;
          }
      
          public void test(final GameObject ob) {
              /*if (ob instanceof T) {// compile error
                  // do work
              }*/
      
              if (t.getClass().getTypeName() == ob.getClass().getTypeName()) {
                  System.out.println("Grab item.");
              } else {
                  System.err.println("No item found.");
              }
          }
      }
      

      有一个测试例子可以通过GameObject

      package stackoverflow.question39718130;
      
      public class GameObjectTest {
      
          public static void main(final String[] args) {
              specificItemWorkerTest();
          }
      
          public static void specificItemWorkerTest() {
              final GameObject specificItemWorker = new SpecificItemWorker();
      
              final ItemSelector<GameObject> selector = new ItemSelector<>(specificItemWorker);
              selector.test(specificItemWorker);
          }
      }
      

      我希望我对SpecificItemWorker 的理解正确。请让我知道这是否适合您的解决方案。

      【讨论】:

      • class.getTypeName()方法返回类类型信息。但不能用于通过IS-A关系测试。另外,SpecificItemWorker是一个接口。它用于决定用户选择使用的对象是否需要另一个Collectable对象来处理。
      • 这在多个层面上都不正确,尤其是使用== 比较字符串,这永远不会是真的
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-18
      • 2016-10-10
      相关资源
      最近更新 更多