Одним из применений ключевого слова var в C # является неявное объявление типа. Каков эквивалентный синтаксис Java для var ?
Одним из применений ключевого слова var в C # является неявное объявление типа. Каков эквивалентный синтаксис Java для var ?
Ответы:
Здесь ничего нет. Увы, вы должны ввести полное имя типа.
Редактировать: 7 лет после публикации, вывод типа для локальных переменных (с var
) был добавлен в Java 10.
Изменить: через 6 лет после публикации, чтобы собрать некоторые комментарии ниже:
Причина, по которой C # имеет var
ключевое слово, заключается в том, что в .NET могут быть типы, которые не имеют имени. Например:
var myData = new { a = 1, b = "2" };
В этом случае было бы невозможно дать правильный тип myData
. 6 лет назад это было невозможно в Java (у всех типов были имена, даже если они были чрезвычайно многословны и непривычны). Я не знаю, изменилось ли это в то же время.
var
это не то же самое, что dynamic
. var
Таблицы все еще на 100% статически типизированы. Это не скомпилирует:
var myString = "foo";
myString = 3;
var
также полезно, когда тип очевиден из контекста. Например:
var currentUser = User.GetCurrent();
Я могу сказать, что в любом коде, за который я отвечаю, currentUser
есть User
класс или производный класс. Очевидно, что если ваша реализация User.GetCurrent
вернула int, то, возможно, это нанесет вам ущерб.
Это не имеет ничего общего 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
Как указано, на виртуальные методы это не влияет.
Нет, нет неуклюжего способа инициализации a 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;
var p = new X(); p.Z()
это не то же самое , как SuperX p = new X(); p.Z()
для всех X и и SuperX, несмотря на то X : SuperX
. С var
в статическом типе из p
всегда X
в первом примере выше, но всегда SuperX
во втором примере. Тонкое, но важное отличие, о котором нужно знать. Но ваш ответ очень правильный :-)
var
не делает код менее понятным. Скорее наоборот на мой взгляд. Зачем, например, писать тип два (или даже три) раза в одной строке, когда вы объявляете и создаете его экземпляр ( RadioButton radioButton = new RadioButton();
)? var
заставляет вас думать дважды, когда вы называете свои переменные, потому что это переключает внимание на функциональность, а не на тип (например UserCollection collection = new userRepository.GetUsers();
, более естественным образом превращается в var users = userRepository.GetUsers();
). Если вы думаете, что var
неясно, это просто потому, что не используется для этого.
var
определенно может сделать понятным код, используемый хорошо, но может также сделать его неясным слишком используемым; как много вариантов форматирования. Баланс зависит от того, насколько вы используете анонимные объекты и дженерики, ни один из которых не существовал в .NET 1.0, что делает его менее полезным в качестве гипотетического ключевого слова в первой версии C♯. Я бы назвал a только RadioButton
radioButton
в случае фабричного или вспомогательного метода, где единственное, что значило в кнопке, было то, что она была RadioButton
, иначе это безумие с или без var
.
var
как и вы, если не больше, но я изменил свое мнение, и, возможно, это так же просто, как вопрос разных мнений, потому что я все еще думаю, что вы не правы, когда вы говорите, что это не имеет значения, сколько вы используете анонимных объектов и обобщений;) Объявление типа чаще всего является просто шумом кода, если вы не можете понять код без него, код, вероятно, неясен в любом случае.
var
сам по себе просто просит компилятор вывести тип из присваивания; это синтаксический сахар. Сначала я скептически относился к этому, но я использую это религиозно и еще не сталкивался со временем, когда это вызывало путаницу. Это устраняет избыточность при создании экземпляра и устраняет необходимость проверки типа при обращении к нему. В JAVA 9 нет эквивалента JAVA.
Если вы добавите Lombok в свой проект, вы можете использовать его ключевое слово val .
final
которые не обязательно неизменна. Рассмотримfinal StringBuilder strB = new StringBuilder("My reference is final"); strB.append("I'm not immutable");
var
. projectlombok.org/features/experimental/var.html
JEP - Предложение по улучшению JDK
http://openjdk.java.net/jeps/286
JEP 286: Вывод типа локальной переменной
Автор Брайан Гетц
// Goals:
var list = new ArrayList<String>(); // infers ArrayList<String>
var stream = list.stream(); // infers Stream<String>
Я подготовил плагин для IntelliJ, который - в некотором роде - дает вам var
в Java. Это хак, поэтому применяются обычные заявления об отказе от ответственности, но если вы используете IntelliJ для разработки на Java и хотите попробовать его, он находится по адресу https://bitbucket.org/balpha/varsity .
С выпуском JDK 10 20 марта Java теперь включает var
зарезервированное имя типа (не ключевое слово - см. Ниже), как указано в JEP 286 . Для локальных переменных в Java 10 или новее действует следующее:
var map = new HashMap<String, Integer>();
var
Имя зарезервированным типа в Java практически идентичен var
ключевому слову в C # в том , что оба позволяют неявного ввода (см ниже важных различий). var
в Java может использоваться только для неявного вывода типов в следующих контекстах (как перечислено в JEP 286: Цели ):
Поэтому var
нельзя использовать для полей, возвращаемых типов, имен классов или имен интерфейсов. Его обоснование заключается в том, чтобы устранить необходимость включения длинных имен типов при объявлении и определении локальных переменных, как указано в JEP 286 (автор Брайан Гетц):
Мы стремимся улучшить опыт разработчиков, уменьшая церемонию, связанную с написанием кода Java, и в то же время поддерживая приверженность Java безопасности статических типов, позволяя разработчикам исключать часто ненужное объявление манифеста типов локальных переменных.
var
Обзор в JavaСледует отметить, что var
это не ключевое слово в Java, а зарезервированное имя типа. Как указано в JEP 286:
Идентификатор var не является ключевым словом; вместо этого это зарезервированное имя типа. Это означает, что на код, который использует var как переменную, метод или имя пакета, это не повлияет; Это повлияет на код, использующий var в качестве имени класса или интерфейса (но на практике эти имена встречаются редко, поскольку они нарушают обычные соглашения об именах).
Обратите внимание, что поскольку var
это зарезервированное имя типа, а не ключевое слово, оно все равно может использоваться для имен пакетов, имен методов и имен переменных (вместе с его новой ролью вмешательства типа). Например, ниже приведены примеры правильного использования var
Java:
var i = 0;
var var = 1;
for (var i = 0; i < 10; i++) { /* ... */ }
public int var() { return 0; }
package var;
Как указано в JEP 286:
Эта обработка будет ограничена локальными переменными с инициализаторами, индексами в расширенном цикле for и локальными переменными, объявленными в традиционном цикле for; он не будет доступен для формальных форм, конструкторов, типов возвращаемых методов, полей, формальных форм перехвата или любого другого типа объявления переменных.
var
в Java & CЭто одно заметное различие между var
C # и Java var
заключается в следующем: может использоваться как имя типа в C #, но не может использоваться как имя класса или имя интерфейса в Java. Согласно документации C # (неявно типизированные локальные переменные) :
Если названный тип
var
находится в области видимости,var
ключевое слово будет преобразовано в имя этого типа и не будет рассматриваться как часть неявно типизированного объявления локальной переменной.
Возможность использовать var
в качестве имени типа в C # создает некоторую сложность и вводит некоторые сложные правила разрешения, которых var
в Java избегают , запрещая var
использовать имя класса или интерфейса. Для получения информации о сложностях var
имен типов в C # см. Ограничения, применяемые к объявлениям переменных с неявным типом . Для получения дополнительной информации об обосновании решения о определении объема для `var в Java, см. JEP 286: Выбор области действия .
var
для полей или возвращаемых типов? Почему важно отметить?
var
в Java нельзя использовать для полей или возвращаемых типов. Это важно, потому что это ограничение делает var
контекстно-зависимым, где оно может использоваться только в одних контекстах (локальные переменные), но не в других. Это не обязательно является разницей между Java и C #, что следует отметить, но является важным ограничением в целом при использовании var
в Java.
var
имя класса и использовать его как таковой. Технически это «ключевое слово context» в случае c #, но в Java кажется, что вы не можете сделать то же самое. Поправьте меня если я ошибаюсь.
var
в качестве имени класса или имени интерфейса в Java (что в любом случае не является распространенным), но вы можете использовать его для имен переменных, имен методов и имен пакетов. Например, 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
. Я обновил ответ выше, чтобы более подробно рассказать об обосновании var
Java и его различиях с var
C #.
Он будет поддерживаться в JDK 10. Его даже можно увидеть в действии в ранней сборке доступа .
СЭП 286 :
Расширение языка Java для расширения вывода типов для объявлений локальных переменных с инициализаторами.
Так что теперь вместо того, чтобы писать:
List<> list = new ArrayList<String>();
Stream<> stream = myStream();
Ты пишешь:
var list = new ArrayList<String>();
var stream = myStream();
Ноты:
var
теперь зарезервированное имя типаЕсли вы хотите попробовать его без установки Java в вашей локальной системе, я создал образ Docker с установленным на нем 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
), не эквивалентен. В var
примере list
это тип ArrayList
, а не List
.
Простое решение (при условии, что вы используете приличную IDE) - просто набрать int везде, а затем заставить его установить тип для вас.
На самом деле я просто добавил класс с именем 'var', поэтому мне не нужно вводить что-то другое.
Код все еще слишком многословен, но, по крайней мере, вам не нужно его печатать!
int
) - я что-то упустил? (*: хотя я бы никогда не назвал Eclipse достойной IDE, я не могу судить за других ...)
Java 10 действительно делала вывод типа локальной переменной, так что теперь она var
в значительной степени эквивалентна C # one (насколько я знаю).
Он также может выводить не денодугируемые типы (типы, которые не могут быть названы в этом месте программистом; хотя, какие типы не денотируемые, отличается). См., Например, Трюки с var
анонимными классами (которые вы никогда не должны использовать на работе) .
Единственное отличие, которое я смог найти, это то, что в C #
В Java 10 var
нет допустимого имени типа.
По состоянию на Java 10, эквивалент ... var
.
Я знаю, что это старше, но почему бы не создать класс var и создать конструкторы с различными типами, и в зависимости от того, какие конструкторы вызываются, вы получаете var с другим типом. Вы даже можете встроить методы для преобразования одного типа в другой.
Lombok
поддерживает var, но все еще классифицируется как экспериментальный:
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: Вывод типа локальной переменной ), это может быть вашим лучшим выбором прямо сейчас.
Обратите внимание, что val
поддерживается Lombok
также без изменения или создания lombok.config
.
Вы можете, в Java 10, но только для локальных переменных, то есть
Ты можешь,
var anum = 10; var aString = "Var";
Но не могу,
var anull = null; // Since the type can't be inferred in this case
Проверьте спецификации для получения дополнительной информации.
var
может использоваться для многих форм неотмечаемых типов, включая типы захвата, типы пересечений и анонимные типы классов. И, начиная с Java 11, его также можно применять к лямбда-параметрам.
В общем, вы можете использовать класс 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);
var
слово официально на языке, ваш ответ также относится к старомодному способу.
Эта функция теперь доступна в Java SE 10. Статическая, типобезопасная переменная наконец-то вошла в мир Java :)
источник: https://www.oracle.com/corporate/pressrelease/Java-10-032018.html
val
(илиvar
) если вы используете конкретный язык «замены Java» ;-)