2013-10-02 2 views
1

는, 나는 두 번째는 분명히 처음의 덜 제한적인 버전이기 때문에이러한 변환 불가능한 유형을 변환 할 수있는 방법이 있습니까? 언뜻

ArrayList<Class<?>> 

ArrayList<Class<? extends Interface1>> 

을 시전 할 수있을 것으로 기대했을 것이다.

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

lessRestrictiveClassListclassList과 같은 목록 개체를 참조한다는 이유 중 하나는 작동하지 않아야하고 작동하지 않아야한다는 것입니다. 당신이 그 목록에 (?Interface1를 확장하지 않음) 유형 Class<?>의 개체를 추가한다면, 갑자기 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>의 하위 유형이 아닙니다. Heuster는 안전하지 않은 이유를 설명했습니다.

두 번째 목록 참조를 사용하여 요소를 추가 할 필요가없는 경우 ArrayList<? extends Class<?>>을 사용해야합니다. 당신 ArrayList<Class<? extends Interface1>>로 변환 할 수 있습니다.

관련 문제