web-dev-qa-db-de.com

Was ist das Äquivalent zum C # 'var' Schlüsselwort in Java?

Das Schlüsselwort var in C # kann implizit als Typ deklariert werden. Was ist die Java-äquivalente Syntax für var ?

243
Arturo

Da ist gar nichts. Leider müssen Sie den vollständigen Typnamen eingeben.

Bearbeiten: 7 Jahre nach der Veröffentlichung wurde in Java 10 die Typinferenz für lokale Variablen (mit var) hinzugefügt. 

Bearbeiten: 6 Jahre nach der Veröffentlichung, um einige Kommentare von unten zu sammeln:

  • Der Grund, warum C # das Schlüsselwort var hat, liegt darin, dass es Typen gibt, die in .NET keinen Namen haben. Z.B:

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

    In diesem Fall wäre es unmöglich, myData einen geeigneten Typ zu geben. Vor 6 Jahren war dies in Java nicht möglich (alle Typen hatten Namen, auch wenn sie extrem wortreich und unkompliziert waren). Ich weiß nicht, ob sich das inzwischen geändert hat.

  • var ist nicht das Gleiche wie dynamic. variables sind immer noch zu 100% statisch typisiert. Das wird nicht kompilieren:

    var myString = "foo";
    myString = 3;
    
  • var ist auch nützlich, wenn der Typ aus dem Kontext ersichtlich ist. Zum Beispiel:

    var currentUser = User.GetCurrent();
    

    Ich kann sagen, dass currentUser in jedem Code, für den ich verantwortlich bin, eine User- oder eine abgeleitete Klasse enthält. Wenn Ihre Implementierung von User.GetCurrent ein int zurückgibt, ist dies offensichtlich ein Nachteil für Sie.

  • Dies hat nichts mit var zu tun, aber wenn Sie seltsame Vererbungshierarchien haben, in denen Sie Methoden mit anderen Methoden spiegeln (z. B. new public void DoAThing()), vergessen Sie nicht, dass nicht-virtuelle Methoden von dem Typ betroffen sind, in den sie umgewandelt werden.

    Ich kann mir kein reales Szenario vorstellen, in dem dies auf gutes Design hindeutet, aber dies funktioniert möglicherweise nicht wie erwartet:

    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
    

    Wie bereits erwähnt, sind virtuelle Methoden davon nicht betroffen.

  • Nein, es gibt keinen unbeholfenen Weg, eine var ohne eine tatsächliche Variable zu initialisieren.

    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
    

    In diesem Fall machen Sie es einfach auf die alte Weise:

    object foo6;
    
231
Mike Caron

Wenn Sie Lombok zu Ihrem Projekt hinzufügen, können Sie das Schlüsselwort val verwenden.

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

43
darthtrevino

JEP - JDK-Erweiterungsvorschlag

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

JEP 286: Typinferenz lokaler Variablen

Autor Brian Goetz

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

Ich habe ein Plugin für IntelliJ zusammengestellt, das Ihnen in gewisser Weise var in Java gibt. Es ist ein Hack, also gelten die üblichen Haftungsausschlüsse, aber wenn Sie IntelliJ für Ihre Java-Entwicklung verwenden und es ausprobieren möchten, finden Sie dies unter https://bitbucket.org/balpha/varsity .

20
balpha

Mit der Veröffentlichung von JDK 10 am 20. März enthält Java jetzt einen var reservierten Typnamen (kein Schlüsselwort - siehe unten), wie in JEP 286 angegeben. Für lokale Variablen gilt jetzt Folgendes in Java 10 oder höher:

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

Der reservierte var-Typname in Java ist nahezu identisch mit dem Schlüsselwort var in C #, da beide die implizite Typisierung zulassen (wichtige Unterschiede siehe unten). var in Java kann nur für implizite Typinferenz in den folgenden Kontexten verwendet werden (wie in JEP 286: Goals ) aufgezählt:

  • lokale Variablen mit Initialisierern
  • indizes in der erweiterten for-Schleife
  • einheimische, die in einer traditionellen for-Schleife deklariert wurden

Daher kann varnicht für Felder, Rückgabetypen, Klassennamen oder Schnittstellennamen verwendet werden. Der Grund ist, die Notwendigkeit für die Angabe langer Typnamen bei der Deklaration und Definition von lokalen Variablen zu beseitigen, wie in JEP 286 (Autor: Brian Goetz):

Wir möchten die Entwicklererfahrung verbessern, indem wir die Zeremonie reduzieren verbunden mit dem Schreiben von Java-Code, während Java die Verpflichtung einhält zur statischen Typensicherheit, indem die Entwickler die Möglichkeit haben, die oft unnötige Manifest-Deklaration lokaler Variablentypen. 

var Scoping in Java

Es ist zu beachten, dass var in Java kein Schlüsselwort ist, sondern ein reservierter Typname. Wie aus JEP 286 zitiert:

Der Bezeichner var ist kein Schlüsselwort. stattdessen ist es ein reservierter Typ Name. Dies bedeutet, dass der Code var als Variable, Methode oder .__ verwendet. Der Paketname wird nicht beeinflusst. Code, der var als Klasse oder .__ verwendet. Der Name der Schnittstelle wird beeinflusst (diese Namen sind jedoch in der Praxis selten...., da sie gegen die üblichen Namenskonventionen verstoßen).

Da var ein reservierter Typname und kein Schlüsselwort ist, kann er weiterhin für Paketnamen, Methodennamen und Variablennamen (zusammen mit der neuen Typinterferenzrolle) verwendet werden. Im Folgenden finden Sie alle Beispiele für gültige Verwendungen von var in Java:

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

