Java Generics: 목록에 캐스트할 수 없는가?
이 문제에 대해 생각해 보세요.
List<DataNode> a1 = new ArrayList<DataNode>();
List<Tree> b1 = a1; // compile error: incompatible type
여기서 DataNode 유형은 트리의 하위 유형입니다.
public class DataNode implements Tree
놀랍게도, 이것은 어레이에 유효합니다.
DataNode[] a2 = new DataNode[0];
Tree[] b2 = a2; // this is okay
이거 좀 이상한데?누가 이것에 대해 설명해 줄 수 있나요?
두 번째 예에서는 어레이 공분산입니다.IMO는 어레이 내의 할당이 안전하지 않게 되어 컴파일 시에는 정상이지만 실행 시에는 실패할 수 있습니다.
첫 번째 예에서는 코드가 컴파일되고 그 뒤에 다음이 이어졌다고 가정합니다.
b1.add(new SomeOtherTree());
DataNode node = a1.get(0);
무슨 일이 일어날 것 같습니까?
다음과 같이 할 수 있습니다.
List<DataNode> a1 = new ArrayList<DataNode>();
List<? extends Tree> b1 = a1;
당신은 ...에서 수 이다.그러면 당신은 오직 물건만 가져올 수 있기 때문이다.b1
, ,, 음, 음, 이, 음, 음, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ible, ible, ible, , ible, ible,Tree
하면 안 b1.add(...)
컴파일러가 안전한지 아닌지 알 수 없기 때문입니다.
자세한 내용은 Angelika Langer의 Java Generics FAQ 섹션을 참조하십시오.
을 해야 List<DataNode>
로로 합니다.List<Tree>
그렇게 하는 것이 안전하다는 것을 알고 있습니다.그러기 위해서는 더블캐스트를 하는 것이 바람직하지 않습니다.
List<DataNode> a1 = new ArrayList<DataNode>();
List<Tree> b1 = (List<Tree>) (List<? extends Tree>) a1;
간단한 설명: 어레이에 대해 처음에 허용한 것은 실수였습니다.
자세한 설명:
이것이 허용되었다고 가정합니다.
List<DataNode> a1 = new ArrayList<DataNode>();
List<Tree> b1 = a1; // pretend this is allowed
그럼 다음 순서로 진행하면 안 될까요?
b1.add(new TreeThatIsntADataNode()); // Hey, b1 is a List<Tree>, so this is fine
for (DataNode dn : a1) {
// Uh-oh! There's stuff in a1 that isn't a DataNode!!
}
으로서는 ''을할 때 을 할 수 .List
를 사용하고 있는 (예를 들면, 「」를 참조).List
범용 에 대해 수 없습니다., 이 Java를 수 없습니다.List<A>
a까지List<B>
~가 아니면A
★★★★★★★★★★★★★★★★★」B
똑같았어요.
(*) 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 맞다.할 수 .List<? extends Tree>
츠키노
List<DataNode>
하지 않다List<Tree>
DataNode
를 확장하다Tree
)를 할 수 ADATANode)는, 「a1」의 「Data Node」의 「Data Node」의 「ADATANode」를 참조해 주세요.
와일드카드를 사용하여 다음과 같은 작업을 수행해야 합니다.
List<DataNode> a1 = new ArrayList<DataNode>();
List<? extends Tree> b1 = a1;
b1.add(new Tree()); // compiler error, instead of runtime error
★★★★★★★★★★★★★★★★.DataNode[]
★★Tree[]
당시에는 당연한 것처럼 보였지만 다음과 같은 작업을 수행할 수 있습니다.
DataNode[] a2 = new DataNode[1];
Tree[] b2 = a2; // this is okay
b2[0] = new Tree(); // this will cause ArrayStoreException since b2 is actually a DataNode[] and can't store a Tree
그렇기 때문에 컬렉션에 제네릭을 추가할 때 런타임 오류를 방지하기 위해 조금 다른 방법을 선택했습니다.
어레이가 설계되었을 때(즉, Java가 설계되었을 때) 개발자들은 분산이 유용하다고 판단하여 이를 허용했습니다. 이 하게 하기 에, 를 들면, 이 결정으로 인해).NotADataNode
의 또 입니다.Tree
DataNode[] a2 = new DataNode[1];
Tree[] b2 = a2; // this is okay
b2[0] = new NotADataNode(); //compiles fine, causes runtime error
할 수 없다, 할 수 없다, 할 수 없다, 할 수 , 할 수 할 수 없다.List<Tree> b1 = a1;
할 수 있어요.List<? extends Tree> b1 = a1;
.
후자의 , 「」를 ,add
★★★★★★★★★★★★★★★★★」set
방법을 )T
인수로)를 지정하면 컴파일 오류가 발생합니다.이렇게 하면 (안전하지 않은 캐스팅이 없으면) 위의 어레이 문제와 동등한 문제를 컴파일할 수 없습니다.
간단한 답변: 목록 a1은 목록 b2와 같은 유형이 아닙니다.a1에는 확장 DataNode를 사용하여 임의의 객체 유형을 넣을 수 있습니다.따라서 Tree 이외의 타입을 포함할 수 있습니다.
C#의 답변입니다만, 이유는 같기 때문에, 이쪽에서는 그다지 문제가 되지 않는다고 생각합니다.
특히 어레이 유형과 달리 구성된 참조 유형은 "공변" 변환을 나타내지 않습니다.이것은, 타입 List<B>가 List<로의 변환(암묵적 또는 명시적)이 없는 것을 의미합니다.A>B가 A에서 파생된 경우에도.마찬가지로 List <B>에서 List <object>로의 변환은 없습니다.
그 이유는 간단합니다.목록으로 변환하는 경우<A > 가 허가되어 있기 때문에, 타입 A 의 값을 리스트에 격납할 수 있는 것이 분명합니다.단, 이로 인해 유형 목록 내의 모든 객체가 항상 유형 B의 값이라는 불변성이 깨집니다.그렇지 않으면 컬렉션 클래스에 할당할 때 예기치 않은 장애가 발생할 수 있습니다."
http://social.msdn.microsoft.com/forums/en-US/clr/thread/22e262ed-c3f8-40ed-baf3-2cbcc54a216e
DataNode는 트리의 하위 유형일 수 있지만 List DataNode는 List Tree의 하위 유형이 아닙니다.
https://docs.oracle.com/javase/tutorial/extra/generics/subtype.html
이것은 타입 삭제 기능을 실장하고 있는 제네릭의 전형적인 문제입니다.
첫 번째 예가 제대로 작동했다고 가정해 보십시오.그러면 다음 작업을 수행할 수 있습니다.
List<DataNode> a1 = new ArrayList<DataNode>();
List<Tree> b1 = a1; // suppose this works
b1.add(new Tree());
하지만 그 이후로는b1
그리고.a1
같은 대상을 가리키다, 그것은 곧 을 의미한다.a1
이제 를 참조합니다.List
양쪽 모두를 지탱하는DataNode
및Tree
s. 마지막 요소를 가져오려고 하면 예외가 발생합니다(어느 요소가 기억나지 않음).
자, 여기서 솔직하게 말씀드리겠습니다. 게으른 일반성의 구현입니다.
첫 번째 감정을 허락하지 않을 의미 있는 이유는 없어요.
덧붙여서, 저는 C++로 템플리트를 만드는 것을 좋아했지만, 제네릭스와 여기에 있는 바보 같은 제약이 제가 Java를 포기한 주된 이유입니다.
언급URL : https://stackoverflow.com/questions/3246137/java-generics-cannot-cast-listsubclass-to-listsuperclass
'source' 카테고리의 다른 글
그렇다면 (성공, 실패)는 언제 약속의 반대가 되는가? (0) | 2022.12.13 |
---|---|
왼쪽 결합이 이중인 MySQL Update 행, 첫 번째 일치 제한 (0) | 2022.12.13 |
2개의 조인 및 구별로 그룹화된 mysql 쿼리 최적화 (0) | 2022.12.13 |
PHP는 T_PAAMAYIM_NEKUDOTAYIM을 기대합니까? (0) | 2022.12.13 |
Kohana 기반 웹사이트의 속도와 확장성 최적화 (0) | 2022.12.13 |