2013-10-02 112 views
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,那就沒問題。有沒有辦法演出,所以這種事情的作品?

+0

使其通用 –

+0

它看起來都很通用!我應該做什麼通用? –

回答

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); 
3

忘記泛型並將其轉換爲原始類型ArrayList。

ArrayList<ArrayList> matrixOfAnimals = new ArrayList<>(); 
matrixOfAnimals.add(listOfMammals); 
2

你可以通過連續做兩個投你想投:

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

這編譯。

+0

'你可以[先做些事],而你不能[做到這一點]第二。如果這並不意味着第一個比第二個限制性更小,我不知道它是什麼!但是,我明白了你的觀點:將兩個非原始對象放在一起意味着它們現在是同一個對象,因此它們必須完全相同。 –

+0

@ Donkey_2009你的第一句話是賴特。我的答案中的部分內容顯然是錯誤的,我將其刪除。 –

3

因爲第二顯然是第一個限制較少的版本。

不是。即使AB的子類型,List<A>也不是List<B>的子類型。赫斯特證明了爲什麼它不安全。

如果您不需要使用第二個列表引用添加元素,則應該使用ArrayList<? extends Class<?>>代替。你可以轉換成ArrayList<Class<? extends Interface1>>

相關問題