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 varw 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 varsł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.
varto nie to samo co dynamic. variables są nadal w 100% typowane statycznie. To nie będzie kompilować:
var myString = "foo";
myString = 3;varjest 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, currentUserma Userklasę pochodną. Oczywiście, jeśli twoja implementacja User.GetCurrentzwraca 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 varzmiennej 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 vartej statycznej typu od pzawsze jest Xw pierwszym przykładzie powyżej, ale zawsze SuperXw drugim przykładzie. Subtelna, ale ważna różnica, o której należy pamiętać. Ale twoja odpowiedź jest bardzo poprawna :-)
varnie 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();)? varsprawia, ż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 varjest niejasne, to tylko dlatego, że nie jest do tego przyzwyczajony.
varcałą 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 radioButtonw 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.
varjak 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.
varsam 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 .
finalnie 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 varJavę. 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 varnazwę 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 vartypu zarezerwowanego w Javie jest prawie identyczna ze varsłowem kluczowym w języku C #, ponieważ oba pozwalają na niejawne pisanie (ważne różnice poniżej). varw 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 varnie 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ż varjest 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 varw 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.
varw Javie i C.Jest to jedna zauważalna różnica między językami varC # i Java: varmogą 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
varjest objęty zakresem,varsłowo kluczowe rozpozna nazwę tego typu i nie będzie traktowane jako część niejawnie wpisanej deklaracji zmiennej lokalnej.
Możliwość użycia varjako nazwy typu w języku C # powoduje pewną złożoność i wprowadza pewne skomplikowane reguły rozwiązywania, których można uniknąć varw Javie, uniemożliwiając używanie nazwy varklasy lub interfejsu. Aby uzyskać informacje na temat złożoności varnazw 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 .
vardo pól lub typów zwracanych? Dlaczego warto to zauważyć?
varw Javie nie można używać dla pól ani typów zwracanych. Jest to ważne, ponieważ to ograniczenie varuwarunkowane 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 varz Java.
varnazwę 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ę.
varjako 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 varw Javie i jej różnic varw 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:
varjest 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 varprzykładzie listjest 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 varprawie 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 vari 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 varnie 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.
Lombokobsł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 valjest to również wsparcie Lombokbez 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.
varmoż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);
varsł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” ;-)