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

Java:扩展/实现两个类/接口的对象列表

Java:扩展/实现两个类/接口的对象列表,java,generics,Java,Generics,我需要一个列表,它保存扩展类X的对象,并实现接口Y 我试过了,但我意识到这不是我真正需要的 public abstract class Animal {} public abstract class Mammal extends Animal {} public abstract class Bird extends Animal {} public class Tiger extends Mammal {} public class Ostrich extends Bird {} publ

我需要一个
列表
,它保存扩展类X的对象,并实现接口Y

我试过了,但我意识到这不是我真正需要的

public abstract class Animal {}
public abstract class Mammal extends Animal {}
public abstract class Bird extends Animal {}

public class Tiger extends Mammal {}
public class Ostrich extends Bird {}

public interface RunningObject {}
public class RunningTiger extends Tiger implements RunningObject {}
public class RunningOstrich extends Ostrich implements RunningObject {}
public class RunningRobot extends NonAnimal implements RunningObject {}

// This line is syntactically wrong
public List<Animal & RunningObject> runningAnimals = new List<>();

runningAnimals.add(new RunningTiger()); // This should work
runningAnimals.add(new RunningOstrich()); // This should work
runningAnimals.add(new Tiger()); // This should give compile error
runningAnimals.add(new Ostrich()); // This should give compile error
runningAnimals.add(new RunningRobot()); // This should give compile error
考虑这一点:

class Test<T extends MyBaseClass & MyBaseInterface>
{
    public List<T> myList;
}

public abstract class MyBaseClass {}
public interface MyBaseInterface {}
public class MyDerivedClassA extends MyBaseClass implements MyBaseInterface {}
public class MyDerivedClassB extends MyBaseClass implements MyBaseInterface {}

Test<MyDerivedClassA> obj = new Test<MyDerivedClassA>();
obj.myList.add(new MyDerivedClassA()); // Works
obj.myList.add(new MyDerivedClassB()); // Compile error

我需要的是在编译时实现类型安全性。这个问题是关于Java和泛型的,所以请不要给我关于设计模式(即使用策略设计模式)之类的问题的答案。

如果您可以控制对列表的访问,您可以使列表只包含
MyBaseClass
的实例,但只能通过带有额外约束的特殊方法添加到列表中:

private List<MyBaseClass> list;

<T extends MyBaseClass & MyBaseInterface> boolean add(T e) {
  return list.add(e);
}
私有列表;
布尔加法(TE){
返回列表。添加(e);
}
现在,作为该类的作者,您知道列表中的所有实例都可以安全地强制转换到
MyBaseInterface
,也可以直接作为
MyBaseClass
使用

这是相当令人讨厌的,但如果必须,可以对元素进行强制转换,前提是您负责确保它们的安全性-编译器只能做这么多。

引入一个“中级”抽象类:

class Test<T extends MyBaseClass & MyBaseInterface>
{
    public List<T> myList;
}

abstract class MyBaseClass {}
interface MyBaseInterface {}
class MyDerivedClassA extends DerivedClass {}
class MyDerivedClassB extends DerivedClass {}
class DerivedClass extends MyBaseClass implements MyBaseInterface {}
类测试
{
公开名单;
}
抽象类MyBaseClass{}
接口MyBaseInterface{}
类MyDerivedClassA扩展了DerivedClass{}
类MyDerivedClassB扩展了DerivedClass{}
类DerivedClass扩展MyBaseClass实现MyBaseInterface{}
然后你可以和我一起去

Test<DerivedClass> obj = new Test<>();
obj.myList.add(new MyDerivedClassA()); // Works
obj.myList.add(new MyDerivedClassB()); // Works
testobj=新测试();
obj.myList.add(新的MyDerivedClassA());//作品
obj.myList.add(新的MyDerivedClassB());//作品

MyDerivedClassB类不是MyDerivedClassA类。尝试“Test obj=new Test();”
&
运算符不适用于
通配符,否则我就不会用
Test
类包装列表。@Jai ok,我删除了前两个选项。这意味着我不能直接将列表暴露在类之外,我必须手动编写列表中所有我想在这个类之外公开的方法?谢谢。这在技术上是正确的方法,但在实践中我很难实现这一点。我当然想直接公开一个列表,它可以通过
list.add()
等方法接收正确的编译时对象。这与我的要求相近,但我的实际问题实际上比这更复杂。见更新的问题。