Java에서 C # 'var'키워드에 해당하는 것은 무엇입니까?


264

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


4
val(나 var) 당신은 특히 "자바 교체"언어 ;-) 사용하는 경우

6
@ pst : 스칼라일까요? 그렇습니다.
— rsenna

IntelliJ의 경우 기능 요청으로 이것을 제출했습니다. youtrack.jetbrains.com/issue/IDEA-102808 IDE는 기본 코드에없는 경우에도 val 또는 var를 표시하도록 코드를 축소 할 수 있습니다.
— Jon Onstott

@Jon IntelliJ를 위해 무언가를 해킹했습니다 . 제 답변을 참조하십시오 .
— balpha

3
이제이 기능에 대한 제안이 Java에 포함되었습니다. openjdk.java.net/jeps/286
— McGin

답변:


248

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

편집 : 게시 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;

11
@Mike Caron : C #에는 [가상] 비가 상 호출이 있으며 연산자는 가상 var p = new X(); p.Z()이 아니므로 SuperX p = new X(); p.Z()모든 X 및 SuperX와 동일하지는 않습니다 X : SuperX. 와 정적 유형varp 항상 X하지만 항상 상기 첫 번째 예에서는 SuperX두 번째 예이다. 알아야 할 미묘하지만 중요한 차이점. 그러나 당신의 대답은 매우 정확합니다 :-)

200
@ 존 한나 : var코드를 덜 명확하게하지 않습니다. 내 의견으로는 반대입니다. 예를 들어 선언하고 인스턴스화 할 때 같은 행에 유형을 두 번 (또는 심지어 세 번) 쓰는 이유는 무엇입니까 (RadioButton radioButton = new RadioButton(); 입니까? var변수 이름을 지정할 때 유형이 아닌 기능성에 초점을 맞추기 때문에 두 번 생각하는 대신 UserCollection collection = new userRepository.GetUsers(); 보다 자연스럽게로 바뀝니다 var users = userRepository.GetUsers();). var확실하지 않다고 생각되면 사용하지 않기 때문입니다.
— Martin Odhelius

4
@MartinOdhelius var는 코드를 명확하게 잘 사용할 수있게하지만 너무 잘못 사용하면 명확하지 않을 수 있습니다. 많은 서식 옵션처럼. 익명의 개체 및 제네릭을 얼마나 많이 사용하는지에 따라 균형이 달라집니다. 둘 중 어느 것도 .NET 1.0에 존재하지 않으므로 C in의 첫 번째 버전에서 가상 키워드로 유용하지 않습니다. 나는 단지 이름을RadioButton radioButton 버튼이나 버튼이 중요한 유일한 것은 그것이 버튼 이었다는 것의 팩토리 또는 헬퍼 방법의 경우RadioButton 지을 var것이다.
— Jon Hanna

6
@ 존 한나 : 나는 var당신 만큼이나 한 번 비판적 이었지만, 나는 내 의견을 바꿨으며, 아마도 다른 의견에 대한 질문만큼 간단 할 수도 있습니다. 익명의 객체와 제네릭을 얼마나 많이 사용하고 있는지에 상관없이;) 타입 선언은 코드 노이즈 일뿐입니다.
— Martin Odhelius

3
var 를 anonymous types 와 혼동 하고 있습니다 . var단순히 컴파일러에게 할당에서 형식을 유추하도록 요청합니다. 그것은 구문 설탕이다. 나는 처음에 회의적이었다. 그러나 나는 그것을 종교적으로 사용했지만 아직 혼란을 야기한 시간에 직면하지 않았다. 인스턴스화 할 때 중복성을 제거하고 참조 할 때 유형을 확인할 필요가 없습니다. JAVA 9와 동등한 JAVA는 없습니다.
— Robear

46

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

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


1
@rightfold : 참조가 final불변 인 것은 아닙니다. 고려final StringBuilder strB = new StringBuilder("My reference is final"); strB.append("I'm not immutable");
— 마티아스 브라운

1
lombok v1.16.12부터에 대한 실험 지원도 있습니다 var. projectlombok.org/features/experimental/var.html
— Roel Spilker

@MatthiasBraun 귀하의 예가 잘못되었습니다. 이 경우 StringBuilder 클래스 자체는 변경할 수 없으며 메서드를 사용하여 내부 구조에 문자열 값을 추가하면됩니다. 이것은 완전히 합법적입니다.
— Andzej Maciusovic


20

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


