对 java 中的方法使用 'diamond' 表示法

Using 'diamond' notation for methods in java

我目前在 java 从事基于组件的架构管理系统的工作。我当前检索附加到对象的组件的实现是这样的:

// ...

private final HashMap<Class<? extends EntityComponent>, EntityComponent> components;

// ...

public <T extends EntityComponent> T getComponent(Class<T> component)
  {
    // ... some sanity checks
    if (!this.hasComponent(component))
    {
        // ... some exception handling stuff
    }

    return component.cast(this.components.get(component));
  }

// ...

现在,这工作正常,但我不得不写

object.getComponent(SomeComponent.class)

每次我需要访问组件时。

是否可以利用泛型将语法转换为更符合

的语法?
object.getComponent<SomeComponent>()

,利用菱形运算符指定class,而不是将组件的class作为参数传递给方法?

我知道这并不是什么大事,但我想使常用代码的语法尽可能漂亮/紧凑会大有帮助。

很遗憾,因为类型参数在 Java 中是 "erased"。这意味着它们仅在编译时可用(编译器使用它们对代码进行类型检查),但在 运行 时不可用。

因此,当您的代码为 运行ning 时,<SomeComponent> 类型参数不再存在,因此您的代码无法执行任何基于(if/else 等)的操作关于它的价值。

换句话说:

  • 在编译时,您的方法调用如下所示:object.getComponent<SomeComponent>()
  • 但是编译后你的方法调用看起来像这样object.getComponent()。没有类型参数了。

所以,是的,不幸的是你仍然需要传递一个 Class 对象,或者类似的东西(例如参见 [​​=45=]),如果你需要做一些依赖于类型参数的事情在 运行 时间。

Class 解决方法起作用的原因是它松散地表示类型参数,因为类型检查器确保其实例符合类型参数,但它是一个对象因此可用在 运行 时间也是如此 - 与类型参数不同。

注意:Class 技巧对类型参数内的类型参数不起作用,例如 Class<List<Something>>,因为在 运行 时间 List<Something>List<OtherThing>相同的是class,即List。所以你不能制作一个 Class 标记来区分这两种类型。据我所知,可以使用 "Super Type Tokens" 来解决这个问题(他们利用了存在擦除异常的事实:对于通用 classes 的 subclasses,类型- "extending" superclass 时使用的参数实际上在 运行 时通过反射可用。(也有更多例外:))。

(相关 google 项:"Erasure"、"Reification"、"Reified generics")