Wie aus JEP 286 zitiert:

Diese Behandlung wäre auf lokale Variablen mit .__ beschränkt. Initialisierer, Indizes in der erweiterten for-Schleife und in .__ deklarierte Locals. eine traditionelle for-Schleife; es wäre nicht für Methodenformale verfügbar, Konstruktorformale, Methodenrückgabetypen, Felder, Catchformals oder jede andere Art von Variablendeklaration.

Unterschiede zwischen var in Java & C #

Dies ist ein bemerkenswerter Unterschied zwischen var in C # und Java umfasst Folgendes: var kann als Typname in C # verwendet werden, kann jedoch nicht als Klassenname oder Schnittstellenname in Java verwendet werden. Entsprechend der C # -Dokumentation (implizit typisierte lokale Variablen) :

Wenn sich ein Typ mit dem Namen var im Gültigkeitsbereich befindet, wird das Schlüsselwort var in .__ aufgelöst. dieser Typname und wird nicht als Teil eines implizit typisierten .__ behandelt. lokale Variablendeklaration.

Die Verwendung von var als Typname in C # führt zu einer gewissen Komplexität und führt zu komplexen Auflösungsregeln, die von var in Java vermieden werden, indem var als Klassen- oder Schnittstellenname verboten wird. Informationen zu den Komplexitäten von var-Typnamen in C # finden Sie unter Einschränkungen gelten für implizit typisierte Variablendeklarationen . Weitere Informationen zu den Gründen für die Festlegung des Bereichs für `var in Java finden Sie unter JEP 286: Auswahlmöglichkeiten für das Scoping .

13
Justin Albano

Es wird in JDK 10 unterstützt. Es ist sogar möglich, es im Early Access Build in Aktion zu sehen.

Der JEP 286 :

Erweitern Sie die Java-Sprache, um die Typinferenz auf Deklarationen lokaler Variablen mit Initialisierern zu erweitern.

Also jetzt anstatt zu schreiben:

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

Du schreibst:

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

Anmerkungen:

  • var ist jetzt ein reservierter Typname
  • Java ist still Verpflichtung zur statischen Typisierung!
  • Es kann nur in local Variablendeklarationen verwendet werden

Wenn Sie es versuchen möchten, ohne Java auf Ihrem lokalen System zu installieren, habe ich ein Docker-Image erstellt, auf dem JDK 10 installiert ist:

$ docker run -it marounbassam/ubuntu-Java10 bash
[email protected]:/# 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 ==> []
11
Maroun

Eine einfache Lösung (vorausgesetzt, Sie verwenden eine anständige IDE) ist, einfach überall "int" einzugeben und dann den Typ für Sie festzulegen.

Ich habe eigentlich nur eine Klasse mit dem Namen 'var' hinzugefügt, damit ich nicht etwas anderes eingeben muss.

Der Code ist noch zu ausführlich, aber Sie müssen ihn zumindest nicht eingeben!

8
JonnyRaa

Java 10 hat einen lokalen Variablentyp-Inferenzsatz erhalten, so dass jetzt var verwendet wird, was ziemlich genau dem C # -Äquivalent entspricht (soweit mir bekannt ist).

Es können auch nicht-bezeichnende Typen abgeleitet werden (Typen, die vom Programmierer an dieser Stelle nicht benannt werden konnten; obwohl welche -Typen nicht-bezeichnend sind, ist anders, zB hat Java keine Entsprechung mit anonymen C # -Typen). .

Der einzige Unterschied, den ich finden konnte, ist, dass in C #

Wenn ein Typ mit dem Namen var im Gültigkeitsbereich liegt, wird das Schlüsselwort var in diesen Typnamen aufgelöst und nicht als Teil einer implizit typisierten lokalen Variablendeklaration behandelt.

In Java 10 ist var kein zulässiger Typname.

5
Alexey Romanov

Sie können einen Blick auf Kotlin von JetBrains werfen, aber es ist val. nicht var.

5
Artiom

Ich weiß, dass dies älter ist, aber warum nicht eine var-Klasse erstellen und Konstruktoren mit unterschiedlichen Typen erstellen. Abhängig davon, welche Konstruktoren aufgerufen werden, erhalten Sie var mit verschiedenen Typen. Sie können sogar Methoden einbauen, um einen Typ in einen anderen zu konvertieren. 

3
Sebastian Zaba

Ab Java 10 ist das Äquivalent ... var

3
Brian Goetz

Lombok unterstützt var aber es wird immer noch als experimentell klassifiziert:

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);

Hier ist eine Falle, die zu vermeiden ist, wenn Sie versuchen, es in IntelliJ IDEA zu verwenden. Es scheint jedoch wie erwartet zu funktionieren, einschließlich automatischer Vervollständigung und allem. Bis es eine "nicht hackige" Lösung gibt (z. B. wegen JEP 286: Local-Variable Type Inference ), könnte dies momentan die beste Lösung sein.

Beachten Sie, dass val auch von Lombok unterstützt wird, ohne einen lombok.config zu ändern oder zu erstellen.

3
BullyWiiPlaza

Sie können in Java 10 jedoch nur für Local - Variablen, dh,

Sie können, 

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

Kann aber nicht

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

Schauen Sie sich die spec für weitere Informationen an.

2
Antho Christen

Im Allgemeinen können Sie die Object-Klasse für jeden Typ verwenden, Sie haben jedoch später eine Typumwandlung! 

z.B:- 

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);
0
Aditya Kumar