我想写一个接受数组和其他东西的泛型方法。每种都可以是任何类型,但它们必须是相同的。我尝试了这个,但我仍然可以在方法中输入任何东西。
public static <T> boolean arrayContains(T[] array, T object){
return Arrays.asList(array).contains(object);
}
我可以使用arrayContains(new String[]{"stuff"}, new Pig())
调用此方法,但我只希望它接受arrayContains(new String[]{"stuff"}, "more stuff")
答案 0 :(得分:3)
你要做的是棘手的,因为任何数组(基本数组除外)都是Object[]
,所以你注意到,该方法将始终接受任何数组和任何对象。
解决这个问题的一种方法是传递一个明确的Class
对象,就像这个
public static <T> boolean arrayContains(T[] array, T object, Class<T> clazz)
然后你可以写
arrayContains(new String[]{"stuff"}, "more stuff", String.class)
但不是
arrayContains(new String[]{"stuff"}, new Pig(), String.class)
答案 1 :(得分:2)
你不能。
或换句话说,任何数组和任何引用已满足您的要求,&#34; x类型数组和另一个类型与数组相同的varable #34;,因为任何数组是&#34;类型为Object
&#34;的数组,而任何引用属于同一类型({ {1}})。
您想要的不是类型安全目的。假设有一种语言功能可以做你想做的事情。它只能在参数表达式的编译时类型上运行。但总有人可以这样做:
Object
或
Object[] foo = anyArrayExpression;
Object bar = anyReferenceExpression;
arrayContains(foo, bar);
(顺便说一句,这些都没有做任何可疑或不安全的事情。在Java中,向上转换始终是100%安全和合法的操作。)
所以任何数组和任何引用总是可以传递给你的函数,并且你的函数总是需要处理任何类型的数组和任何类型对象的实际对象。所以你的功能什么都没有。
即使您将其限制为某种类型arrayContains((Object[])anyArrayExpression, (Object)anyReferenceExpression);
的子类型,并且您的函数只需要X
和X[]
,但实际上仍然可以传入的引用所指向的对象的运行时类是X
和Y[]
,其中Z
和Y
是Z
的无关子类型。这只是Java类型系统如何工作的一个事实。因此,无论您如何操作,您的函数总是必须处理可能与其他对象的运行时类无关的数组的运行时组件类型。 (唯一的例外是如果X
是最终的,那么它没有子类,但那么你的限制将毫无意义,因为它将一直都是真的。)
答案 2 :(得分:0)
下一步怎么样?
public static <A, E extends A> boolean arrayContains(A[] array, E object){
return Arrays.asList(array).contains(object);
}
在这种情况下,第二个参数的类型必须扩展(或相同)数组元素的类型。
答案 3 :(得分:0)
这就是我最终要做的事情。
public static boolean arrayContains(Object[] array, Object object) {
if (array.getClass().getComponentType() != object.getClass()) {
throw new IllegalArgumentException("Type of array and object are not equal! " + array.getClass().getComponentType().getName() + " != " + object.getClass().getName()); //$NON-NLS-1$ //$NON-NLS-2$
}
return Arrays.asList(array).contains(object);
}
答案 4 :(得分:-2)
您需要提供多个参数化类型,然后在它们不匹配时执行某些操作。
public static <T, S> boolean arrayContains(T[] array, S object){
System.out.println("array.class: " + array.getClass().getComponentType().getName());
System.out.println("object.class: " + object.getClass().getName());
System.out.println("array.class == object.class: " + (array.getClass().getComponentType() == object.getClass()));
// TODO: do something if the types don't match
return Arrays.asList(array).contains(object);
}