【发布时间】:2018-12-18 15:09:05
【问题描述】:
我有一个通用接口
public interface MyInterface<T> {
T method(T input);
}
以及它的几个实现,通过像这样的普通类
public class MyClass<T> implements MyInterface<T> {
@Override
public T method(T input) {
T output = input; // whatever
return output;
}
}
和匿名类(见下文)。现在我想测试这些实现:
class TestClass1 {
// ...
}
class TestClass2 {
final int n;
final String s;
TestClass2(int n, String s) {
this.n = n;
this.s = s;
}
// ...
}
public class TestGenericImplementation {
private static <T> void makeTest(T testObject, MyInterface<T> impl) {
T output = impl.method(testObject);
if (output == null)
throw new NullPointerException();
// verify output further
}
// Question 1. How to specify the parameter here properly?
public static void testImplementation(MyInterface impl) {
// Question 2. How to avoid compiler warning about unchecked cast below?
// Doesn't work if impl is of type MyInterface<?> above
makeTest(new TestClass1(), impl);
makeTest(new TestClass2(1, "ABC"), impl);
// Ugly typecasts. Compiler complains.
makeTest(new TestClass1(), (MyInterface<TestClass1>) impl);
makeTest(new TestClass2(1, "ABC"), (MyInterface<TestClass2>) impl);
}
public static void main(String[] args) {
// Question 3. How to pass the interface argument here?
// Works but issues compiler warning about raw type
testImplementation(new MyClass());
testImplementation(new MyInterface() {
@Override
public Object method(Object input) {
return null; // whatever
}
});
// Looks ugly
testImplementation(new MyClass<Object>());
testImplementation(new MyInterface<Object>() {
@Override
public Object method(Object input) {
return null;
}
});
/* Diamond operator appeared only in Java 7,
* while generics were introduced in Java 5.
* What was the recommended way to solve this problem between 2004 and 2011?
* Besides that, this doesn't work for anonymous classes.
*/
testImplementation(new MyClass<>());
testImplementation(new MyInterface<>() { // Doesn't work
@Override
public Object method(Object input) {
return null;
}
});
testImplementation(x -> x); // Lambda exprssions are for simple cases only
}
}
问题是编译器由于从通用接口转换到其具体版本而发出一系列错误和警告(我需要使用具体类 TestClass1 和 TestClass2 来代替泛型类型变量T)。是否可以完全避免这些警告?如果不是(即只能被压制),是否会因此产生任何陷阱?
【问题讨论】:
-
Java 中的泛型永远不会被具体化。什么意思?
-
@Michael 我的意思是在
testImplementation()中从T转换到TestClass1和TestClass2。如果这里 reify 是一个错误的术语,请纠正我。
标签: java generics reification