Java 如何用更具体的类型替换参数化类型

Java 如何用更具体的类型替换参数化类型,java,generics,type-parameter,Java,Generics,Type Parameter,考虑以下设置: 我们有一个接口超类型,其参数化如下: public interface SuperType<V> { } public interface SuperType<V, S extends SuperType<V, S>> { public S doSomething(); } 让我们考虑超类型< /代码>: 现在,我们想为超类型定义另一个方法,该方法采用更具体的类型参数V,并返回相同的实现类型S,但现在用W extends V参数化

考虑以下设置:

我们有一个接口
超类型
,其参数化如下:

public interface SuperType<V> {
}
public interface SuperType<V, S extends SuperType<V, S>> {

    public S doSomething();
}

让我们考虑<代码>超类型< /代码>:

现在,我们想为
超类型
定义另一个方法,该方法采用更具体的类型参数
V
,并返回相同的实现类型
S
,但现在用
W extends V
参数化:

public interface SuperType<V, S extends SuperType<V, S>> {

    public S doSomething();

    public <W extends V, T extends SuperType<W, T>> T doMoreSpecific(Class<W> typeToken);
}
公共接口超类型{
公众剂量测定法();
公共T域特定(类typeToken);
}
此新接口定义旨在支持:

Object s = "Java Generics";
SubType<Object> x = new SubType<>(s);
SubType<String> y = x.doMoreSpecific(String.class);
objects=“Java泛型”;
子类型x=新的子类型;
子类型y=x.doMoreSpecific(String.class);
在这里,我很难实现
子类型
。作为一个实现,我想提供的是:

public class SubType<V> implements SuperType<V, SubType<V>> {

    private final V value;

    public SubType(V value) { this.value = value; }

    public SubType<V> doSomething() { return this; };

    public <W extends V> SubType<W> doMoreSpecific(Class<W> typeToken) {
        return new SubType<>((W) value);
    }
}
公共类子类型实现超类型{
私人最终V值;
公共子类型(V值){this.value=value;}
公共子类型doSomething(){返回此;};
公共子类型doMoreSpecific(类typeToken){
返回新的子类型((W)值);
}
}
我的问题是:

我应该如何在type
SuperType
中定义方法
doMoreSpecific()
的签名,以便
子类型实现超类型
是否可接受

否则,哪个实现和接口方法定义会起作用


或者,为什么我们不能在Java中使用以下签名来实现这一点呢?

<W extends V> SuperType<W, ?> doMoreSpecific(Class<W> typeToken);
超类型域特定(类typeToken);

可能有一些不安全的情况,虽然我还没有找到,任何批评是欢迎的

您不能按照代码建议的方式执行操作,您有一个类型化方法:
W
是从参数类型推断出来的,但参数类型仅在调用站点已知。ie在接口
SuperType
(必须实现)中没有一个方法
doMoreSpecific()
版本可以指定


最接近的方法是使
W
成为
SuperType
的泛型类型参数,但是您的实现将只适用于一个类
W
,这将是typeToken冗余,这显然不是您想要的。

我不知道您在
doMoreSpecific
后面的确切意图是什么,但是如果只是从
子类型
子类型
进行强制转换,则可以执行以下操作(尽管这不是很好的实践…):


注3:这完美地展示了泛型实际上是如何工作的:它们所做的只是在您所需的位置自动插入类型转换。

只是一个commnet,在接口中,所有方法都是抽象的,因此,显式定义是多余的
S extends
是无效的语法,这使您的问题难以理解…我希望我修复了语法错误。我懒得定义IDE中的所有类型:)。抱歉。@Harmlez我的IDE不同意
S extends
部分。@Harmlez您将使您的代码变得不可读且太复杂。您的解决方案解决了问题,但我无法在抽象类或默认方法中实现该方法。如果我这样做,我将失去具体实现的类型,这可能会实现更多的接口。在我的问题中,我也没有提到这一点,但我尽量避免透露太多细节。尽管如此,如果没有更好的解决方案,我将采用您的解决方案。@Harmlez-您可以将旧定义保留为
doMoreSpecific0
;而
domorespectic
只需调用
domorespectic
;我和一位同事讨论了我的问题,他告诉我,我想要的不是Java,而是Scala:一个类型构造函数。在我看来,我面临的问题是,我无法从参数化类型中提取原始类型,以形成要返回的新类型。例如,如果我可以从
S
中提取原始类型,比如说
raw:S
,那么我可以如下定义签名:
public raw:S extends SuperType domaorespecific(Class typeToken)public class SubType<V> implements SuperType<V, SubType<V>> {

    private final V value;

    public SubType(V value) { this.value = value; }

    public SubType<V> doSomething() { return this; };

    public <W extends V> SubType<W> doMoreSpecific(Class<W> typeToken) {
        return new SubType<>((W) value);
    }
}
<W extends V> SuperType<W, ?> doMoreSpecific(Class<W> typeToken);
Object s = "Java Generics";
SubType<Object> x = new SubType<>(s);
SubType<String> y = (SubType<String>) (SubType<?>) x;
    ArrayList<?> lo = new ArrayList<Object>();
    ArrayList<Integer> li = (ArrayList<Integer>) lo;
    ArrayList<String> ls = (ArrayList<String>) lo;

    li.add(5);
    ls.add("five");

    System.out.println(lo);        // prints "[5, five]"

    System.out.println(li.get(0)); // prints "5"
    System.out.println(li.get(1)); // ClassCastException

    System.out.println(ls.get(0)); // ClassCastException
    System.out.println(ls.get(1)); // prints "five"