Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/363.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_Types_Set_Type Safety - Fatal编程技术网

Java 如何创建一个集合,其中只能添加一个不';不允许添加子类或超类?

Java 如何创建一个集合,其中只能添加一个不';不允许添加子类或超类?,java,types,set,type-safety,Java,Types,Set,Type Safety,我想要一个只包含一种数据类型的集合,不允许它的任何超类或子类被添加到集合中。好的,我想我完全误解了这一点 我可能会使用组合而不是继承,在内部委托给HashSet,但在add中,您需要检查: if (o.getClass() != clazz) { // throw or reject } 请注意,这意味着您将在执行时需要实际的类,因此您需要使用以下内容构造集合: ExactTypeSet<String> x = new ExactTypeSet<String>

我想要一个只包含一种数据类型的集合,不允许它的任何超类或子类被添加到集合中。

好的,我想我完全误解了这一点

我可能会使用组合而不是继承,在内部委托给
HashSet
,但在
add
中,您需要检查:

if (o.getClass() != clazz)
{
     // throw or reject
}
请注意,这意味着您将在执行时需要实际的类,因此您需要使用以下内容构造集合:

ExactTypeSet<String> x = new ExactTypeSet<String>(String.class);
ExactTypeSet x=新的ExactTypeSet(String.class);

您可以使用
对象。getClass()确定对象的类型

如果您希望保证只添加MyClass类型的类,您可以扩展HashSet并重写
add(Object o)
方法,并且仅在(o.getClass()==MyClass.class)
的情况下将元素添加到集合中

更新:添加了一个可以作为PoC运行的工作示例

public class MySet extends HashSet<MySet.MyClass> {
    public static class MyClass {}

    public static class MySubClass extends MyClass {}

    @Override
    public boolean add(MyClass c) {
        if (c.getClass() != MyClass.class) {
            throw new IllegalArgumentException("illegal class to add " + c.getClass().getName());
        }
        return super.add(c);
    }

    public static void main(String[] args) {
        MySet set = new MySet();
        set.add(new MyClass());   // works
        set.add(new MySubClass()); // throws Exception
    }

}
公共类MySet扩展HashSet{
公共静态类MyClass{}
公共静态类MySubClass扩展MyClass{}
@凌驾
公共布尔加法(MyClass c){
如果(c.getClass()!=MyClass.class){
抛出新的IllegalArgumentException(“要添加的非法类”+c.getClass().getName());
}
返回super.add(c);
}
公共静态void main(字符串[]args){
MySet set=新的MySet();
set.add(new MyClass());//有效
set.add(new MySubClass());//引发异常
}
}
运行此示例将产生:

线程“main”java.lang.IllegalArgumentException中的异常: 添加MySet$MySubClass的非法类


在非常特殊的情况下,如果您知道要添加的类的类型,您可以扩展现有的Set实现并重写
add(Object o)
方法,只允许在
o.getClass().getName().equals(“yourclassname”)的位置添加对象

我认为这不起作用,因为您不能覆盖
add()
并同时更改其参数的类型。也许您的意思是
add(objecte)
。这个示例很有效,您可以添加一个main方法,并使用
HashSet
getClass()=String.class
。我检查了。@Peter:add()的参数类型也是
HashSet
->
add(eo)
中的泛型类型E,所以
HashSet
add(MyClass o)
:你说得对,我在考虑像
remove(Object)
contains(Object)
这样的方法,检查实际的类会更简单。可以在不同的类加载器中使用相同的名称对两个类进行分类。(我倾向于让自己感到困惑并避免它;)不应该比较类名,而是直接比较类对象。在运行时可能有几个不同的类具有相同的名称(一个名称仅在单个类加载器加载的类集中是唯一的,但可能有几个类加载器)。