gpt4 book ai didi

java - 返回泛型父类(super class)

转载 作者:行者123 更新时间:2023-11-30 02:27:35 24 4
gpt4 key购买 nike

对于一堆带有泛型的包装类,我的继承结构遇到了一些问题。这基本上是结构:

public abstract class SuperWrapper<E extends Super>{
private E wrappedObject;
public E getWrappedObject(){
return wrappedObject;
}
}

public abstract class MiddleWrapper<E extends Middle> extends SuperWrapper<E>{}

public class SubAWrapper extends MiddleWrapper<SubA>{}

public class SubBWrapper extends MiddleWrapper<SubB>{}

包装的类遵循相同的继承结构,因此基本上:

public class Super{}

public class Middle extends Super{}

public class SubA extends Middle{}

public class SubB extends Middle{}

这些包装类不是我的,不能更改(这就是包装类的原因)。此结构对于大多数用途都非常有效,但是当我想要一个方法返回 SubAWrapper 或 SubBWrapper 时,会出现一些问题。

这是我迄今为止尝试过的:

public static MiddleWrapper<?> findMiddle(String id){
SubAWrapper a = new SubAWrapper();
SubBWrapper b = new SubBWrapper();
if(returnSubA){
return a;
} else{
return b;
}
}

这可以编译并工作,但 SonarQube 会警告在返回类型中使用通配符,并且从我的谷歌搜索来看,这不是应该忽略的警告之一。

另一种方式:

public static <E extends Middle> MiddleWrapper<E> findMiddle(String id){
SubAWrapper a = new SubAWrapper();
SubBWrapper b = new SubBWrapper ();
if(returnSubA){
return (MiddleWrapper<E>) a;
} else{
return (MiddleWrapper<E>) b;
}
}

这可以编译并使用当前代码,但是,这似乎很危险。如果调用者像这样使用这个方法:MiddleWrapper<SubA> middle = findMiddle("1");它可以正常编译,但如果 findMiddle 尝试返回 SubBWrapper,则在运行时会出现 ClassCastException。我认为可行但没有的的是:

public static MiddleWrapper<Middle> findMiddle(String id){
SubAWrapper a = new SubAWrapper ();
SubBWrapper b = new SubBWrapper ();
if(returnSubA){
return (MiddleWrapper<Middle>) a; //Compile error here
} else{
return (MiddleWrapper<Middle>) b; //and here
}
}

所以我的问题基本上是,是否有正确的方法来编写可以编译、运行并遵循最佳实践的 findMiddle 方法?

为了额外加分,有没有办法编写一个方法,使其返回一个包含 SubA 和 SubB 的列表。像这样但没有通配符:

public static List<MiddleWrapper<?>> getAllMiddle(){
List<MiddleWrapper<?>> ret = Lists.newArrayList();
ret.add(new SubAWrapper());
ret.add(new SubBWrapper());
return ret;
}

ps。目前我们仍在使用 Java 6,但计划于明年升级到 Java 8,因此使用 Java 7-8 功能的解决方案最终仍然有用。

最佳答案

MiddleWrapper是一个通用类,参数化为 Middle类:

public abstract class MiddleWrapper<E extends Middle> extends SuperWrapper<E>{}

如果您想提供一个返回 List 的方法的MiddleWrapper MiddleWrapper 至少有两个不同的泛型类型,你没有太多选择。

如果不需要对Middle设置任何约束可能返回的子类。
您展示的方法很好:

public static List<MiddleWrapper<?>> getAllMiddle() {
List<MiddleWrapper<?>> ret = Lists.newArrayList();
ret.add(new SubAWrapper());
ret.add(new SubBWrapper());
return ret;
}

你说:

This compiles and works but SonarQube warns about the use of a wildcard in a return type and from my googling it's not one of the warnings that should be ignored.

为什么使用?MiddleWrapper<?>会是一个坏习惯吗?
类(class)MiddleWrapper是通用的,在您的方法中,您可以返回任何类型的 Middle用作通用。
这是此用例的做法。

现在,如果您需要对 Middle 设置约束可能返回的子类。
例如一些Middle子类,但不是其他一些子类。

您可以引入一个扩展 Middle 的中间类,使 SubASubB扩展它并输入 List与它在 getAllMiddle()方法。

public class ValidMiddle extends Middle {...}

public class SubA extends ValidMiddle{...}

public class SubB extends ValidMiddle{...}

方法应该是:

public static List<MiddleWrapper<? extends ValidMiddle>> getAllMiddleWithMoreSpecificType() {
List<MiddleWrapper<? extends ValidMiddle>> ret = Lists.newArrayList();
ret.add(new SubAWrapper());
ret.add(new SubBWrapper());
return ret;
}

请注意,对于应该操作此声明类型的客户端来说,这种方式有点冗长:

 List<MiddleWrapper<? extends ValidMiddle>> listOfWrappers = getAllMiddle();

关于java - 返回泛型父类(super class),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45236128/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com