Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java泛型转换和使用_Java_Generics_Capture - Fatal编程技术网

Java泛型转换和使用

Java泛型转换和使用,java,generics,capture,Java,Generics,Capture,我对泛型继承有点问题。下面是依赖关系树: public class Attributes { } public abstract class Feature<T extends Attributes> { private T attributes; public T getAttributes() { return attributes; } public void setAttributes(T attributes)

我对泛型继承有点问题。下面是依赖关系树:

public class Attributes {
}

public abstract class Feature<T extends Attributes> {
    
    private T attributes;

    public T getAttributes() {
        return attributes;
    }

    public void setAttributes(T attributes) {
        this.attributes = attributes;
    }
}

public abstract class AbstractFeatureRepository<T extends Feature<? extends Attributes>> {
    public abstract String getType();

    public abstract boolean create(T feature);
}
公共类属性{
}
公共抽象类特征{
私人T属性;
公共T getAttributes(){
返回属性;
}
公共void集合属性(T属性){
this.attributes=属性;
}
}
公共抽象类AbstractFeatureRepositoryTry

private static void createFeature(Class clazz,Feature此代码:

featureRepositories.get(type)

根据
java.util.Map
的文档,返回
Map
中类型为
V
的对象。在代码中,如果一个映射中只有2个对象(或者N个对象,其中N是一个小数字,您在注释中提到4),则表示表达式的类型为
AbstractFeatureRepository,并且使用固定键来指示特定类型,使用贴图会使其变得非常困难

映射必须是同质类型的,即所有键都有一个公共超类型,所有值都有一个公共超类型。您面临的问题是希望键的类型与值的类型相关:这可以通过类型安全的异构容器来实现(本质上是:一个你构造的映射,这样你就可以对类型之间的关系施加约束)。但是对于所描述的问题来说,即使这样也太复杂了

改为使用两(N)个字段:

public class Controller {
    private final NodeRepository nodeRepository = new NodeRepository();
    private final LinkRepository linkRepository = new LinkRepository();
这仍然是一种映射:键是字段,值是字段值

但这样做的好处是保留了存储库的具体类型,因此可以将这些类型传递给方法:

private <A extends Attributes> void createFeature(AbstractFeatureRepository<A> repo, Feature<A> feature) {
    repo.create(feature);
}
为了尽可能接近您的原始代码,我进行了三到四次相对较小的重构

但最重要的变化出现在
Controller.createFeature()


我必须承认,您试图解决的问题对我来说并不十分清楚。因此,我仅根据我的一般Java知识做出了一些假设。请告诉我解决方案是否满足您的要求?

以下是我使用的方法:

public class Controller {

    private final Map<Class<?>, AbstractFeatureRepository<? extends Feature>> featureRepositories;

    public Controller3(List<AbstractFeatureRepository<? extends Feature>> featureRepositories) {
        this.featureRepositories = featureRepositories.stream()
                .collect(Collectors.toMap(AbstractFeatureRepository::getClazz, Function.identity()));
    }

    public Node createNode() {
        Node newNode = new Node();
        createFeature(Node.class, newNode);
        return newNode;
    }

    public Link createLink() {
        Link newLink = new Link();
        createFeature(Link.class, newLink);
        return newLink;
    }

    private <T extends Feature> void createFeature(Class<T> clazz, T feature) {
        AbstractFeatureRepository<T> repository = getRepository(clazz);
        repository.create(feature);
    }
    
    @SuppressWarnings("unchecked")
    private <T extends Feature, V extends AbstractFeatureRepository<T>> V getRepository(Class<T> clazz) {
        return (V) featureRepositories.get(clazz);
    }

    public static void main(String[] args) {
        Controller3 controller = new Controller3();
        controller.createLink();
    }
}

公共类控制器{

私有最终映射如果您通过构造知道,
featureRepositories.get(“节点”)
只能是一个显式强制转换的
NodeRepository
。事实上,这无论如何都是一个选中强制转换,因此如果不是,它将立即失败。我的第一个建议是摆脱这种过度工程。看起来你刚刚学会了继承和泛型,迫不及待地想把它们放到不需要它们的地方o对于实际问题,
get(“节点”)
不是类型安全的,
get(Node.class)
将是,因为
类是泛型的。但是,我再次认为这是一个巨大的设计问题,泛型问题只是一个次要的子包。你能给我们提供你的AbstractRepository类吗?也许问题就在那里。@AndriyKucher尽管Kayaman对过度工程的评论,你可能会找到一个“类型安全的异构容器”会有帮助的。它是用有效的Java描述的;我相信你可以在网络上的其他地方找到它。我的评论也不是故意的。我只是对这些问题有一种持续的似曾相识。请阅读我的更新1。尽管我认为我是按照repo支持的类型进行转换,但仍然没有运气。尽管这是一个非常好和详细的nswer(你有我的投票权)此代码给我的错误与原始代码相同:/是的,只要涉及到?您仍然有一些麻烦-这是关于为什么会发生这种情况的一般指南,真正的修复需要重新设计,超出问题中可用的代码。我不认为这是我需要的。据我所知,您建议通过Reposi类tory作为一个参数,所以以后我可以强制转换到它。但我不想使用实现,而是想在抽象级别上使用repos。这与代码中的方法相同,但不是传递sting,而是传递类,并强制转换存储库。我不使用实现
createFeature
函数不依赖于
AbstractFeatureRepository
的具体实现,谢谢,但我不想在这个控制器中存储每个Repo,这就是我试图摆脱的。目前有4个存储库,但以后会更多,所以我计划为它们添加一种存储,以便它们将自动注册到Spring.您可以用更严格的边界替换我演示中的所有
s。例如
void createFeature(…)
AbstractFeatureRepo,AbstractFeatureRepo
,它们的类型信息在运行时完全可用。你知道,我选择了类似的解决方案。事实上,这是涉及cast的情况。这是我在这里看到的唯一解决方案,我真的很惊讶,在这种非常简单的情况下,这是一种痛苦。我稍后会发布我的解决方案,但它与您的建议。不幸的是,您对其安全性的解释不能让我感到方便。T extends功能实际上可以是任何东西。“T extends功能实际上可以是任何东西”-您能看到我之前评论中的其他建议吗?“您对其安全性的解释不能让我感到方便“-若要了解我的解释,。您将看到“错误:方法m()已定义…”。。。“它已经被定义了,因为
声明的类型和
声明的类型是完全相同的类型。如果该示例不能让您确信
t extends Feature
CAP#1 extends Feature
也是完全相同的类型,那么什么都不会。代码-如您在此处所示-:
行:27类型参数T不在类型变量T的范围内
行:32类型参数T不在类型变量T的范围内
。单击页面顶部的绿色开始按钮可查看编译失败。此外,您已将
功能
声明为泛型类。但在任何地方,y
    public Link createLink() {
        Link newLink = new Link();
        createFeature(Link.class, newLink);
        return newLink;
    }
    
    
    private <T extends Feature> void createFeature(Class<T> class1, T feature) {
        AbstractFeatureRepository<? extends Feature> abstractFeatureRepository = featureRepositories.get(feature.getClass());
        abstractFeatureRepository.create(abstractFeatureRepository.getClazz().cast(feature));
    }
featureRepositories.get(type)
List<? extends Number> list = new ArrayList<Integer>();
List<Number> list = new ArrayList<Integer>();
List<? extends Number> list = new ArrayList<Integer>();
Number n = Double.valueOf(5.0);
list.add(n);
public <T extends Attribute> void createFeature(Class<T> typeDesired, Feature<T> feature) {
    featureRepositories.get(type).create(typeDesired.cast(feature));
}
public class Controller {
    private final NodeRepository nodeRepository = new NodeRepository();
    private final LinkRepository linkRepository = new LinkRepository();
private <A extends Attributes> void createFeature(AbstractFeatureRepository<A> repo, Feature<A> feature) {
    repo.create(feature);
}
public Node createNode() {
    Node newNode = new Node();
    newNode.getAttributes().setStartPoint("Berlin");
    // Or, easier, nodeRepository.create(newNode);
    createFeature(nodeRepository, newNode);
    return newNode;
}

public Link createLink() {
    Link newLink = new Link();
    newLink.getAttributes().setUri("/home/local");
    // Or, easier, linkRepository.create(newNode);
    createFeature(linkRepository, newLink);
    return newLink;
}
private <T extends Feature<?>> void createFeature(Class<T> class1, T feature) {
    AbstractFeatureRepository<T> abstractFeatureRepository = (AbstractFeatureRepository<T>)featureRepositories.get(feature.getClass());
    abstractFeatureRepository.create(feature);
}
Controller.java:31: error: incompatible types: AbstractFeatureRepository<CAP#1> cannot be converted to AbstractFeatureRepository<T>
    AbstractFeatureRepository<T> abstractFeatureRepository = featureRepositories.get(feature.getClass());

where T is a type-variable:
    T extends Feature<?> declared in method <T>createFeature(Class<T>,T)
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Feature<?> from capture of ? extends Feature<?>
1 error
Node: [NodeAttributes - Start Point: 'Berlin']

Link: [LinkAttributes - URI: 'urn::foo::bar']
public class Controller {

    private final Map<Class<?>, AbstractFeatureRepository<? extends Feature>> featureRepositories;

    public Controller3(List<AbstractFeatureRepository<? extends Feature>> featureRepositories) {
        this.featureRepositories = featureRepositories.stream()
                .collect(Collectors.toMap(AbstractFeatureRepository::getClazz, Function.identity()));
    }

    public Node createNode() {
        Node newNode = new Node();
        createFeature(Node.class, newNode);
        return newNode;
    }

    public Link createLink() {
        Link newLink = new Link();
        createFeature(Link.class, newLink);
        return newLink;
    }

    private <T extends Feature> void createFeature(Class<T> clazz, T feature) {
        AbstractFeatureRepository<T> repository = getRepository(clazz);
        repository.create(feature);
    }
    
    @SuppressWarnings("unchecked")
    private <T extends Feature, V extends AbstractFeatureRepository<T>> V getRepository(Class<T> clazz) {
        return (V) featureRepositories.get(clazz);
    }

    public static void main(String[] args) {
        Controller3 controller = new Controller3();
        controller.createLink();
    }
}