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
的主体内部, T
和Object
是一样的,所以我们只能在a
和b
上调用toString
来打印它们。
a
和b
必须有相同的types是没有实际的原因 a
。 只是它们有一些共同的types,而这种types是Object
或它的一个子types。 事实上,为什么<T> void x(T a, T b)
实际上需要是通用的。
- 方法体不关心
a
和b
的实际types是什么,因为它无法使用它们。 - 调用网站并不关心
a
和b
的实际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的第一次调用并不是一般地编译的。 第二个调用等于T
到String
,所以它失败,因为1
和2
不是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); }