나는 언어가 언어이고 VM이 매우 성숙하다는 점에서 Java가 왜 형식 유추를하지 않는지 항상 궁금했습니다. Google의 Go는 형식 유추가 뛰어난 언어의 한 예이며 입력해야하는 양을 줄입니다. 이 기능 뒤에 Java의 일부가 아닌 특별한 이유가 있습니까?
나는 언어가 언어이고 VM이 매우 성숙하다는 점에서 Java가 왜 형식 유추를하지 않는지 항상 궁금했습니다. Google의 Go는 형식 유추가 뛰어난 언어의 한 예이며 입력해야하는 양을 줄입니다. 이 기능 뒤에 Java의 일부가 아닌 특별한 이유가 있습니까?
답변:
기술적으로 말하면 Java는 제네릭을 사용할 때 형식 유추를 가지고 있습니다 . A의 일반적인 방법 과 같은
public <T> T foo(T t) {
return t;
}
컴파일러는 작성시 분석하고 이해합니다.
// String
foo("bar");
// Integer
foo(new Integer(42));
인수로 입력 된 내용에 따라 첫 번째 호출에 대해서는 문자열이 리턴되고 두 번째 호출에 대해서는 정수가 리턴됩니다. 결과적으로 적절한 컴파일 타임 검사를 받게됩니다. 할 때 또한 자바 7에서, 하나는 추론 몇 가지 추가 유형을 얻을 수있는 인스턴스 제네릭이 너무 좋아
Map<String, String> foo = new HashMap<>();
Java는 우리를 위해 빈 꺾쇠 괄호를 채울만큼 친절합니다. Java가 왜 변수 할당의 일부로 타입 추론 을 지원하지 않습니까? 한 시점 에서 변수 선언에 형식 유추에 대한 RFE 가 있었지만 "수정하지 않음"으로 닫혔습니다.
인간은 두 가지 방식으로 형식 선언의 중복성으로부터 혜택을받습니다. 먼저, 중복 유형은 유용한 문서 역할을합니다. 독자는 getMap () 선언을 검색하여 반환되는 유형을 찾을 필요가 없습니다. 둘째, 이중화를 통해 프로그래머는 의도 된 유형을 선언 할 수 있으므로 컴파일러가 수행 한 교차 점검의 이점을 얻을 수 있습니다.
이것을 닫은 기고자는 또한 그것이 "비자 바와 같지 않다"고 느끼며 이것이 내가 동의하는 것이라고 언급했다. 자바의 장황함은 축복이자 저주가 될 수 있지만 언어를 그대로 만들어줍니다.
물론 그 특정 RFE는 그 대화의 끝이 아니 었습니다. Java 7 동안이 기능은 다시 고려 되었으며 James Gosling의 테스트 구현을 포함하여 일부 테스트 구현이 작성되었습니다. 다시 말하지만이 기능은 결국 중단되었습니다.
Java 8이 출시되면서 이제 람다의 일부로 형식 유추를 얻습니다.
List<String> names = Arrays.asList("Tom", "Dick", "Harry");
Collections.sort(names, (first, second) -> first.compareTo(second));
자바 컴파일러 방법을보고 할 수있는 Collections#sort(List<T>, Comparator<? super T>)
다음의 인터페이스 Comparator#compare(T o1, T o2)
및 그 결정 first
과 second
A가되어야 String
하므로 프로그래머 람다 표현 유형을 재 작성하는 것을 포기 수.
First, the redundant type serves as valuable documentation - readers do not have to search for the declaration of getMap() to find out what type it returns
-예, 그렇다면 HashMap<String, Integer> map = foo.getMap()
동의합니다-C #에서는 일반적으로 var
그러한 경우에는 사용할 수는 없지만 사용하지 않습니다 . 그러나이 논쟁은 물이라면 물을 보유하지 않습니다 HashMap<String, Integer> map = new HashMap<String, Integer>()
. 이것은 진정한 중복성이며 유형 이름을 두 번 쓰면 아무런 이점이 없습니다. 그리고 컴파일러 교차 검사를 통해 어떻게 이점을 얻을 수 있는지 전혀 이해하지 못합니다.
var
Java 의 C #과 동일한 내용이 여전히 누락 되었습니다.
Humans benefit from the redundancy
은 현재 질문에 대한 실제 답변 이라고 생각합니다. 내가 읽은 모든 정당화는 Java 디자이너의 무례하고 근거가 없으며 우스운 변명처럼 보입니다 .C # 및 C ++에는 기능이 있으며 C # 및 C ++ 디자이너는 Java와 모든 사람이 행복하게 사용합니다. Java 개발자가 C # 또는 C ++ 개발자와 다른 이유는 무엇입니까? 이것이 제가 @KonradMorawski에 동의하는 이유입니다. "여기에서 일이 이루어지는 방식"이 다시 실제적인 이유 인 것 같습니다 .
먼저, 형식 유추는 런타임이 30 년 된 CPU인지 또는 새로운 비트인지 여부에 관계없이 런타임의 성숙도와 는 아무런 관련 이 없습니다 . 컴파일러에 관한 것입니다.
즉, 제네릭에 허용되며 제네릭이 아닌 유형에 허용되지 않는 이유는 철학 때문인 것으로 보입니다. 디자이너가 추가하지 못하게하는 것은 없습니다.
업데이트 : java 10에서 지원하는 것 같습니다 —- http://openjdk.java.net/jeps/286
내가 아는 한, Java가 90 년대 초에 설계되었을 때 형식 추론은 주류 언어들 사이에서 인기가 없었지만 (ML과 같이 이미 잘 알려진 개념이었습니다). 따라서 Java가 C ++, Pascal 또는 기타 주류 언어를 사용하지 않는 프로그래머를 대상으로하기 때문에 유형 유추가 지원되지 않았다고 생각할 수 있습니다 (최소한의 놀람 원칙).
또한 Java의 디자인 원칙 중 하나는 프로그래머와 컴파일러가 코드에 대해 동일한 이해를 갖도록 명시 적으로 작성하는 것입니다. 정보를 복제하면 오류 가능성이 줄어 듭니다. 물론 더 많은 문자를 입력하는 것이 제공하는 추가 안전성의 가치가 있는지 여부는 맛의 문제 일 수 있지만 이것은 Java에 대한 디자인 철학이었습니다.
Java가 미래에 유형 유추를 얻을지 모르겠지만 IMO는 언어에 큰 혁명이 될 것입니다 (Glenn Nelson이 언급했듯이 "Java와 유사하지 않음"으로 설명 됨). 새로운 이름을 선호하는 Java 이름.
유형 유추와 함께 JVM 언어를 사용하려면 Scala를 사용할 수 있습니다.
몇 가지 가능한 이유를 생각할 수 있습니다. 하나는 명시 적 타이핑이 자체 문서화라는 것입니다. Java는 일반적으로 이것을 결정보다 우선 순위로 만듭니다. 또 다른 이유는 유형이 다소 모호한 경우 일 수 있습니다. 유형 또는 하위 유형이 루틴을 만족시킬 수있는 경우와 같습니다. List를 사용하고 싶지만 누군가가 와서 ArrayList 전용 메소드를 사용한다고 가정 해 봅시다. JIT는 ArrayList를 유추하고 컴파일 오류를 원하더라도 계속 수행합니다.
Let's say you want to use a List, but someone comes along and uses a method exclusive to ArrayList. The JIT would infer an ArrayList and carry on even if you wanted a compilation error
-나는이 비트를 이해하지 못한다. 타입 추론은 변수를 메소드를 호출하지 않고 변수를 설명하는 순간에 발생합니다. 당신이 의미 한 바의 예를 보여줄 수 있습니까?
요구 사항에 맞는 가장 일반적인 인터페이스를 사용하여 변수를 선언하고 다음과 같이 적절한 구현 클래스로 변수를 초기화하라는 잘 확립 된 권장 사항과 모순됩니다.
Collection<String> names = new ArrayList<>();
효과적으로,
var names = new ArrayList<String>();
구문 설탕에 불과합니다
ArrayList<String> names = new ArrayList<String>();
원하는 경우 IDE에서 new ArrayList<String>()
"원 클릭"(리 팩터 / 로컬 변수 작성)을 사용 하여 표현식 에서 생성 할 수 있지만 "인터페이스 사용"권장 사항과 모순된다는 점을 기억하십시오.