현재 편집기에서 선언 유형을 접거나 펼칠 수있는 단축키를 사용하는 것이 좋습니다. 그래도 훌륭한 플러그인.
— 핫키

2
@hotkey IntelliJ의 내장 코드 폴딩을 사용하므로 Ctrl-Shift-NumPadPlus로 모든 것을 펼칠 수 있습니다. 커서가 접힌 변수 선언이 포함 된 행에있는 경우 Ctrl-NumPadPlus 및 Ctrl-NumPadMinus를 사용하여 현재 메소드에서 선언을 접거나 펼칠 수 있습니다. 모든 선언을 접는 것은 다소 어색합니다. 모든 것을 접은 다음 (Ctrl-Shift-NumPadMinus) 모든 것을 다시 펼칩니다 (Ctrl-Shift-NumPadPlus).
— balpha

18

3 월 20 일에 JDK 10이 릴리스되면서 Java var에 JEP 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 : 범위 선택을 참조하십시오 .


var필드 또는 리턴 유형에 사용할 수 없다는 점에서 Java와 c #의 차이점이 있습니까? 주목해야하는 이유는 무엇입니까?
— user1306322

@ user1306322 그런 맥락에서, no. varJava에서는 필드 또는 리턴 유형에 사용할 수 없습니다. 이 제한은 var상황에 따라 달라 지므로 일부 상황 (로컬 변수)에서만 사용할 수 있고 다른 상황에서는 사용할 수 없으므로 중요합니다. 이것은 반드시 Java와 C #의 차이점 일 필요는 없지만 Java에서 사용할 때 일반적으로 중요한 제한 사항입니다 var.
— 저스틴 알바노

방금 조회 한 결과 C # var에서 클래스 이름을 만들어 사용할 수 있는 것처럼 보입니다 . 기술적으로 c #의 경우 "컨텍스트 키워드"이지만 Java에서는 동일한 작업을 수행 할 수 없습니다. 틀 렸으면 말해줘.
— user1306322

1
당신이 올바른지. 당신은 사용할 수 없습니다 var클래스 이름이나 (일반 어쨌든되지 않습니다) 자바에서 인터페이스 이름으로,하지만 당신은 변수 이름, 메소드 이름 및 패키지 이름을 사용할 수 있습니다. 예를 들어, var var = 1;유효한 Java 문이지만 클래스를 선언하려고 public class var {}하면 오류가 발생 as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations합니다. varJava 의 이론적 근거 와 varC # 의 차이점 에 대해 자세히 설명하기 위해 위의 답변을 업데이트했습니다 .
— 저스틴 알바노

11

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 ==> []

3
제공 한 코드 (전 / 후 var)는 동일하지 않습니다. 이 var예 에서는 list유형 ArrayList이 아닌 유형 List입니다.
— 길리

8

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

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

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


"정확한 IDE"라고 말하면 Eclipse *는 제외됩니까? -이것은 Luna에서 작동하지 않는 것 같습니다 (적어도 방금 시도했을 때 int)-뭔가 빠졌습니까? (* : Eclipse를 괜찮은 IDE라고 부르지는 않지만 다른 사람들을 판단 할 수는 없습니다 ...)
— BrainSlugs83

@ BrainSlugs83 dunno IDEA를 사용하고 있습니다. 이클립스는 실제로 사용되지 않았습니다. 유형이 맞지 않습니까? 나는 실제로 제대로 작동한다는 것을 제외하고는 IDEA와 같은 c # / visual studio / resharper에 익숙합니다! 모든 JetBrains의에서 '- 그래서 INT의 소개로가 ALT-입력 할 수있는 오류 유형을 설정하고 그것을 밖으로 유형 분류에 도착 사람 누를 수있는 오류있을 때 제안 목록을 얻기 위해 고도를 입력
— JonnyRaa

5

JetBrains 로 Kotlin 을 살펴볼 수는 있지만 Val입니다. var가 아닙니다.


4
코 틀린에는 val과 var가 있습니다. val은 Java에서 변수 final을 선언하는 것과 동일하며 var는 재 할당을 허용합니다.
— samlewis

5

Java 10은 로컬 변수 유형 유추를 얻었으므로 이제는 var C #과 거의 동일합니다 (알고있는 한).

그것은 수도 비 denotable 유형 (프로그래머에 의해 그 자리에서 명명 할 수없는 종류, 비록 추론 된 유형이 아닌 다른 denotable이다). 예를 들어 트릭 과 익명 클래스의 트릭을 참조하십시오 (직장에서 절대 사용해서는 안됩니다)var .

