带有泛型静态工厂的Java泛型拼图器
我最近开始为一个项目编写一个通用对象映射程序,但遇到了一些我不太理解的问题。鉴于以下情况:带有泛型静态工厂的Java泛型拼图器,java,generics,Java,Generics,我最近开始为一个项目编写一个通用对象映射程序,但遇到了一些我不太理解的问题。鉴于以下情况: public class G<X> { public G(Class<X> c) { } public void m(X x) { } public static <T> G<T> create(Class<T> c) { return new G<T>(c); } public static voi
public class G<X> {
public G(Class<X> c) { }
public void m(X x) { }
public static <T> G<T> create(Class<T> c) {
return new G<T>(c);
}
public static void main(String[] args) {
Object o = ""; // irrelevant!
G<?> t = create(o.getClass());
t.m(o);
}
}
inconvertible types
found : G<capture#155 of ? extends java.lang.Object,Y<capture#155 of ? extends java.lang.Object>>
required: G<java.lang.Object,Y<java.lang.Object>>
如果我将泛型对象类传递给create
,这似乎会中断
请注意,我的实际实现将所有FooDTO
类从一个泛型超类扩展而来,即Mapper
的签名实际上类似于Mapper
。我认为这与这里无关
编辑2:
实际上,建议更改行gt=create(o.getClass())
togt=(G)创建(o.getClass())代码>在这个上下文中工作
不幸的是,我没有意识到我的类更复杂这一事实实际上会产生影响。这里有一个更完整的例子(我为这个零碎的问题道歉):
公共类Y{
}
公共类别G{
公共G类(c类、s类){
}
公共空间m(X X){
}
公共静态G创建(c类){
类s=null;//通过某种反射魔法找到它
返回新的G(c,s);
}
公共静态void main(字符串[]args){
对象o=”“;//不相关!
G您已经从传递了Class
对象,该对象返回一个Class
,这意味着您必须声明t
为G
当变量的泛型类型参数是通配符时,不能使用泛型类型参数调用方法。编译器不知道通配符真正是哪个特定类,因此在调用此类方法时无法保证类型安全。这与不能在列表上调用add
的原因相同
要编译它,必须使用类文字,以避免使用class
,并声明t
没有通配符
G<Object> t = create(Object.class);
将编译。由于您指定的是G
,javac希望找出泛型是什么(它们代表什么类)。将语句更改为gt=create(o.getClass());
修复错误
capture
错误通常意味着编译器无法找出类
现在还不清楚您想做什么……也许这些信息对您的帮助更大……您正在创建一个G
,然后将其分配给G
类型的变量。调用的方法将使用泛型类型的变量,而
不会接受任何内容。如果您将该变量更改为G
它会起作用。您这里有一个消费者
公共静态类G{
公共G(类)你想实现什么?让我再添加一些评论。用G@sinelaw没有区别。我不认为简单地将G
更改为G
编译。由于G
的构造函数的编写方式,create(o.getClass())
正在创建一个实际有效的。不过我有一个跟进。更改我的SO。如果我不知道类型,并且只有一个对象的引用怎么办?这就是我的全部问题。如果我传递object.class
我会丢失所有运行时类型信息。删除泛型并不能解决问题,它只会将其清除地毯。是的,编译器无法识别类型,但删除泛型会删除泛型类型安全性,因此编译器甚至没有机会。但这完全改变了类。构造函数选择class
的唯一原因可能是因为将x
传递给.m()很重要
是该类的一个实例。如果您将其更改为ClassAccepting,因为在我的情况下,它工作得很好。如果我发现一个案例出现问题,我将更新我的问题。@newacct,您是对的,这会更改类G
,但请考虑一下:您始终可以传递扩展X
到mx
不是该类的一个实例。我的意思是,将类型为class
的类c
传递到G
的构造函数中有什么意义?OP的代码不显示该类中的任何代码,所以从字面上看,我们可以删除该p参数。但是人们会猜测,类c
与G
的第一个类型参数匹配有一些要求。特别是,类型X
用于另一个地方:方法m
中的参数X
的类型。因此,可以合理地想象,在m
必须是c
的一个实例。在实践中,c
参数很可能来自getClass()
在m()
的参数上调用的getClass()
,但编译器在此呈现中无法保证这一点。
public class Y<T> {
}
public class G<X, Z extends Y<X>> {
public G(Class<X> c, Class<Z> s) {
}
public void m(X x) {
}
public static <T, S extends Y<T>> G<T, S> create(Class<T> c) {
Class<S> s = null; // find this via some reflection magic
return new G<T, S>(c, s);
}
public static void main(String[] args) {
Object o = ""; // irrelevant!
G<? extends Object, Y<? extends Object>> t = create(o.getClass());
t.m(o);
}
}
inconvertible types
found : G<capture#155 of ? extends java.lang.Object,Y<capture#155 of ? extends java.lang.Object>>
required: G<java.lang.Object,Y<java.lang.Object>>
G<Object, Y<Object>> t = (G<Object, Y<Object>>) create(o.getClass());
java: inconvertible types
required: G<java.lang.Object,Y<java.lang.Object>>
found: G<capture#1 of ? extends java.lang.Object,Y<capture#1 of ? extends java.lang.Object>>
G<Object> t = create(Object.class);
t.mo(o);
public static class G<X, Z extends Y<X>> {
public G(Class<? extends X> c, Class<Z> s) {}
public void m(X x) {}
public static <T, S extends Y<T>> G<T, S> create(Class<? extends T> c) {
Class<S> s = null; // find this via some reflection magic
return new G<T, S>(c, s);
}
public static void main(String[] args) {
Object o = ""; // irrelevant!
create(o.getClass()).m(o);
}
}