genericsJava方法的generics是否可以用来强制参数的types?

我想使用genericstypes来确保方法的参数是相同types的,如下所示:

public static <T> void x(T a, T b) 

我会假定传递给这个方法的两个参数(a和b)总是必须是相同的types。 但令我惊讶的是,我能够将任何types的参数(甚至是基元)传递给方法x,就好像T被擦除为Object,不pipe传递了什么参数。

我发现迄今为止唯一的解决方法是使用像这样的“扩展”:

 public static <T, U extends T> void x(T a, U b) 

但是虽然我能忍受,但这不是我想要的。

有没有办法使用genericstypes来强制方法的所有参数的types?

如果我正确理解你的问题,你需要这个:

 x(10, "x"); 

在编译时失败。 现在考虑这样做:

 Integer i = 10; String s = "x"; Object o1 = i; Object o2 = s; x(o1, o2); 

在这种情况下,它们都是对象 – 相同的types。 我不认为有什么办法可以真正实现你想要的东西 – 当你将参数转换为Object时,总是可以用两种不同的types调用它,而不会有任何警告/错误。

你可以像这样使用它来指定你想要使用的types:

 ClassName.<Type>x(obj1, obj2); 

而且它是唯一的办法。

如果我理解正确,一种方法是明确指定T的types,而不是让编译器在两个不同types的对象作为参数传入的情况下推断它的types是最直接的超类。 采取这样的事情,例如:

 public class Test { public static void main(String[] args) { Test.x(5.0, 5); // This works since type is inferred to be Number Test.<Integer>x(5, 5); // This works since type is stated to be Integer Test.<Integer>x(5.0, 5); // This doesn't; type is stated to be Integer and Double is passed in } public static <T> void x(T a, T b) { } } 

为什么这应该是问题首先是对我来说是模糊的。 我怀疑你错误地理解了types系统有用的方法。

我们可以用<T> void x(T a, T b)什么? 那么,不是很多。 在x的主体内部, TObject是一样的,所以我们只能在ab上调用toString来打印它们。

ab必须有相同的types是没有实际的原因 a 。 只是它们有一些共同的types,而这种types是Object或它的一个子types。 事实上,为什么<T> void x(T a, T b)实际上需要是通用的。

  • 方法体不关心ab的实际types是什么,因为它无法使用它们。
  • 调用网站并不关心ab的实际types是什么,因为x是一个void方法,所以它是一个黑洞。

对于有结果的方法更为典型,如<T> List<T> Arrays.asList(T...)

 // This will cause a compile error because // the type inferred must be compatible // with the return assignment. List<Integer> r = Arrays.asList(1, 1.0); 

还是一个界限:

 // We don't care what the actual types of // a and b are, just that we can call bar() // on them. // Note: this method does not need to be generic. <T extends Foo> void x(T a, T b) { a.bar(); a.bar(); } 

或者是一种断言某种关系的边界:

 // We don't care what the actual types of // a and b are, just that we can compare // them to each other. <T extends Comparable<T>> T max(T a, T b) { return (a.compareTo(b) < 0) ? b : a; } 

调用方法时,可以显式指定types参数。 例如:

  <String>x("hello", "world"); 

但是,如果明确指定types参数并仅依赖于Java的types推断function,那么我不认为您可以,不仅在generics中,而且在一般情况下。

方法参数的types不是一个具体的types,而是表示一组适用的types (例如,在final类的情况下,这个集合只能包含一个types)。

例如,这个方法:

 public void x(Something a) { } 

表示一个方法,该参数应该是一组types ,它与Something (即Something及其所有子types)兼容。

generics也是如此。

据推测,你不是以通用的方式调用generics方法,所以它被看作是对x(Object a, Object b)的调用。 在这个例子中:

 public class Test { static <T> void x(T a, T b) { } public static void main(String[] args) { x(1, 2); // compiles Test.<String>x(1, 2); // does not compile Test.<String>x("a", "b"); // compiles } } 

对x的第一次调用并不是一般地编译的。 第二个调用等于TString ,所以它失败,因为12不是Strings 。 第三次调用编译,因为它正确传入Strings

这对我有效

 public static <T> void x(T a, T b, Class<T> cls) { } 

现在编译

 public static void main(String[] args) throws Exception { x(1, 2, Integer.class); } 

而这不

 public static void main(String[] args) throws Exception { x(1, "", Integer.class); }