我不是专业的Java程序员,所以这个问题可能很简单,但我在网上搜索了答案,但到目前为止一无所获。
假设我们在 Java 中有一个泛型类:
public class C1 <T, U> {
public /*TYPE*/ f(T t, U u) {
return t.g(u)
}
问题是 - 如何确定此通用示例的结果类型?有没有办法写出像typeof(t.g(u))
这样的东西?
按原样调用t.g(u)
T
因为它是一个无界类型。您需要对其设置编译时限制,以便编译器知道哪些方法可用。否则,您将只能调用Object
方法,因为编译器唯一可以推断T
的是扩展Object
。
例如,如果您有一个接口G<U>
要调用的g
方法:
public interface G<U> {
R g(U u);
}
然后,您将指定该T extends G<U>
,以便调用g()
。现在您知道g()
的返回类型是什么:它是 R
.
public class C1<T extends G<U>, U> {
public R f(T t, U u) {
return t.g(u)
}
}
如果您希望g()
的结果依赖于T
和U
类型,则可以执行以下操作:
public interface G<T, U> {
T g(U u);
}
public class C1<T, U> {
public T f(G<T, U> g, U u) {
return g.g(u)
}
}
您的代码不会按原样编译,因为没有什么可以告诉编译器t
有一个成员函数g
。您需要将类型参数T
声明为扩展某些基类或接口,这些基类或接口确实声明了g()
方法。返回类型将是g
的返回类型(可能是另一种参数类型)。
例如:
public interface Foo<X, Y> {
X g(Y u);
}
public class C1 <T extends Foo<X, U>, U, X> {
public X f(T t, U u) {
return t.g(u);
}
}
请注意,如果返回类型X
也是泛型的,则需要在类 C1
中为其声明一个单独的类型参数。或者,您可以声明C1
以统一处理单个参数化类型(例如,String
× String
→ String
):
public class C1 <T extends Foo<T, T>> {
public T f(T t, T u) {
return t.g(u);
}
}
其他变化也是可能的。
如果要强制 t 具有方法 g,则必须像这样声明您的类:
public class C1<T extends Ginterface, U extends SecInterface> {
}
并且此方法的返回类型将是 Ginterface 中 g 函数的返回类型