Java의 var 키워드에 람다 식을 할당 할 수없는 이유는 무엇입니까?
var
Java 10에서 다음과 같은 문자열 로 할당 할 수 있습니다 .
var foo = "boo";
다음과 같은 람다 식으로 할당 할 수는 없습니다.
var predicateVar = apple -> apple.getColor().equals("red");
이 같은 나머지 추론 할 수있을 때 왜 람다 또는 메소드 참조 유형을 추론 할 수없는 String
, ArrayList
등, 사용자 클래스를?
로부터 로컬 - 변수 유형 추론 JEP :
추론 프로세스는 실질적으로 변수에 이니셜 라이저 표현식의 유형을 제공합니다. 미묘함 :
- 이니셜 라이저에는 대상 유형이 없습니다 (아직 추론하지 않았기 때문에). lambdas , 메서드 참조 및 배열 이니셜 라이저와 같이 이러한 유형이 필요한 폴리 표현식 은 오류를 트리거합니다.
람다 식 자체에는 형식이 없기 때문에 var
.
... 마찬가지로 기본 규칙을 설정할 수 있습니다.
물론,이 제한을 해결할 수있는 방법을 찾을 수 있습니다. 개발자가 그렇게하지 않기로 결정한 이유는 의사 결정에 참여한 사람이 여기에서 대답 할 수없는 한 실제로 추측에 달려 있습니다. 어쨌든 관심이 있으시면 openjdk 메일 링리스트 중 하나에서 물어볼 수 있습니다 : http://mail.openjdk.java.net/mailman/listinfo
내가 추측한다면, 그들은 아마도 var
제 3 자 기능적 인터페이스 유형을 배제하는 특정 기능적 인터페이스 유형 집합과의 맥락에서 람다 추론을 연결하고 싶지 않았을 것입니다. 더 나은 해결책은 (Apple) -> boolean
호환 가능한 기능 인터페이스 유형으로 변환 할 수 있는 일반 함수 유형 (예 :)을 추론하는 것입니다. 그러나 JVM에는 이러한 함수 유형이 없으며이를 구현하지 않기로 결정한 것은 람다 표현식을 만든 프로젝트에서 이미 이루어졌습니다. 구체적인 이유에 관심이 있다면 개발자에게 물어보십시오.
이것은 var
. 람다에 독립형 이 있는지 여부와 관련이 있습니다 . 방법의 var
작품은이 RHS에 이니셜 라이저의 독립 실행 형을 계산하고가 추정하는 것입니다.
Java 8에 도입 된 이후로 람다 식 및 메서드 참조에는 독립형 유형이 없습니다 . 기능 인터페이스 여야 하는 대상 유형이 필요합니다 .
시도하는 경우 :
Object o = (String s) -> s.length();
또한 컴파일러는 람다를 변환하려는 기능 인터페이스를 알지 못하기 때문에 유형 오류가 발생합니다.
추론을 요청 var
하면 더 어려워 지지만 쉬운 질문에 답할 수 없기 때문에 더 어려운 질문도 할 수 없습니다.
다른 방법 (예 : 캐스트)으로 대상 유형을 제공하면 작동합니다.
var x = (Predicate<String>) s -> s.isEmpty();
이제 RHS에는 독립형 유형이 있기 때문입니다. 그러나 x
매니페스트 유형을 제공하여 대상 유형을 제공하는 것이 좋습니다 .
이것이 불가능하거나 바람직하지 않거나 원하지 않는다고 말하는 모든 사람에게 Scala가 인수 유형 만 지정하여 람다 유형을 추론 할 수 있다는 점을 지적하고 싶습니다.
val predicateVar = (apple: Apple) => apple.getColor().equals("red")
그리고 Haskell에서는 getColor
객체에 첨부되지 않은 독립형 함수이고 완전한 Hindley-Milner 추론을 수행하기 때문에 인수 유형도 지정할 필요가 없습니다.
predicateVar = \apple -> getColor apple == "red"
이것은 프로그래머가 명시 적으로 지정하는 것이 성가신 단순한 유형이 아니라 더 복잡한 유형이기 때문에 매우 편리합니다.
즉, Java 10의 기능이 아닙니다. 구현 및 이전 디자인 선택의 제한 사항입니다.
여러 사람이 이미 언급했듯이 어떤 유형을 var
추론 해야 하며 그 이유는 무엇입니까?
진술 :
var predicateVar = apple -> apple.getColor().equals("red");
모호 컴파일러가 선택해야하는 이유에 유효한 이유도 없다 Function<Apple, Boolean>
위에 Predicate<Apple>
또는 가정 역도 마찬가지 apple
람다의 식별자가 나타내는 Apple
isntance이.
또 다른 이유는 람다 자체에 발언 가능한 유형이 없으므로 컴파일러가이를 추론 할 방법이 없기 때문입니다.
또한 "가능하다면" 컴파일러가 모든 기능 인터페이스를 거쳐야하고 var
변수에 람다를 할당 할 때마다 어떤 기능 인터페이스가 가장 적합한 지 결정해야하므로 오버 헤드를 상상해보십시오 .
이에 답하기 위해 우리는 람다가 무엇이며 어떻게 작동하는지 자세히 이해해야합니다.
먼저 람다가 무엇인지 이해해야합니다.
람다 식은 항상 기능적 인터페이스 Runnable
를 구현하므로 인터페이스를 구현하는 완전히 새로운 클래스를 만드는 대신 람다 구문을 사용하여 기능적 인터페이스를 만드는 메서드를 만들 수 있습니다. 필요합니다. 람다는 여전히 구현중인 기능적 인터페이스의 유형을 가지고 있음을 명심하십시오.
이를 염두에두고 한 단계 더 나아가 보겠습니다.
이것은 Runnable의 경우처럼 훌륭하게 작동합니다 new Thread(()->{//put code to run here});
. 기능적 인터페이스를 구현하기 위해 완전히 새로운 객체를 만드는 대신 이와 같은 새 스레드를 만들 수 있습니다. 이것은 컴파일러가 Thread()
Runnable 유형의 객체 를 취 한다는 것을 알고 있기 때문에 작동하므로 람다 표현식이 어떤 유형이어야하는지 알고 있습니다.
그러나 람다를 지역 변수에 할당하는 경우 컴파일러는이 람다가 구현하는 기능 인터페이스가 무엇인지 알지 못하므로 어떤 유형 var
이어야 하는지 추론 할 수 없습니다 . 사용자가 만든 기능적 인터페이스를 구현하거나 runnable
인터페이스 일 수 있으므로 알 수있는 방법이 없습니다.
이것이 람다가 var 키워드와 함께 작동하지 않는 이유입니다.
비 기능이기 때문에 :
이 처리는 이니셜 라이저가있는 로컬 변수, 향상된 for 루프의 인덱스 및 기존 for 루프에서 선언 된 로컬로 제한됩니다. 메서드 형식, 생성자 형식, 메서드 반환 형식, 필드, catch 형식 또는 다른 종류의 변수 선언에는 사용할 수 없습니다.
'Programing' 카테고리의 다른 글
Ansible : 별도의 Vault 파일에서 인벤토리 파일의 일부 변수를 암호화하는 방법은 무엇입니까? (0) | 2020.11.30 |
---|---|
Bootstrap 4의 열 중앙에 콘텐츠 배치 (0) | 2020.11.30 |
Django의 contrib.auth에서 모델 사용자의 이메일 필드를 고유하게 만드는 방법 (0) | 2020.11.30 |
/ usr / bin / codesign 명령이 종료 코드 1과 함께 실패했습니다. (0) | 2020.11.30 |
SQL Server에서 단일 행 MERGE / upsert 구문 (0) | 2020.11.30 |