내가 찾을 수있는 한 가지 차이점은 C #에서

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

Java 10에서는 var유효한 유형 이름이 아닙니다.


@Lii 예, 여기서 의미하는 바가 기억 나지 않습니다.
— Alexey Romanov

큰! 역사를 정리하기 위해 내 의견을 제거합니다!
— Lii

4

자바 (10)로, 동등한은 ... var.


있습니까 어떤 차이가? 나는 당신이 이것과 같은 짧은 대답을 쓰는 것보다 낫다는 것을 의미합니다. 그리고 분명히 약간의 차이 가 있어야합니다 .
— user1306322

@ user1306322 그것은 완전히 별개의 질문입니다! 이것의 많은 측면이 이미 요청되었으므로 java-10 태그를 확인할 수 있습니다.
— Brian Goetz

음,이는 이 먼저 사이드 바의 모든 관련 게시물에 링크 된대로이 인터넷 검색을하는 경우를보고 질문. 그래서 나는 당신이 그 질문에 대답하는 별도의 질문을 알고 있다면 적어도 그 질문에 링크하거나 그 일부를 답에 포함시킬 수 있다고 생각합니다.
— user1306322

3

나는 이것이 더 오래되었다는 것을 알고 있지만 var 클래스를 만들고 다른 유형의 생성자를 만들고 왜 어떤 생성자가 호출되는지에 따라 다른 유형의 var를 얻습니다. 한 유형을 다른 유형으로 변환하는 메소드를 빌드 할 수도 있습니다.


3

Lombokvar를 지원 하지만 여전히 실험으로 분류됩니다.

import lombok.experimental.var;

var number = 1; // Inferred type: int
number = 2; // Legal reassign since var is not final
number = "Hi"; // Compilation error since a string cannot be assigned to an int variable
System.out.println(number);

에서 사용할 때 피해야 할 함정은 다음과 같습니다IntelliJ IDEA . 자동 완성 및 모든 것을 포함하여 예상대로 작동하는 것으로 보입니다. "해킹되지 않은"솔루션이있을 때까지 (예 : JEP 286 : Local-Variable Type Inference )이 방법이 가장 좋습니다.

참고 val로 지원입니다 Lombok수정 또는를 만들지 않고뿐만 아니라 lombok.config.


2

Java 10에서는 로컬 변수에 대해서만 가능합니다 .

넌 할 수있어

var anum = 10; var aString = "Var";

그러나 할 수 없습니다

var anull = null; // Since the type can't be inferred in this case

자세한 내용 은 사양 을 확인하십시오 .


2
이것은 올바르지 않습니다. var캡처 유형, 교차 유형 및 익명 클래스 유형을 포함하여 여러 유형의 선언 할 수없는 유형에 사용할 수 있습니다. Java 11부터는 람다 매개 변수에도 적용 할 수 있습니다.
— Brian Goetz

0

일반적으로 모든 유형에 Object 클래스를 사용할 수 있지만 나중에 유형 캐스팅을 수행했습니다!

예 :-

Object object = 12;
    Object object1 = "Aditya";
    Object object2 = 12.12;

    System.out.println(Integer.parseInt(object.toString()) + 2);

    System.out.println(object1.toString() + " Kumar");
    System.out.println(Double.parseDouble(object2.toString()) + 2.12);

Aditya, 다른 모든 답변을 확인하십시오. 그들 중 많은 사람들이 -1을 가지고 있으며 아마도 좋은 이유가 있습니다. 정확하지 않은 경우 아무 것도 게시하지 마십시오.
— user1306322

@ user1306322 내 대답에 무엇이 문제입니까! 정교하게 할 수 있습니까? 모든 데이터 유형에 Object 클래스를 사용할 수 없습니까?
— Aditya Kumar

객체 객체 = 12; Object object1 = "Aditya"; 객체 object2 = 12.12; System.out.println (정수 .parseInt (object.toString ()) + 2); System.out.println (object1.toString () + "Kumar"); System.out.println (Double.parseDouble (object2.toString ()) + 2.12);
— Aditya Kumar

문제는 질문을 이해하지 못했다는 것입니다. 문제는 "이 작업을 수행하는 방법"이 아니라 "이런 일이 있는가"였습니다. 당신은 잘못된 질문에 대답합니다. 으로 var공식적 언어로 단어, 당신의 대답은 지금은 옛날 방식을 참조한다.
— user1306322

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.