2011-05-03 2 views
3

는이 작업을 수행 할 구문 법적 :왜 자바가 이것을 허용합니까?

String [] s = new String[1]; 
Object [] o = s; 

o[0] = new Integer(42); 

하지만 물론 런타임시 충돌합니다.

제 질문은 무엇입니까? 처음부터이 과제를 허용하는 시점은 무엇입니까?

답변

8

문제는 할당 Object [] o = s;입니다. 나는 이것이 "this"로 무엇을 의미하는지 생각합니다.

전문 용어는 array covariance이며,이 기술 용어가 없으면 일반적으로 배열을 처리하는 코드를 사용할 수 없습니다. 예를 들어 java.util.Arrays의 비 프리미티브 배열 메서드 대부분은 실제 Object[] 인스턴스에만 사용할 수 있으므로 쓸모가 없습니다. 분명히 이것은 완벽한 유형의 안전보다 Java 설계자가 더 중요하게 생각했습니다.

Java 5에서 소개 된 Java의 제네릭 (와일드 카드를 통한 명시 적 공분산)을 볼 때 다른 해결책이 있습니다. 그러나 그로 인해 복잡성이 상당히 증가합니다 (? 와일드 카드에 대한 지속적인 질문을 참조하십시오). Java의 원래 설계자는 복잡성을 피하고자했습니다.

0

컴파일러는 o이 실제로 String[]임을 (정적 분석없이) 알 수 없으므로 런타임에 실패하더라도 할당 할 수 있습니다. 예를 들어 Integer[]o에 할당하면 문제가 발생하지 않습니다. 당신이 컴파일러는 그것을 허용하는 코드

를 실행할 때 [] 정확한지, [] 객체에 문자열을 캐스팅하고 있기 때문에

그것은 허용하지 않는다
1

, 당신은 java.lang.ArrayStoreException: java.lang.Integer 얻을. 이것은

와 유사합니다.
Integer i = new Integer(10); 
Object o = i; 
String s = (String) o; 

컴파일러는 불평하지 않지만 런타임에 ClassCastExeption을 얻습니다.

+0

하지만 질문에 전혀 대답하지 않습니다. 당신은 단순히 OP가 말한 것을 정확히 다시 말하고 있습니다. 또한 OP는 그것이 "허용"되었다고 결코 말하지 않았습니다 *, OP는 "구문 적으로"* 정확하고 런타임에 충돌하고 있다고 말했다. OP의 잘 공식화 된 질문은 매우 명확하며 대답은 아무 것도 대답하지 않습니다 ... – SyntaxT3rr0r

+0

저는 컴파일러가 객체와 유추하여 오류나 경고를 생성하지 않는다는 것을 보여주고 있습니다. 더욱이, ArrayStoreException은 배열에 값을 할당 할 때 ClassCastExeception과 동등합니다. 형식이 호환되지 않을 때 throw됩니다. 그러나 의견이 맞지 않아도됩니다. – Augusto

0

컴파일러는 런타임에 배열 만 문자열을 보유 할 것인지 (보유하지 않을 것인지) 결정할 수 없으므로 할당을 허용해야합니다. 런타임시 확인되는 [ArrayStoreException][1]을 던집니다.

String [] s = new String[1]; 
Object [] o = s; 

o = new Integer[1]; 

o[0] = new Integer(1); 

이 상황 유효 확인을 실행합니다

이것이 고려하십시오. 보다 넓은 시야를 제공하기 위해, IMHO 배열은 Java에서 낮은 레벨의 새는 추상화입니다.

2

할당 그런 종류의 수의 요점은 그것을 허용하지하면 다음과 불가능과 같은 일을 할 것입니다 : 컴파일러가 당신의 문자열을 금지

ArrayList[] lists = new ArrayList[10]; 
lists[0] = new ArrayList(); 

List[] genericLists = lists; 
lists[0].add("someObject"); 

경우 -> 개체 경우, 그것은 또한 ArrayList를 금지해야 -> List 및 서브 클래스에서 수퍼 클래스 유형 중 하나로 할당하는 다른 모든 인스턴스. 이런 종류의 Java는 쓸모없는 객체 지향 언어의 많은 기능을 만듭니다. 물론,이 같은 일을 훨씬 더 일반적이다 : 관계없이

List[] lists = new List[10]; 
lists[0] = new ArrayList(); 
lists[0].add("someObject"); 

하지만, 그것을 만들기 위해 프로그래머에게 달려 있으므로, 동시에 많은 유용하고 합법적 인 사용 사례를 허용하지 않고 이러한 경우를 필터링 할 수 없습니다 컴파일러 그들이하는 일이 제정신이 아님을 확신하십시오.원하는 것이 Object[]이면 변수를 선언하십시오. String[]으로 선언하고 Object[]으로 전송 한 다음 실제로 가지고있는 것이 String[] 인 것을 잊으면 간단히 프로그래머 오류가 발생합니다.

0

일반적으로 컴파일러는 oString[]으로 지정되었는지 여부를 알 수 없습니다. 이것을 고려하십시오 :

String[] s = new String[1]; 
Object[] o; 

if (complexFunction(System.currentTimeMillis())) { 
    o = s; 
} else { 
    o = new Integer[1]; 
} 

o[0] = 42; 

컴파일러는 o이 걸릴 것입니다 어떤 종류의 디자인 타임에 알 수 없습니다 - 그냥 할당을 할 수 있도록.