我想使用泛型类型来确保方法的参数类型相同,如下所示:
public static <T> void x(T a, T b)
我认为传递给此方法的两个参数(a和b)必须始终具有相同的类型。但令我惊讶的是,我能够将任何类型的参数(甚至原语)传递给方法x,就像T被擦除为Object一样,无论传递什么参数。
到目前为止我发现的唯一解决方法是使用&#39; extends&#39;像这样:
public static <T, U extends T> void x(T a, U b)
但是虽然我能忍受它,但这不是我想要的。
有没有办法使用泛型类型来强制方法的所有参数的类型?
答案 0 :(得分:29)
如果我理解正确,一种方法是explicitly specify the type of T而不是让编译器推断它的类型是最直接的超类,如果两个不同类型的对象作为参数传入。拿这样的东西,例如:
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) {
}
}
答案 1 :(得分:21)
如果我理解你的问题,你想要这个:
x(10, "x");
在编译时失败。 现在考虑这样做:
Integer i = 10;
String s = "x";
Object o1 = i;
Object o2 = s;
x(o1, o2);
在这种情况下,它们都是对象 - 相同的类型。我认为没有任何方法可以真正强制执行您想要的操作 - 当您将参数转换为Object时,始终可以使用两种不同的类型调用它而不会出现任何警告/错误。
您可以像这样使用它来指定要使用的类型:
ClassName.<Type>x(obj1, obj2);
这可能是唯一的方法。
答案 2 :(得分:14)
为什么这首先成为问题对我来说有点模糊。我怀疑你反而误解了类型系统有用的方法。
<T> void x(T a, T b)
我们可以做些什么?嗯,不是很多。在x
的正文中,T
与Object
相同,因此我们只能在toString
和a
上执行类似调用b
的操作打印它们。
确实没有实际的原因 a
和b
必须具有相同的类型。只是他们有一些共同的类型,那个类型是Object
或它的子类型。事实上,<T> void x(T a, T b)
实际上根本不需要是通用的,没有明确的理由。
a
和b
的实际类型,因为它无论如何也无法使用它们。a
和b
的实际类型,因为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;
}
答案 3 :(得分:12)
调用方法时,可以显式指定类型参数。例如:
<String>x("hello", "world");
但是,如果你没有明确指定type-parameter并且只依赖于Java的类型推断功能,那么我认为你不仅可以泛型,但总的来说。
方法参数的类型不是具体类型,而是表示 适用类型集 的东西(即使这个< em> set 只能包含一种类型,例如final
类。
例如,这种方法:
public void x(Something a) { }
表示一个方法,该参数应该是类型的类型,它与Something
(即Something
及其所有子类型)兼容。 / p>
同样适用于泛型。
答案 4 :(得分:10)
据推测,您并未以通用方式调用泛型方法,因此将其视为对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
。
答案 5 :(得分:7)
这对我有用
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);
}