【问题标题】:Referring to the defining class in generics引用泛型中的定义类
【发布时间】:2015-11-24 06:43:10
【问题描述】:

我尝试创建一个定义树的类,其中树节点可以标记,并且标记由后代节点继承,基本上创建了事物的分类法。

然后我有了一个想法,有时标签不应该被继承(企鹅不能飞的异常),但我想为此创建一个单独的类,因为可能有一些应用程序处理异常的开销是浪费了。所以我创建了另一个类,NodeWithException。我希望这棵树具有相同类型的节点,但要像 Node 一样具有可扩展性。

我的问题在于

public class NodeWithException<TYPE_PARAM extends NodeWithException<?>> 

它将引入原始类型。但如果我不放“?”在那里,我会陷入无限递归的兔子洞。有没有更优雅的解决方案可以避免使用原始类型?

代码可以在下面阅读或从这里下载:https://drive.google.com/file/d/0Bzgrcf36fidPWVlFdk9qdmdfT1E/view?usp=sharing

我的课:

Node.java

package tags_and_tax.model;

import java.util.HashSet;
import java.util.Set;

public class Node<TYPE_PARAM extends Node> {
    TYPE_PARAM parent = null;
    final Set<TYPE_PARAM> children = new HashSet<>();
    final Set<Tag> tags = new HashSet<>();

    public void addChild(TYPE_PARAM child){
        child.setParent(this);
    }

    public void  setParent(TYPE_PARAM newParent){
        if (parent != null){
            parent.children.remove(this);
        }
        parent = newParent;
        newParent.children.add(this);
    }
    public Set<Tag> getAllTags(){
        Set<Tag> result = new HashSet<>(tags);
        TYPE_PARAM node = parent;
        while(node != null){
            result.addAll(node.tags);
            node = (TYPE_PARAM) node.parent;
        }
        return result;
    }

    public Set<Tag> getTags(){
        return tags;
    }

}

NodeWithExceptions.java

package tags_and_tax.model;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;


@SuppressWarnings("rawtypes")
public class NodeWithException<TYPE_PARAM extends NodeWithException<?>> extends Node<TYPE_PARAM> {
    final Set<Tag> removeTags = new HashSet<>();

    public Set<Tag> getRemoveTags() {
        return removeTags;
    }

    @SuppressWarnings("unchecked")
    @Override
    public Set<Tag> getAllTags(){
        Set<Tag> result = new HashSet<>(tags);
        LinkedList<TYPE_PARAM> parents = new LinkedList<>();
        parents.add((TYPE_PARAM) this);
        TYPE_PARAM node = parent;
        while(node != null){
            parents.add(node);
            node = (TYPE_PARAM) node.parent;
        }

        while(parents.size() > 0){
            node = parents.removeLast();
            result.addAll(node.tags);
            result.removeAll(node.removeTags);            
        }        
        return result;
    }    

}

Tag.java(这不是很有趣,只是为了完整起见)

package tags_and_tax.model;

import java.util.HashMap;
import java.util.Map;

/**
 * Should be a "singletons" i.e. no two instances with the same name. Why not
 * use enums? Because they can't be created during runtime.
 * */
public class Tag {

    private final String name;

    private final int id;
    private static int idCounter = 0;

    static Map<String, Tag> map = new HashMap<>();

    private Tag(String name) {
        this.name = name;
        id = idCounter;
        idCounter++;
    }

    public String getName() {
        return name;
    }

    /** Only for debugging purposes (to see that things are really singletons.) */
    public int getId() {
        return id;
    }

    public static Tag getTag(Enum enum1) {
        return getTag(enum1.name());
    }

    public static Tag getTag(String str) {
        Tag result = map.get(str);
        if (result == null) {
            result = new Tag(str);
            map.put(str, result);
        }
        return result;
    }

    /** Only needed if deserialization messes things up. */
    @Override
    public boolean equals(Object tag2) {
        if (tag2 == null)
            return false;
        return name.equals(((Tag) tag2).name);
    }

    /* Generated by IDE */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public String toString() {
        return "name: " + name;
    }

}

【问题讨论】:

  • 注意:由于您发布了一些背景,一个足够清晰的问题,然后是代码转储,我回答了问题,忽略了背景和代码转储。所以我可能误解了这个问题。

标签: java generics architecture


【解决方案1】:

我下载了你的代码,我什至无法编译 Test1 类,因为错误:Error:(9, 27) java: type argument tags_and_tax.model.NodeWithException is not within bounds of type-variable TYPE_PARAM

@immibis 已经回答了你可以使用NodeWithException&lt;T extends NodeWithException&lt;T&gt;&gt; 然后你会得到类似于Enum的东西

【讨论】:

  • 你用过java 8吗?我回答了@immibis 为什么递归不起作用。虽然另一种方式对我有用,但会收到原始类型的警告。
  • 是的,我确实使用过 Java 8,所以我有点困惑
猜你喜欢
  • 1970-01-01
  • 2012-02-04
  • 1970-01-01
  • 2014-08-13
  • 1970-01-01
  • 2020-12-20
  • 1970-01-01
  • 2019-07-21
  • 1970-01-01
相关资源
最近更新 更多