奇怪的Java泛型

奇怪的Java泛型,java,generics,Java,Generics,这是什么意思 HashBiMap<Character, Integer> charOcc = HashBiMap.<Character, Integer> create(); HashBiMap charOcc=HashBiMap。创建(); 它使用Character和Integer作为类型参数调用通用静态方法(create())。例如,如果您正在查看Google Java集合,则声明具有以下签名: public static <K,V> HashBiMap

这是什么意思

HashBiMap<Character, Integer> charOcc = HashBiMap.<Character, Integer> create();
HashBiMap charOcc=HashBiMap。创建();

它使用
Character
Integer
作为类型参数调用通用静态方法(
create()
)。例如,如果您正在查看Google Java集合,则声明具有以下签名:

public static <K,V> HashBiMap<K,V> create()
公共静态HashBiMap create()
部分本身指定这些是方法的类型参数

C#中的等效调用将是:

HashBiMap.Create<Character, Integer>();
HashBiMap<Character, Integer>.Create();
HashBiMap.Create();
HashBiMap.Create();
这取决于您希望它是非泛型类型中的泛型方法,还是泛型类型中的非泛型方法


Java中类型参数和类型参数的定位是不直观的。

这意味着
static create()
方法具有类型参数,如:

public static <Character, Integer> HashBiMap<Character, Integer> create() {..}
publicstatichashbimap create(){..}
create()
是一种通用方法。由于它是静态的,并且没有参数(因此没有类型推断),因此您可以通过奇怪的
语法来告诉它泛型参数是什么


编辑:在这种特定情况下,这实际上是不必要的;编译器可以从左侧推断泛型类型。但有时在其他情况下,这是必要的,比如这个问题:

大概是你认为奇怪的右手边(RHS)

HashBiMap.<Character, Integer> create();
HashBiMap。创建();
通常,在调用泛型静态方法时,只需要在LHS上使用类型参数。但是,有时静态方法并不像您所期望的那样推断类型参数。在这些情况下,您还可以在RHS上使用类型参数,以便将类型参数强制为您想要的任何类型。这称为显式类型参数

下面是一个类型参数推断不正确的示例(改编自优秀的“有效Java”一书):

例子 给定静态方法

public static <E> Set<E> union(Set<? extends E> s1, Set<? extends E> s2)

publicstaticsetunion(SetHashBiMap)可能有一个方法

public static <K,V> HashBiMap<K,V> create(){...}
publicstatichashbimap create(){…}
使用语法

HashBiMap<Character, Integer> charOcc = HashBiMap.<Character, Integer> create();
HashBiMap charOcc=HashBiMap.create();

您正在为K传递字符,为V传递整数。

如果希望避免提供形式参数的繁琐语法,可以使用强制转换来输入提示

以你为例,

Set<Integer> integers = ... ;
Set<Double> doubles = ... ;
Set<Number> numbers = union((Set<Number>)integers, doubles);
设置整数=;
设置双精度=;
集合数=并集((集合)整数,双精度);
这将被编译器接受并避免使用

Set<Number> numbers = Union.<Number>union(integers, doubles);
Set number=Union.Union(整数,双精度);

另一方面,调用代码的结构遵循定义的结构-首先是perameters类型,其次是方法名称。@Bozho:但是相对于点的位置是奇怪的,我也不喜欢它在定义中:)@Downvoter:你投票了吗,因为我不喜欢Java语法,还是因为你认为我说的不准确?事实上,这有必要吗?我认为编译器应该能够从左边推断泛型类型参数。应该但不会。在Java中,您必须声明所有内容。@mcv-您错了-编译器可以从左边推断类型。如果我没记错的话,Google Collections在其实用程序类中利用了这一事实<代码>映射myMap=Maps.newHashMap()
HashBiMap实际上来自Google Collections,该方法专门用于创建它的实例时,不必在右侧编写类型参数。
HashBiMap<Character, Integer> charOcc = HashBiMap.<Character, Integer> create();
Set<Integer> integers = ... ;
Set<Double> doubles = ... ;
Set<Number> numbers = union((Set<Number>)integers, doubles);
Set<Number> numbers = Union.<Number>union(integers, doubles);