我可以使用调用类中的泛型类型吗?

Vin*_*ent 5 java generics

我正在刷新我的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)

如果有的话,我思考的根本缺陷是什么?我应该采取什么方法?

jbx*_*jbx 8

首先,请记住,泛型是编译时的事情,而不是运行时.

现在在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.


new*_*cct 1

编辑后:

    // 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)