我正在刷新我的Java并阅读泛型.由于他们在我的Java课程中没有得到广泛的对待,因此我仍然无法理解它,所以请在回答时牢记这一点.
首先,我很确定我所尝试的是不可能的.但是,我想知道我的想法是错的,以及我应该如何实现我想要的.
我正在尝试做的是操纵一个对象,该对象从另一个不了解实例化类型的类实现泛型接口.因此,我有类似以下类:
public interface CalledInterface<E> {
public E get() { ... }
public set(E e) { ... }
}
public class Called implements CalledInterface<String> {
...
}
Run Code Online (Sandbox Code Playgroud)
现在我想做的是:
public class Caller {
protected CalledInterface<?> c;
public Caller (CalledInterface<?> arg) {
c = arg;
}
public void run(){
// I can do this:
c.set(c.get());
// But I'd want to be able to do something like:
<?> element = c.get();
c.set(element);
}
}
Run Code Online (Sandbox Code Playgroud)
如果有的话,我思考的根本缺陷是什么?我应该采取什么方法?
首先,请记住,泛型是编译时的事情,而不是运行时.
现在在Caller你的定义中Called c.Called被定义为CalledInterface<String>自动实现,Called在编译时生成以下方法:
String get();
void set(String e); //i assume you wanted to return void
Run Code Online (Sandbox Code Playgroud)
所以基本上这没有意义:
<?> element = c.get();
Run Code Online (Sandbox Code Playgroud)
本Caller类甚至不知道Called在内部使用泛型,因为它,Called只是处理字符串.
UPDATE
根据你的评论,因为你不想直接Caller使用Called但是CalledInterface首先要做的就是改变它的类型c.在这种情况下,您不应该使用泛型,因为泛型的全部要点是在具有不同类型的不同场景中使用相同的类(在编译时再次确定),强制执行类型而不重复代码.
如果我理解正确您不想限制Caller使用String,那么您需要做的是更改CalledInterface为不使用泛型,并将方法更改为:
Object get();
void set(Object o);
Run Code Online (Sandbox Code Playgroud)
这就是我们在Java 1.4中使用Generics之前做的事情.你显然冒着没有类型安全的风险,所以想一想你的想法是否真的让设计更有意义,因为它可能不是因为你无论如何都必须做一个instanceof以检查类型以Object有用的方式使用(即访问它的方法).
另一方面,如果您只是将c成员(和构造函数参数Caller)更改为:
CalledInterface<String> c;
Run Code Online (Sandbox Code Playgroud)
您Caller将与CalledInterface实现进行交互,而不是实现,同时仍然是类型安全的.所以你仍然可以传递一个实例Called并将其设置为c.
编辑后:
// I can do this:
c.set(c.get());
Run Code Online (Sandbox Code Playgroud)
不,你不能。它不会与cbeing一起编译CalledInterface<?>。(你有尝试过吗?)
为此,您可以使用“捕获助手”:
private static <T> void helper(CalledInterface<T> c) {
c.set(c.get());
}
public void run(){
helper(c);
}
Run Code Online (Sandbox Code Playgroud)
这也解决了你的第二个问题:
private static <T> void helper(CalledInterface<T> c) {
T element = c.get();
c.set(element);
}
public void run(){
helper(c);
}
Run Code Online (Sandbox Code Playgroud)