1

乍一看,我本来希望能够投射

ArrayList<Class<? extends Interface1>> 

ArrayList<Class<?>>

因为第二个显然是第一个限制较少的版本。但是,以下代码无法编译:

import java.util.ArrayList;

public class TypeInvocationConversionTest
{
  private static ArrayList<Class<? extends Interface1>> classList;

  private static ArrayList<Class<?>> lessRestrictiveClassList;

  public static void main(String[] args)
  {
    classList = new ArrayList<Class<? extends Interface1>>();
    lessRestrictiveClassList = (ArrayList<Class<?>>) classList;
  }

  private interface Interface1 {}
}

但产生错误

TypeInvocationConversionTest.java:12: inconvertible types
found   : java.util.ArrayList<java.lang.Class<? extends TypeInvocationConversionTest.Interface1>>
required: java.util.ArrayList<java.lang.Class<?>>
    lessRestrictiveClassList = (ArrayList<Class<?>>) classList;
                                                     ^

我不认为想要转换这两种类型是不合理的:出于动机,这里有一个更接近我实际处理的简短程序(此代码无法编译):

import java.util.ArrayList;

public class Mammal
{
  public void produceMilk() {}
}

public class Reptile
{
  public void layEggs() {}
}

public interface Species
{
  String getSpeciesName();
}

public class Dog extends Mammal
  implements Species
{
  @Override
  public String getSpeciesName()
  {
    return "Canis lupus familiaris";
  }
}

public class Cat extends Mammal
  implements Species
{
  @Override
  public String getSpeciesName()
  {
    return "Feles catus";
  }
}

public class Boa extends Reptile
  implements Species
{
  @Override
  public String getSpeciesName()
  {
    return "Boa constrictor";
  }
}

public class Panel3 extends Reptile
  implements Species
{
  @Override
  public String getSpeciesName()
  {
    return "Dromiceiomimus brevitertius";
  }
}

public class AnimalFunTime
{
  public static void main(String[] args)
  {
    ArrayList<Class<? extends Mammal>> listOfMammals;
    ArrayList<Class<? extends Reptile>> listOfReptiles;
    ArrayList<ArrayList<Class<?>>> matrixOfAnimals;

    listOfMammals.add(Dog.class);
    listOfMammals.add(Cat.class);

    listOfReptiles.add(Boa.class);
    listOfReptiles.add(Panel3.class);

    ///////////////////////////////////////////////////////////////////////////
    // The following two lines cause an error.                                //
    ///////////////////////////////////////////////////////////////////////////
    matrixOfAnimals.add( (ArrayList<Class<?>>) listOfMammals);
    matrixOfAnimals.add( (ArrayList<Class<?>>) listOfReptiles);

    // Get milk.
    for (int i = 0 ; i < listOfMammals.size() ; i++) {
      listOfMammals.get(i).produceMilk();
    }

    // Get eggs.
    for (int i = 0 ; i < listOfReptiles.size() ; i++) {
      listOfReptiles.get(i).layEggs();
    }

    // Display all the animals' names.  
    for (int j = 0 ; j < matrixOfAnimals.size() ; j++) {
      ArrayList<Class<?>> currentFamily = matrixOfAnimals.get(j);
      for (int i = 0 ; i < currentFamily.size() ; i++) {
        Class<?> currentAnimal = currentFamily.get(i);
        if (Species.isAssignableFrom(currentAnimal) {
          System.out.println(currentAnimal.getSpeciesName());
        }
        else
        {
          throw new SpeciesNotImplementedException("Please tell us the animal's name!");
        }
      }
    }
  }
}

正如评论所说,此代码无法编译,因为我无法创建一个包含ArrayList<Class<? extends Mammal>>ArrayList<Class<? extends reptile>>对象的列表。如果我可以将这两个都转换为ArrayList<Class<?>>s,那就没问题了。有没有办法做演员所以这种事情有效?

4

4 回答 4

5

这不起作用(也不应该)起作用的原因之一是它lessRestrictiveClassList会引用与classList. 因此,如果您将类型的对象Class<?>(其中?不扩展Interface1)添加到该列表中,突然合同classList被打破:

ArrayList<Class<? extends Interface1>> classList = new ArrayList<>();

// assume this is allowed:
ArrayList<Class<?>> lessRestrictiveClassList = (ArrayList<Class<?>>) classList;

// now add an element to the less restrictive list
lessRestrictiveClassList.add(String.class);

// and obtain it from the original list
// this code will crash, because String does not implement Interface1
Class<? extends Interface1> cls = classList.get(0);

最后一行会让你遇到大问题,因为它可能导致代码意外失败。

您应该复制到限制较少的列表,而不是两次引用数组列表:

ArrayList<Class<? extends Interface1>> classList = new ArrayList<>();
ArrayList<Class<?>> lessRestrictiveClassList = new ArrayList<>();

lessRestrictiveClassList.addAll(classList);
于 2013-10-02T14:34:20.357 回答
3

忘记泛型并转换为原始类型 ArrayList。

ArrayList<ArrayList> matrixOfAnimals = new ArrayList<>();
matrixOfAnimals.add(listOfMammals);
于 2013-10-02T14:18:21.813 回答
3

因为第二个显然是第一个限制较少的版本。

它不是。List<A>不是的子类型,List<B>即使A是 的子类型B。Heuster 证明了它为什么不安全。

如果您不需要使用第二个列表引用添加元素,则应ArrayList<? extends Class<?>>改为使用。你可以转换ArrayList<Class<? extends Interface1>>成那个。

于 2013-10-02T18:58:55.850 回答
2

您可以通过连续进行两次演员来进行您想要的演员:

lessRestrictiveClassList = (ArrayList<Class<?>>) (ArrayList<?>) classList;

这编译。

于 2013-10-02T14:32:25.603 回答