简体   繁体   English

java泛型边界类型

[英]java generics bounds type

Are following two signatures same? 以下两个签名是否相同?

public static <T> void work(Class<T> type, T instance);

and

public static <T, S extends T> void work(Class<T> type, S instance);

No, the two signatures are not the same. 不,这两个签名不一样。 From the Java Language Spec, Chapter 8 : Java语言规范,第8章

Two methods have the same signature if they have the same name and argument types. 如果两个方法具有相同的名称和参数类型,则它们具有相同的签名。

Two method or constructor declarations M and N have the same argument types if all of the following conditions hold: 如果满足以下所有条件,则两个方法或构造函数声明M和N具有相同的参数类型:

  • They have the same number of formal parameters (possibly zero) 它们具有相同数量的形式参数(可能为零)
  • They have the same number of type parameters (possibly zero) 它们具有相同数量的类型参数 (可能为零)

... ...

Since your two methods do not share the same number of type parameters, the signatures are not the same. 由于您的两种方法不共享相同数量的类型参数,因此签名不同。

In practical cases where the methods are called with implicit type parameters, they might be seen as interchangeable. 在使用隐式类型参数调用方法的实际情况中,它们可能被视为可互换。 But this is only at the source level, never at the binary level. 但这只是在源级别,而不是在二进制级别。 In other words, if you had the one-type-parameter version of work() in class Foo and it was called by a method in class Bar , and then you switched to the two-type-parameter version of work() and recompiled Foo , you would also need to recompile Bar . 换句话说,如果你在类Foo有一个work() -parameter版本的work()并且它被类Bar的方法调用,然后你切换到work()的两个类型参数版本并重新编译Foo ,你还需要重新编译Bar

Edit 编辑

@onepotato asks: @onepotato问道:

If they don't have the same signatures, then why when I copy and paste them in one class Eclipse tell me that they have the same method signature? 如果他们没有相同的签名,那么为什么当我将它们复制并粘贴到一个类Eclipse时告诉我他们有相同的方法签名?

There is a difference between two signatures being equal and two signatures conflicting (being "override-equivalent"). 两个签名相等且两个签名冲突 (“覆盖等效”)之间存在差异。 Two signatures conflict if one is a subsignature of the other. 如果一个是另一个的子签名,则两个签名冲突。 This is explained later in the same section: 稍后将在同一部分对此进行说明:

Two method signatures m1 and m2 are override-equivalent iff either m1 is a subsignature of m2 or m2 is a subsignature of m1. 如果m1是m2的子签名或m2是m1的子签名,则两个方法签名m1和m2是覆盖等价的。

It is a compile-time error to declare two methods with override-equivalent signatures in a class. 在类中声明具有覆盖等效签名的两个方法是编译时错误。

The signature of a method m1 is a subsignature of the signature of a method m2 if either: 方法m1的签名是方法m2的签名的子签名,如果:

  • m2 has the same signature as m1, or m2与m1具有相同的签名,或
  • the signature of m1 is the same as the erasure (§4.6) of the signature of m2. m1的签名与m2签名的擦除(§4.6)相同。

Just looking at the bytecode we can see that they do not: 只看字节码我们就可以看到它们没有:

For the first: 为了第一:

// access flags 0x9
// signature <T:Ljava/lang/Object;>(Ljava/lang/Class<TT;>;TT;)V
// declaration: void work<T>(java.lang.Class<T>, T)
public static work(Ljava/lang/Class;Ljava/lang/Object;)V
 L0
  LINENUMBER 86 L0
  RETURN
 L1
  LOCALVARIABLE type Ljava/lang/Class; L0 L1 0
  // signature Ljava/lang/Class<TT;>;
  // declaration: java.lang.Class<T>
  LOCALVARIABLE instance Ljava/lang/Object; L0 L1 1
  // signature TT;
  // declaration: T
  MAXSTACK = 0
  MAXLOCALS = 2

For the second: 对于第二个:

// access flags 0x9
// signature <T:Ljava/lang/Object;S:TT;>(Ljava/lang/Class<TT;>;TS;)V
// declaration: void work<T, ST>( extends java.lang.Class<T>, S)
public static work(Ljava/lang/Class;Ljava/lang/Object;)V
 L0
  LINENUMBER 86 L0
  RETURN
 L1
  LOCALVARIABLE type Ljava/lang/Class; L0 L1 0
  // signature Ljava/lang/Class<TT;>;
  // declaration: java.lang.Class<T>
  LOCALVARIABLE instance Ljava/lang/Object; L0 L1 1
  // signature TS;
  // declaration: S
  MAXSTACK = 0
  MAXLOCALS = 2

For any set of arguments, if a valid choice of T exists for 对于任何参数集,如果存在有效的T选择

<T> void work(Class<T> type, T instance)

then a valid choice of T and S exists for 然后存在有效的TS选择

<T, S extends T> void work(Class<T> type, S instance)

and vice versa. 反之亦然。

So from a theoretical point of view, they are equivalent. 所以从理论的角度来看,它们是等价的。 However, due to limited inference, it may be the case that, when type arguments are not given, one will compile while the other doesn't for certain arguments. 但是,由于推理有限,可能会出现这样的情况:当没有给出类型参数时,将会编译而另一个不会针对某些参数进行编译。 In such a case, it is always possible to explicitly specify a valid set of type arguments for the case that doesn't compile, to make it compile. 在这种情况下,始终可以为不编译的情况显式指定一组有效的类型参数,以使其进行编译。

Since they are equivalent, an API should always prefer the simpler form, ie without the S . 由于它们是等价的,API应该总是更喜欢更简单的形式,即没有S

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM