Java 我可以得到一个扩展类并实现接口的对象集合吗?

Java 我可以得到一个扩展类并实现接口的对象集合吗?,java,Java,基本上,我的问题没有什么可补充的: class A {} interface I {} // how can I get a Set<> of object of type A that implements I? class A{} 接口I{} //如何获得一组实现I的类型为a的对象? 我尝试了几件事,,,你必须制作一个工具I: interface I {} class A implements I {} Set<A> setOfA; 接口I{} 类实现I{}

基本上,我的问题没有什么可补充的:

class A {}
interface I {}

// how can I get a Set<> of object of type A that implements I?
class A{}
接口I{}
//如何获得一组实现I的类型为a的对象?

我尝试了几件事,
你必须制作一个工具I:

interface I {}
class A implements I {}

Set<A> setOfA;
接口I{}
类实现I{}
套毛;
可能是alsp

class SubA extends A implements I { }
Set <SubA> setOfSubA;
class SubA扩展了一个实现I{}
一组亚基;

类a的使用不能改变它的行为,正如它突然“实现”I所表明的那样。接口方法的实现应该来自哪里

我能够做到以下几点:

// how can I get a Set<> of object of type A that implements I?
public class MyClass<T extends String & Iterable>{
    private Set<T> mySet;
}
公共类MyClass{
私有集mySet;
}

public void myFancyMethod(Set mySet){}
但是当我这么做的时候

private Set<? extends String & Iterable>

private Set您可以编写自己的类:

public class MySet<E extends A & I> extends HashSet<E> {
    // blank
}
公共类MySet扩展HashSet{
//空白
}

这将确保
MySet
的任何实例只包含扩展
A
并实现
I

的对象。Java不支持交集类型,它在声明类型参数时只支持多个边界(如
扩展A&I
)。也就是说,我们不能使用像
a&I
这样的符号来表示同时扩展a和I的类型族,但我们可以声明一个类型参数
来引用特定的此类类型

如果您想要后者,则类型参数非常适合。但是,如果您的集合应该允许不相关的
A
I
子类型,那么似乎不存在好的解决方案。我最好的想法是这样的:

class AISetWrapper {
    Set<A> set = new HashSet<>();

    <T extends A & I> Set<T> getSet() {
        return (Set<T>) set; // unchecked cast that only works because generics are not reified
    }
}

A和I是实际的类和接口名称,还是它们表示泛型类型参数?看起来和这里的问题一样:[基于java中的超类和子类对泛型类型的多个限制][1][1]:John是对的,看起来如果不使封闭类也泛型,我就不能拥有这样的集合,不幸的是:)。请问
集在哪里?因为您希望对象既扩展
A
又实现
I
,所以可以将两者都用作泛型。但是上面没有设置编译时限制,即传递的对象只扩展A并实现I,而不是其中一个。这里的重点是编译时检查,因为作为运行时,您可以通过类型擦除来执行任何您想要的操作。问题是获取一组扩展A和implemnt I的对象。它没有提到编译时或运行时。是的,不符合条件的对象(仅实现I)在通过上述函数添加到集合时可能会编译,但由于内部检查将失败,它们实际上不会被添加。很抱歉,我无意中键入了
implements
,而不是
&
。刚刚修复。应该是
HashSet
。但是,这将OP限制为
Set
的单个实现。似乎
类AISetWrapper
可以避免未经检查的强制转换。这就是我的答案所称的类型参数方法。正如我在回答中已经说过的,这种方法将集合的所有元素限制为扩展a和I的特定公共超类型。也就是说,不能将AI1和AI2的实例添加到同一集合中。我的观点是,在
hack
解决方案中,将泛型声明移动到类级别而不是方法级别将删除强制转换警告。但这样做会改变意义,正如我的评论试图解释的那样。。。
public class MySet<E extends A & I> extends HashSet<E> {
    // blank
}
class AISetWrapper {
    Set<A> set = new HashSet<>();

    <T extends A & I> Set<T> getSet() {
        return (Set<T>) set; // unchecked cast that only works because generics are not reified
    }
}
class AI1 extends A implements I { }

class AI2 extends A implements I { }

public static void main(String[] args) {
    AISetWrapper aiSet = new AISetWrapper();
    aiSet.get().add(new AI1()); // compiles
    aiSet.get().add(new AI2()); // compiles
    aiSet.get().add(new A()); // does not compile
    aiSet.get().add(new I() {}); // does not compile
}