对 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")
我目前在 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")