[java] Java에서 C # ‘var’키워드에 해당하는 것은 무엇입니까?

중 하나 개를 사용 var에 C #의 키워드는 암시 적 형식 선언이다. var에 대한 Java 등가 구문은 무엇입니까 ?



답변

없습니다. 아아, 당신은 전체 유형 이름을 입력해야합니다.

편집 : 게시 7 년 후, 로컬 변수에 대한 유형 유추 (와 var)가 Java 10에 추가되었습니다.

편집 : 게시 후 6 년 동안 아래에서 의견을 수집하십시오.

  • C #에 var키워드가있는 이유는 .NET에 이름이없는 유형을 가질 수 있기 때문입니다. 예 :

    var myData = new { a = 1, b = "2" };

    이 경우에 적절한 유형을 부여하는 것은 불가능합니다 myData. 6 년 전, Java에서는 불가능했습니다 (모든 유형은 이름이 매우 장황하고 부조 한 경우에도 이름이있었습니다). 그 동안 이것이 변했는지 알 수 없습니다.

  • var와 동일하지 않습니다 dynamic. variables는 여전히 100 % 정적으로 입력됩니다. 이것은 컴파일되지 않습니다 :

    var myString = "foo";
    myString = 3;
  • var컨텍스트에서 유형이 분명한 경우에도 유용합니다. 예를 들면 다음과 같습니다.

    var currentUser = User.GetCurrent();

    내가 책임지고있는 코드 에서 클래스가 파생되었거나 클래스를 currentUser가지고 있다고 말할 수 있습니다 User. 분명히, 당신의 구현이 User.GetCurrentint 를 반환 한다면 , 이것은 당신에게 해를 끼칠 것입니다.

  • 이것과는 아무런 관련이 var없지만 다른 메소드 (예 :)로 메소드를 음영 처리하는 이상한 상속 계층 구조가있는 경우 new public void DoAThing()비가 상 메소드가 유형에 의해 영향을 받는다는 것을 잊지 마십시오.

    이것이 좋은 디자인을 나타내는 실제 시나리오를 상상할 수는 없지만 예상대로 작동하지 않을 수 있습니다.

    class Foo {
        public void Non() {}
        public virtual void Virt() {}
    }
    
    class Bar : Foo {
        public new void Non() {}
        public override void Virt() {}
    }
    
    class Baz {
        public static Foo GetFoo() {
            return new Bar();
        }
    }
    
    var foo = Baz.GetFoo();
    foo.Non();  // <- Foo.Non, not Bar.Non
    foo.Virt(); // <- Bar.Virt
    
    var bar = (Bar)foo;
    bar.Non();  // <- Bar.Non, not Foo.Non
    bar.Virt(); // <- Still Bar.Virt

    표시된대로 가상 메소드는 이에 영향을받지 않습니다.

  • 아니요, var실제 변수없이 초기화하는 비 서투른 방법은 없습니다 .

    var foo1 = "bar";        //good
    var foo2;                //bad, what type?
    var foo3 = null;         //bad, null doesn't have a type
    var foo4 = default(var); //what?
    var foo5 = (object)null; //legal, but go home, you're drunk

    이 경우 구식 방식으로 수행하십시오.

    object foo6;

답변

프로젝트에 Lombok을 추가하면 해당 val 키워드를 사용할 수 있습니다 .

http://projectlombok.org/features/val.html


답변

JEP-JDK 개선 제안

http://openjdk.java.net/jeps/286

JEP 286 : 로컬 변수 유형 유추

저자 Brian Goetz

// Goals:
var list = new ArrayList<String>();  // infers ArrayList<String>
var stream = list.stream();          // infers Stream<String>


답변

나는 IntelliJ 용 플러그인을 만들어서 varJava로 제공합니다 . 그것은 해킹이므로 일반적인 면책 조항이 적용되지만 Java 개발에 IntelliJ를 사용하고 시도 하려면 https://bitbucket.org/balpha/varsity에 있습니다.


답변

3 월 20 일에 JDK 10이 릴리스되면서 Java varJEP 286에 지정된대로 키워드가 아닌 예약 된 유형 이름이 포함됩니다 (아래 참조) . 지역 변수의 경우 이제 다음이 Java 10 이상에서 유효합니다.

var map = new HashMap<String, Integer>();

var자바에서 예약 유형 이름은 거의 동일 var모두 암시 타이핑 (중요한 차이점은 아래 참조) 할 수 있다는에서 C #의 키워드. varJava에서는 JEP 286 : Goals에 열거 된대로 다음 컨텍스트에서 암시 적 유형 유추에만 사용할 수 있습니다 .

  • 이니셜 라이저가있는 지역 변수
  • 향상된 for 루프의 인덱스
  • 전통적인 for-loop로 선언 된 지역 주민

