繁体   English   中英

Java泛型类型解析

[英]Java generic type resolution

我最近开始使用Java,但在处理泛型类型时仍然感到困惑。 以下是我遇到一些问题的简化方案。

我有一个类,它使用Class类型作为Key和该类对象的集合来保存Map:

public class GenericListInside {
    private Map<Class<?>, List<?>> mapping = new HashMap<>();

    public <T> void addListing(Class<T> clazz, List<T> object) {
        mapping.put(clazz, object);
    }
}

我可以毫无问题地调用addListing:

GenericListInside gli = new GenericListInside();
List<Foo> list = new ArrayList<>(); 
//add something to list
gli.addListing(Foo.class, list); 

现在我决定创建一个Class来提供流畅的界面。 就像是:

with(Foo.class).use(list);

然后我来了:

public class FluidInserter<T> {
    Class<T> clazz;
    GenericListInside gli = new GenericListInside();

    public FluidInserter with (Class<T> clazz) {
        this.clazz = clazz;
        return this;
    }

    public <T> void use(List<T> list) {
        gli.addListing(clazz, list);
    }
}

但是当我尝试编译时,我得到:

错误:(18,12)java:类util.GenericListInside中的方法addListing不能应用于给定的类型;
required:java.lang.Class,java.util.List
发现:java.lang.Class,java.util.List
原因:推断类型不符合等式约束
推断:T
等式约束:T,T

这个消息有点令人困惑......任何人都可以弄清楚我做错了什么?

流体构建器的泛型方法采用泛型方法参数,但该参数与clazz字段的类型不同,尽管名称重叠。

只需从方法声明中删除<T> ,同时将List<T>保留为参数:

public void use(List<T> list) {
    gli.addListing(clazz, list);
}

FluidInserter主题说明:您不希望在with方法中返回原始类型的FluidInserter 将返回类型更改为:

public FluidInserter<T> with (Class<T> clazz)

问题在于使用的定义use(List<T> list)方法:

public <T> void use(List<T> list) {
    gli.addListing(clazz, list);
}

在这里,您通过引入具有相同名称的方法范围的类型参数来隐藏类范围的类型参数T

它应该是:

public void use(List<T> list) {
    gli.addListing(clazz, list);
}

它应该编译得很好,因为T已经在类级别定义。

你的问题是以下声明:

public <T> void use(List<T> list) {
    gli.addListing(clazz, list);
}

由于您已经在类级别定义了泛型<T> ,因此无需对该方法进行泛化。

我建议你将签名更改为以下内容:

public void use(List<? extends T> list) {
    // same logic here
}

另外,作为附注,我认为您还应该使GenericListInside通用。 现在, mapping字段的定义允许键和值中的混合类型,这是您不想要的。

编辑

您可以像这样在GenericListInside添加泛型:

public class GenericListInside<T> {

    private final Map<Class<T>, List<T> mapping = new HashMap<>();

    public void addListing(Class<T> clazz, List<T> list) {
        mapping.put(clazz, list);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM