如何从擦除中转换泛型类型
How to Cast Generic Type from Erasure
我有一个 parent class, Parent
, 有两个 child class, A
和 B
.我有一个接口 Function<Type1 extends Parent,Type2 extends Parent>
,它允许程序员编写一个特定的函数 Type2 of(Type1 t)
,它将 Type1 转换为 Type2。界面被包装在 class、Wrapper<Type1 extends Parent,Type2 extends Parent>
中,其中包含有用的信息,例如 Class<Type1> type1Class
等
当我尝试为 Wrapper
class、Wrapper<Type1,Type2> add(Wrapper<Type1,Type2> additionalWrapper)
实现 add
方法时,我的问题出现了。我正在尝试将两个 Function
相加,但由于擦除,我很难输出 Type2
而不是 Parent
。
如何让 add
方法输出 Type2
而不是 Parent
?
public class Parent {
protected int value;
public void setValue(int x){ value = x; }
public int getValue(){ return value; }
public Parent(){}
public Parent(int x){setValue(x);}
public Parent add(Parent p){return null;}
}
public class A extends Parent{
public A(){ setValue(1); }
public A(int x){ setValue(x); }
public A(B b){ setValue( b.getValue()); }
public A add(A a){ return new A( getValue()+a.getValue()); }
public A add(B b){ return new A( getValue()*b.getValue()); }
}
public class B extends Parent{
public B(){ setValue(2); }
public B(int x){ setValue(x); }
public B(A a){ setValue(a.getValue()); }
public B add(B b){ return new B(getValue() + b.getValue()); }
public B add(A a){ return new B(getValue() * a.getValue()); }
}
public interface Function <Type1 extends Parent, Type2 extends Parent> {
public Type2 of(Type1 t);
}
public class Wrapper<Type1 extends Parent, Type2 extends Parent> {
protected Function<Type1,Type2> function;
protected Class<Type1> type1Class;
protected Class<Type2> type2Class;
public Wrapper(final Class<Type1> t1, final Class<Type2> t2, Function<Type1,Type2> x) {
type1Class = t1;
type2Class = t2;
function = x;
}
public Type2 of(Type1 t){
return function.of(t);
}
public Wrapper<Type1,Type2> add(final Wrapper<Type1,Type2> additionalWrapper){
return new Wrapper<Type1,Type2>( type1Class, type2Class, new Function<Type1,Type2>(){
public Type2 of(Type1 t){
try{
Type2 term = function.of(t);
Type2 summand = additionalWrapper.of(t);
Type2 sum = (Type2) term.add(summand); ///Problem happens here. term and summand are both interpreted as Parent by the erasure, I think, and therefore add outputs null, setting sum=null.
return sum;
} catch(Exception e){
e.printStackTrace();
return null;
}
}
});
}
}
public class Main {
public static void main(String[] args){
Wrapper<A, B> wrapper1 = new Wrapper<A, B>(A.class,B.class,new Function<A, B>() {
@Override
public B of(A a) {
return new B(a);
}
});
Wrapper<A, B> wrapper2 = new Wrapper<A, B>(A.class,B.class,new Function<A, B>() {
@Override
public B of(A a) {
B b = new B();
return b.add(a);
}
});
Wrapper<A,B> wrapper3 = wrapper1.add(wrapper2);
A a = new A(3);
B b = wrapper3.of(a);
System.out.println(b.getValue()); ///Error happens here because b was set to null and therefore doesn't contain int value.
}
}
基本上你没有两种方法去添加A和B,违反了多态或SOLID原则。您可以像下面这样构建您的 类 -
class A extends Parent{
public A(){ setValue(1); }
public A(int x){ setValue(x); }
public A(B b){ setValue( b.getValue()); }
@Override
public A add(Parent a){ return new A( getValue()+a.getValue()); }
}
class B extends Parent{
public B(){ setValue(2); }
public B(int x){ setValue(x); }
public B(A a){ setValue(a.getValue()); }
@Override
public B add(Parent b){ return new B(getValue() + b.getValue()); }
}
因为add
是在Parent中定义的,所以只需要一个实现即可。在当前场景中,由于 Class A
中 add
的签名与 Parent
中的签名不匹配,因此 方法未被覆盖全部
如果在添加方法中添加 @Override
,您就会知道。编译器会抛出错误。
希望对您有所帮助。
正如 Louis Wasserman 在评论中建议的那样,我需要在单个重写函数中使用 instanceof Parent add(Parent p)
。
在类A和B中,我需要有这个功能:
@Override
public Parent add(Parent p){
if (p instanceof A){
A a = (A) p;
return add(a);
}
else if (p instanceof B){
B b = (B) p;
return add(b);
}
else return null;
}
我有一个 parent class, Parent
, 有两个 child class, A
和 B
.我有一个接口 Function<Type1 extends Parent,Type2 extends Parent>
,它允许程序员编写一个特定的函数 Type2 of(Type1 t)
,它将 Type1 转换为 Type2。界面被包装在 class、Wrapper<Type1 extends Parent,Type2 extends Parent>
中,其中包含有用的信息,例如 Class<Type1> type1Class
等
当我尝试为 Wrapper
class、Wrapper<Type1,Type2> add(Wrapper<Type1,Type2> additionalWrapper)
实现 add
方法时,我的问题出现了。我正在尝试将两个 Function
相加,但由于擦除,我很难输出 Type2
而不是 Parent
。
如何让 add
方法输出 Type2
而不是 Parent
?
public class Parent {
protected int value;
public void setValue(int x){ value = x; }
public int getValue(){ return value; }
public Parent(){}
public Parent(int x){setValue(x);}
public Parent add(Parent p){return null;}
}
public class A extends Parent{
public A(){ setValue(1); }
public A(int x){ setValue(x); }
public A(B b){ setValue( b.getValue()); }
public A add(A a){ return new A( getValue()+a.getValue()); }
public A add(B b){ return new A( getValue()*b.getValue()); }
}
public class B extends Parent{
public B(){ setValue(2); }
public B(int x){ setValue(x); }
public B(A a){ setValue(a.getValue()); }
public B add(B b){ return new B(getValue() + b.getValue()); }
public B add(A a){ return new B(getValue() * a.getValue()); }
}
public interface Function <Type1 extends Parent, Type2 extends Parent> {
public Type2 of(Type1 t);
}
public class Wrapper<Type1 extends Parent, Type2 extends Parent> {
protected Function<Type1,Type2> function;
protected Class<Type1> type1Class;
protected Class<Type2> type2Class;
public Wrapper(final Class<Type1> t1, final Class<Type2> t2, Function<Type1,Type2> x) {
type1Class = t1;
type2Class = t2;
function = x;
}
public Type2 of(Type1 t){
return function.of(t);
}
public Wrapper<Type1,Type2> add(final Wrapper<Type1,Type2> additionalWrapper){
return new Wrapper<Type1,Type2>( type1Class, type2Class, new Function<Type1,Type2>(){
public Type2 of(Type1 t){
try{
Type2 term = function.of(t);
Type2 summand = additionalWrapper.of(t);
Type2 sum = (Type2) term.add(summand); ///Problem happens here. term and summand are both interpreted as Parent by the erasure, I think, and therefore add outputs null, setting sum=null.
return sum;
} catch(Exception e){
e.printStackTrace();
return null;
}
}
});
}
}
public class Main {
public static void main(String[] args){
Wrapper<A, B> wrapper1 = new Wrapper<A, B>(A.class,B.class,new Function<A, B>() {
@Override
public B of(A a) {
return new B(a);
}
});
Wrapper<A, B> wrapper2 = new Wrapper<A, B>(A.class,B.class,new Function<A, B>() {
@Override
public B of(A a) {
B b = new B();
return b.add(a);
}
});
Wrapper<A,B> wrapper3 = wrapper1.add(wrapper2);
A a = new A(3);
B b = wrapper3.of(a);
System.out.println(b.getValue()); ///Error happens here because b was set to null and therefore doesn't contain int value.
}
}
基本上你没有两种方法去添加A和B,违反了多态或SOLID原则。您可以像下面这样构建您的 类 -
class A extends Parent{
public A(){ setValue(1); }
public A(int x){ setValue(x); }
public A(B b){ setValue( b.getValue()); }
@Override
public A add(Parent a){ return new A( getValue()+a.getValue()); }
}
class B extends Parent{
public B(){ setValue(2); }
public B(int x){ setValue(x); }
public B(A a){ setValue(a.getValue()); }
@Override
public B add(Parent b){ return new B(getValue() + b.getValue()); }
}
因为add
是在Parent中定义的,所以只需要一个实现即可。在当前场景中,由于 Class A
中 add
的签名与 Parent
中的签名不匹配,因此 方法未被覆盖全部
如果在添加方法中添加 @Override
,您就会知道。编译器会抛出错误。
希望对您有所帮助。
正如 Louis Wasserman 在评论中建议的那样,我需要在单个重写函数中使用 instanceof Parent add(Parent p)
。
在类A和B中,我需要有这个功能:
@Override
public Parent add(Parent p){
if (p instanceof A){
A a = (A) p;
return add(a);
}
else if (p instanceof B){
B b = (B) p;
return add(b);
}
else return null;
}