Jednym zastosowaniem słowa kluczowego var w języku C # jest niejawna deklaracja typu. Jaka jest równoważna składnia Java dla var ?
Jednym zastosowaniem słowa kluczowego var w języku C # jest niejawna deklaracja typu. Jaka jest równoważna składnia Java dla var ?
Odpowiedzi:
Nie ma żadnego. Niestety, musisz wpisać pełną nazwę typu.
Edycja: 7 lat po opublikowaniu var
w Javie 10 dodano wnioskowanie o zmiennych lokalnych (z ).
Edycja: 6 lat po opublikowaniu, aby zebrać niektóre komentarze poniżej:
Powodem, dla którego C # zawiera to var
słowo kluczowe, jest to, że można mieć typy, które nie mają nazwy w .NET. Na przykład:
var myData = new { a = 1, b = "2" };
W takim przypadku podanie odpowiedniego typu byłoby niemożliwe myData
. 6 lat temu było to niemożliwe w Javie (wszystkie typy miały nazwy, nawet jeśli były bardzo gadatliwe i niezdarne). Nie wiem, czy to się zmieniło w międzyczasie.
var
to nie to samo co dynamic
. var
iables są nadal w 100% typowane statycznie. To nie będzie kompilować:
var myString = "foo";
myString = 3;
var
jest także przydatny, gdy typ jest oczywisty z kontekstu. Na przykład:
var currentUser = User.GetCurrent();
Mogę powiedzieć, że w każdym kodzie, za który jestem odpowiedzialny, currentUser
ma User
klasę pochodną. Oczywiście, jeśli twoja implementacja User.GetCurrent
zwraca int, to może to ci szkodzić.
Nie ma to nic wspólnego var
, ale jeśli masz dziwne hierarchie dziedziczenia, w których metody cieniowane są innymi metodami (np. new public void DoAThing()
), Nie zapominaj, że na metody nie-wirtualne ma wpływ typ, w jakim są rzutowane.
Nie wyobrażam sobie scenariusza z prawdziwego świata, w którym świadczy to o dobrym projekcie, ale może nie działać zgodnie z oczekiwaniami:
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
Jak wskazano, nie ma to wpływu na metody wirtualne.
Nie, nie ma niezręcznego sposobu na zainicjowanie var
zmiennej bez rzeczywistej.
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
W takim przypadku po prostu zrób to w staromodny sposób:
object foo6;
var p = new X(); p.Z()
nie jest taki sam jak SuperX p = new X(); p.Z()
dla wszystkich X i SuperX, chociaż X : SuperX
. Z var
tej statycznej typu od p
zawsze jest X
w pierwszym przykładzie powyżej, ale zawsze SuperX
w drugim przykładzie. Subtelna, ale ważna różnica, o której należy pamiętać. Ale twoja odpowiedź jest bardzo poprawna :-)
var
nie wyjaśnia kodu. Wręcz przeciwnie, moim zdaniem. Po co na przykład pisać typ dwa (a nawet trzy) razy w tym samym wierszu, kiedy go deklarujesz i tworzysz jego instancję ( RadioButton radioButton = new RadioButton();
)? var
sprawia, że myślisz dwa razy, gdy nazywasz zmienne, ponieważ skupia się on na funkcjonalności, a nie na typie (na przykład UserCollection collection = new userRepository.GetUsers();
, bardziej naturalnie, zmienia się w var users = userRepository.GetUsers();
). Jeśli uważasz, że var
jest niejasne, to tylko dlatego, że nie jest do tego przyzwyczajony.
var
całą pewnością potrafi dobrze wyczyścić kod, ale może też spowodować, że będzie zbyt niejasny; jak wiele opcji formatowania. Saldo różni się w zależności od tego, jak często korzystasz z anonimowych obiektów i rodzajów, z których żaden nie istniał w .NET 1.0, co czyni go mniej użytecznym jako hipotetyczne słowo kluczowe w pierwszej wersji C♯. Nazwałbym tylko RadioButton
radioButton
w przypadku metody fabrycznej lub pomocniczej, w której jedyną znaczącą rzeczą w przycisku był fakt, że był to RadioButton
, w przeciwnym razie to szaleństwo z lub bez var
.
var
jak ty, jeśli nie bardziej, ale zmieniłem zdanie i być może jest to tak proste, jak kwestia różnych opinii, ponieważ nadal uważam, że się mylisz, kiedy mówisz, że to nieważne, ile używasz anonimowych obiektów i generycznych;) Deklaracja typu najczęściej jest po prostu szumem kodu, jeśli nie możesz zrozumieć kodu bez niego, kod jest prawdopodobnie niejasny w obu przypadkach.
var
sam prosi kompilator o wywnioskowanie typu z przydziału; to cukier syntaktyczny. Na początku byłem sceptyczny, ale używam go religijnie i jeszcze nie spotkałem się z czasem, kiedy to spowodowało zamieszanie. Usuwa nadmiarowość podczas tworzenia instancji i eliminuje potrzebę sprawdzania typu podczas odwoływania się. Nie ma odpowiednika JAVA od JAVA 9.
Jeśli dodasz Lombok do swojego projektu, możesz użyć jego słowa kluczowego val .
final
nie są koniecznie niezmienne. Zastanów sięfinal StringBuilder strB = new StringBuilder("My reference is final"); strB.append("I'm not immutable");
var
. projectlombok.org/features/experimental/var.html
JEP - Propozycja ulepszenia JDK
http://openjdk.java.net/jeps/286
JEP 286: Wnioskowanie o typie zmiennej lokalnej
Autor Brian Goetz
// Goals:
var list = new ArrayList<String>(); // infers ArrayList<String>
var stream = list.stream(); // infers Stream<String>
Przygotowałem wtyczkę dla IntelliJ, która - w pewnym sensie - daje ci var
Javę. Jest to hack, więc obowiązują zwykłe zastrzeżenia, ale jeśli używasz IntelliJ do programowania Java i chcesz go wypróbować, znajdziesz go na https://bitbucket.org/balpha/varsity .
Wraz z wydaniem JDK 10 20 marca Java zawiera teraz var
nazwę typu zastrzeżonego (nie słowo kluczowe - patrz poniżej), jak określono w JEP 286 . W przypadku zmiennych lokalnych w Java 10 lub nowszej obowiązuje teraz:
var map = new HashMap<String, Integer>();
Nazwa var
typu zarezerwowanego w Javie jest prawie identyczna ze var
słowem kluczowym w języku C #, ponieważ oba pozwalają na niejawne pisanie (ważne różnice poniżej). var
w Javie można używać wyłącznie do wnioskowania typu niejawnego w następujących kontekstach (jak wyliczono w JEP 286: Cele ):
Dlatego var
nie można go używać do pól, typów zwracanych, nazw klas ani nazw interfejsów. Jego uzasadnieniem jest usunięcie potrzeby dołączania długich nazw typów podczas deklarowania i definiowania zmiennych lokalnych, jak stwierdzono w JEP 286 (autor: Brian Goetz):
Staramy się poprawić wrażenia programistów, zmniejszając ceremonię związaną z pisaniem kodu Java, przy jednoczesnym utrzymaniu zaangażowania Javy w bezpieczeństwo typu statycznego, umożliwiając programistom unikanie często niepotrzebnej manifestacji lokalnych zmiennych.
var
Określanie zakresu w JavieNależy zauważyć, że var
nie jest słowem kluczowym w Javie, ale raczej nazwą typu zarezerwowanego. Jak cytowano z JEP 286:
Identyfikator var nie jest słowem kluczowym; zamiast tego jest to nazwa typu zarezerwowanego. Oznacza to, że kod, który używa var jako zmiennej, metody lub nazwy pakietu, nie zostanie zmieniony; wpłynie to na kod, który używa var jako nazwy klasy lub interfejsu (ale nazwy te są rzadkie w praktyce, ponieważ naruszają zwykłe konwencje nazewnictwa).
Należy pamiętać, że ponieważ var
jest to nazwa typu zarezerwowanego, a nie słowo kluczowe, nadal można jej używać w nazwach pakietów, nazwach metod i nazwach zmiennych (wraz z nową rolą zakłócania typu). Na przykład następujące są wszystkie przykłady prawidłowego użycia var
w Javie:
var i = 0;
var var = 1;
for (var i = 0; i < 10; i++) { /* ... */ }
public int var() { return 0; }
package var;
Jak cytowano z JEP 286:
To leczenie byłoby ograniczone do zmiennych lokalnych z inicjalizatorami, indeksów w rozszerzonej pętli for i miejscowych zadeklarowanych w tradycyjnej pętli for; nie byłby dostępny dla formałów metod, konstruktorów, typów zwracanych metod, pól, formałów catch ani innych deklaracji zmiennych.
var
w Javie i C.Jest to jedna zauważalna różnica między językami var
C # i Java: var
mogą być używane jako nazwa typu w języku C #, ale nie mogą być używane jako nazwa klasy lub nazwa interfejsu w języku Java. Zgodnie z dokumentacją w języku C # (niejawnie wpisane zmienne lokalne) :
Jeśli nazwany typ
var
jest objęty zakresem,var
słowo kluczowe rozpozna nazwę tego typu i nie będzie traktowane jako część niejawnie wpisanej deklaracji zmiennej lokalnej.
Możliwość użycia var
jako nazwy typu w języku C # powoduje pewną złożoność i wprowadza pewne skomplikowane reguły rozwiązywania, których można uniknąć var
w Javie, uniemożliwiając używanie nazwy var
klasy lub interfejsu. Aby uzyskać informacje na temat złożoności var
nazw typów w języku C #, zobacz Ograniczenia dotyczą niejawnie deklarowanych zmiennych . Aby uzyskać więcej informacji na temat uzasadnienia decyzji dotyczącej zakresu dla `var w Javie, zobacz JEP 286: Wybory zakresu .
var
do pól lub typów zwracanych? Dlaczego warto to zauważyć?
var
w Javie nie można używać dla pól ani typów zwracanych. Jest to ważne, ponieważ to ograniczenie var
uwarunkowane jest kontekstem, gdzie można go używać tylko w niektórych kontekstach (zmienne lokalne), a nie w innych. Należy zauważyć, że niekoniecznie jest to różnica między Javą i C #, ale ogólnie ważne ograniczenie przy korzystaniu var
z Java.
var
nazwę klasy i używać jej jako takiej. Technicznie jest to „kontekstowe słowo kluczowe” w przypadku c #, ale w Javie wydaje się, że nie można zrobić tego samego. Popraw mnie, jeśli się mylę.
var
jako nazwy klasy lub nazwy interfejsu w Javie (co zresztą i tak nie jest powszechne), ale można go używać do nazw zmiennych, nazw metod i nazw pakietów. Na przykład, var var = 1;
to ważne stwierdzenie Java ale próbuje zadeklarować klasę jako public class var {}
powoduje błąd: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations
. Zaktualizowałem powyższą odpowiedź, aby uzyskać bardziej szczegółowe informacje na temat uzasadnienia var
w Javie i jej różnic var
w stosunku do C #.
Będzie obsługiwany w JDK 10. Można go nawet zobaczyć w działaniu w kompilacji wczesnego dostępu .
JEP 286 :
Ulepsz język Java, aby rozszerzyć wnioskowanie o typ na deklaracje zmiennych lokalnych za pomocą inicjatorów.
Więc teraz zamiast pisać:
List<> list = new ArrayList<String>();
Stream<> stream = myStream();
Ty piszesz:
var list = new ArrayList<String>();
var stream = myStream();
Uwagi:
var
jest teraz nazwą typu zarezerwowanegoJeśli chcesz spróbować bez instalacji Java w systemie lokalnym, stworzyłem obraz Docker z zainstalowanym JDK 10:
$ 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 ==> []
var
) nie jest równoważny. W tym var
przykładzie list
jest typu ArrayList
, a nie a List
.
Prostym rozwiązaniem (zakładając, że używasz przyzwoitego IDE) jest wpisanie wszędzie „int”, a następnie ustawienie go dla Ciebie.
Właśnie dodałem klasę o nazwie „var”, więc nie muszę wpisywać czegoś innego.
Kod jest wciąż zbyt szczegółowy, ale przynajmniej nie musisz go pisać!
int
) - czy coś mi brakuje? (*: chociaż nigdy nie nazwałbym Eclipse porządnym IDE, nie mogę oceniać innych ...)
Java 10 uzyskała wnioskowanie na temat lokalnych zmiennych, więc teraz ma var
prawie odpowiednik C # one (o ile mi wiadomo).
Może również wywnioskować non-denotable rodzajów (typów, które nie mogą być nazwane w tym miejscu przez programistę, choć których typy są non-denotable jest inna). Zobacz np. Sztuczki var
i anonimowe zajęcia (których nigdy nie powinieneś używać w pracy) .
Jedną różnicą, którą mogłem znaleźć, jest to, że w C #
W Javie 10 var
nie jest prawidłową nazwą typu.
Jak Java 10, odpowiednikiem jest ... var
.
Wiem, że jest to starsze, ale dlaczego nie stworzyć klasy var i stworzyć konstruktorów z różnymi typami, a zależnie od tego, który konstruktor zostanie wywołany, otrzymasz var z innym typem. Możesz nawet wbudować metody konwersji jednego typu na inny.
Lombok
obsługuje var, ale nadal jest klasyfikowany jako eksperymentalny:
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);
Oto pułapka, której należy unikać, próbując jej użyć IntelliJ IDEA
. Wygląda na to, że działa zgodnie z oczekiwaniami, włączając automatyczne uzupełnianie i wszystko. Dopóki nie będzie rozwiązania „niehakującego” (np. Z powodu JEP 286: Lokalne wnioskowanie o typ zmiennej ), może to być teraz najlepszy wybór.
Pamiętaj, że val
jest to również wsparcie Lombok
bez modyfikowania ani tworzenia lombok.config
.
Możesz w Javie 10, ale tylko dla zmiennych lokalnych , co oznacza,
Możesz,
var anum = 10; var aString = "Var";
Ale nie mogę
var anull = null; // Since the type can't be inferred in this case
Sprawdź specyfikację, aby uzyskać więcej informacji.
var
może być używany do wielu form typów nieoznaczalnych, w tym typów przechwytywania, typów skrzyżowań i typów anonimowych. Od wersji Java 11 można go również stosować do parametrów lambda.
Zasadniczo możesz używać klasy Object dla dowolnego typu, ale później możesz rzutować!
na przykład:-
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);
var
słowo jest teraz oficjalnie w języku, twoja odpowiedź odnosi się również do starego stylu.
Ta funkcja jest teraz dostępna w Javie SE 10. Statyczny, bezpieczny dla typu var w końcu znalazł się w świecie Java :)
źródło: https://www.oracle.com/corporate/pressrelease/Java-10-032018.html
val
(lubvar
) jeśli używasz określonego języka „zastępowania Java” ;-)