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
varanonymous 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 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 : 범위 선택을 참조하십시오 .


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.