Java I';我对多态性感到困惑

Java I';我对多态性感到困惑,java,oop,polymorphism,Java,Oop,Polymorphism,我知道多态性规则,我们可以通过如下代码中的参数发送它 interface Animal { void whoAmI(); } class A implements Animal{ @Override public void whoAmI() { // TODO Auto-generated method stub System.out.println("A"); } } class B implements Animal{

我知道多态性规则,我们可以通过如下代码中的参数发送它

interface Animal {
  void whoAmI();
}

class A implements Animal{

    @Override
    public void whoAmI() {
        // TODO Auto-generated method stub
        System.out.println("A");
    }

}

class B implements Animal{

    @Override
    public void whoAmI() {
        // TODO Auto-generated method stub
        System.out.println("B");
    }

}

class RuntimePolymorphismDemo {

public void WhoRU(List t){
    System.out.println(t.getClass());
}

public static void main(String[] args) {
     A a = new A();
     B b = new B();

     RuntimePolymorphismDemo rp = new RuntimePolymorphismDemo();
     rp.WhoRU(a);
     rp.WhoRU(b);
  }
}
但是

 List<Example> examples = new ArrayList<Example>();
List examples=new ArrayList();
在上面的代码中,我不明白为什么我们必须使用
List

List<Example> examples = new ArrayList<Example>();
为什么我们不能这样使用

ArrayList<Example> examples = new ArrayList<Example>();
arraylistexamples=new ArrayList();
因为当我们使用
List
时,我们不能使用只存在于
ArrayList
类中的方法,比如
trimToSize()


如何知道何时使用或不使用?

使用列表而不是ArrayList的原因是,当您想使用列表的功能而不关心其实现时,只需使用基本接口或抽象类就可以提供更大的灵活性


如果需要更改ArrayList的特殊功能,则可以指定它,但如果将来决定将实现更改为ArrayList以外的其他内容,则很难更改(因为您必须在引用它的任何地方更改代码,而不仅仅是底层代码).

使用列表而不是ArrayList的原因是,当您想使用列表的功能而不关心其实现时,只需使用基本接口或抽象类就可以提供更大的灵活性


如果需要更改ArrayList的特殊功能,则可以指定它,但如果将来决定将实现更改为ArrayList以外的其他内容,则很难更改(因为您必须在引用它的任何地方更改代码,而不仅仅是底层代码).

列表
是一个界面
ArrayList
是一种具体类型,是一种实现


如果您只需要使用
列表
中的功能,那么您可以将变量声明为
列表
。然后,如果一个有用的
List
新实现可用(
MySuperFastList
),您可以在代码中交换它,只需要做一个更改。

List
是一个接口
ArrayList
是一种具体类型,是一种实现


如果您只需要使用
列表
中的功能,那么您可以将变量声明为
列表
。然后,如果一个有用的
List
新实现可用(
MySuperFastList
),您可以在代码中交换它,只需要做一个更改。

与扩展示例代码相同,我们说:

Animal a=new A();
Animal b=new B();

您可以毫无问题地将“更派生的类型”分配给派生较少的类型,实际上您可以构造一个Anymal数组,总是引用您的示例,用一些实例和实例填充它,通过在数组上循环并调用每个“Animal”WhoAmI()与扩展示例代码相同,我们说:

Animal a=new A();
Animal b=new B();
您可以毫无问题地将“更派生的类型”分配给派生较少的类型,实际上您可以构造(始终参照您的示例)Anymal数组,用一些实例和实例填充它,并通过在数组上循环并调用每个“Animal”WhoAmI()来查看polymorfism在起作用

这个代码,我不明白为什么我们必须使用列表。为什么我们不能这样使用

ArrayList<Example> examples = new ArrayList<Example>();
在此处使用接口
列表
而不是具体类
ArrayList
遵循一种常见的最佳实践:尽可能使用接口而不是具体类,例如在变量声明、参数类型和方法返回类型中。这被视为最佳实践的原因是:

  • 将接口用于声明和返回类型隐藏了实现细节,使其在将来更易于修改。例如,我们可能会发现使用
    LinkedList
    比使用
    ArrayList
    更有效。我们现在可以很容易地在一个地方进行更改,就在列表实例化的地方。这种做法对于方法参数类型和方法返回类型尤其重要,这样类的外部用户就不会看到类的这个实现细节,并且可以在不影响其代码的情况下自由更改它

  • 通过使用该接口,未来的维护人员可能会更清楚地看到,该类需要某种
    列表
    ,但它并不特别需要
    数组列表
    。如果该类依赖于某些特定于
    ArrayList
    的属性,即它需要使用
    ArrayList
    方法,那么使用
    ArrayList examples=…
    而不是
    List examples=…
    可能暗示该代码依赖于特定于
    ArrayList
    的某些内容

  • 与使用具体类
    ArrayList
    相比,使用更抽象的
    列表可以简化测试/模拟

  • 这个代码,我不明白为什么我们必须使用列表。为什么我们不能这样使用

    ArrayList<Example> examples = new ArrayList<Example>();
    
    在此处使用接口
    列表
    而不是具体类
    ArrayList
    遵循一种常见的最佳实践:尽可能使用接口而不是具体类,例如在变量声明、参数类型和方法返回类型中。这被视为最佳实践的原因是:

  • 将接口用于声明和返回类型隐藏了实现细节,使其在将来更易于修改。例如,我们可能会发现使用
    LinkedList
    比使用
    ArrayList
    更有效。我们现在可以很容易地在一个地方进行更改,就在列表实例化的地方。这种做法对于方法参数类型和方法返回类型尤其重要,这样类的外部用户就不会看到类的这个实现细节,并且可以在不影响其代码的情况下自由更改它

  • 通过使用该接口,将来的维护人员可能会更清楚地知道该类需要som