따라서 필드, 리턴 유형, 클래스 이름 또는 인터페이스 이름에는 사용할 var 수 없습니다 . JEP 286 (Brian Goetz 작성)에 명시된 바와 같이 로컬 변수를 선언하고 정의 할 때 긴 유형 이름을 포함 할 필요가 없어야합니다.

개발자는 Java 코드 작성과 관련된 의식을 줄이고 정적 유형 안전에 대한 Java의 약속을 유지하면서 개발자가 불필요하게 로컬 변수 유형의 매니페스트 선언을 제거 할 수 있도록하여 개발자 경험을 개선하고자합니다.

var 자바 범위

주목해야한다 var자바의 키워드가 아니라 예약 유형 이름이 아닙니다. JEP 286에서 인용 한 바와 같이 :

식별자 var는 키워드가 아닙니다. 대신 예약 된 유형 이름입니다. 이는 var를 변수, 메소드 또는 패키지 이름으로 사용하는 코드는 영향을받지 않습니다. var를 클래스 또는 인터페이스 이름으로 사용하는 코드는 영향을받습니다 (그러나 이러한 이름은 일반적인 명명 규칙을 위반하기 때문에 실제로는 드 rare니다).

이후 있습니다 var예약 유형 이름이 아닌 키워드입니다, 그것은 여전히 (새로운 유형의 간섭 역할과 함께) 패키지 이름, 메소드 이름, 변수 이름을 사용할 수 있습니다. 예를 들어, 다음은 varJava에서 의 올바른 사용 예입니다 .

var i = 0;
var var = 1;
for (var i = 0; i < 10; i++) { /* ... */ }
public int var() { return 0; }
package var;

JEP 286에서 인용 한 바와 같이 :

이 처리는 이니셜 라이저, 향상된 for-loop의 색인 및 전통적인 for-loop에서 선언 된 지역 변수를 사용하는 지역 변수로 제한됩니다. 메소드 형식, 생성자 형식, 메소드 리턴 유형, 필드, catch 형식 또는 기타 변수 선언에는 사용할 수 없습니다.

varJava와 C의 차이점

이것은 varC #과 Java의 차이점 중 하나 입니다. C # var에서는 유형 이름으로 사용할 수 있지만 Java에서는 클래스 이름이나 인터페이스 이름으로 사용할 수 없습니다. C # 설명서 에 따르면 (암시 적으로 형식화 된 지역 변수) :

명명 된 유형 var이 범위 내에 있으면 var키워드는 해당 유형 이름으로 해석되며 암시 적으로 유형이 지정된 로컬 변수 선언의 일부로 취급되지 않습니다.

varC #에서 유형 이름 으로 사용하는 기능 은 약간의 복잡성을 야기하고 복잡한 해결 규칙을 도입합니다. 이는 varJava var에서 클래스 또는 인터페이스 이름 으로 허용하지 않기 때문에 피할 수 없습니다 . varC #에서 형식 이름 의 복잡성에 대한 자세한 내용은 암시 적으로 형식화 된 변수 선언에 대한 제한 적용을 참조하십시오 . `var in Java의 범위 결정에 대한 이론적 근거에 대한 자세한 정보는 JEP 286 : 범위 선택을 참조하십시오 .


답변

JDK 10에서 지원 될 것입니다. 초기 액세스 빌드 에서 실제로 작동하는 것을 볼 수도 있습니다. 입니다. .

JEP 286 :

이니셜 라이저를 사용하여 유형 유추를 로컬 변수 선언으로 확장하도록 Java 언어를 향상 시키십시오.

이제 글을 쓰는 대신

List<> list = new ArrayList<String>();
Stream<> stream = myStream();

당신은 쓰기:

var list = new ArrayList<String>();
var stream = myStream();

노트:

  • var 이제는 예약 된 유형 이름입니다.
  • 자바는 여전히 정적 타이핑에 전념하고 있습니다!
  • 로컬 변수 선언 에서만 사용할 수 있습니다

로컬 시스템에 Java를 설치하지 않고 시도해보고 싶다면 JDK 10이 설치된 Docker 이미지 를 만들었 습니다.

$ docker run -it marounbassam/ubuntu-java10 bash
root@299d86f1c39a:/# jdk-10/bin/jshell
Mar 30, 2018 9:07:07 PM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
|  Welcome to JShell -- Version 10
|  For an introduction type: /help intro

jshell> var list = new ArrayList<String>();
list ==> []


답변

간단한 솔루션 (괜찮은 IDE를 사용한다고 가정)은 어디서나 ‘int’를 입력 한 다음 유형을 설정하도록하는 것입니다.

실제로 ‘var’이라는 클래스를 추가했기 때문에 다른 것을 입력하지 않아도됩니다.

코드는 여전히 장황하지만 적어도 입력 할 필요는 없습니다!