Почему вы называете этот класс дважды во время создания экземпляра на Java?
Когда вы создаете экземпляр объекта, почему вы указываете класс дважды?
OddEven number = new OddEven();
Почему вы не можете просто сказать number = new OddEven();
? Когда я объявляю строку, я говорю только String
один раз:
String str = "abc";
На самом деле, мой вопрос не "почему вы так делаете" - очевидно, вы это делаете, потому что вам нужно - но почему же создатели решили сделать синтаксис Java таким?
Мои мысли:
- Есть что-то фундаментальное для того, как Java работает на низком уровне, что требует ввода имени дважды, или
- Создатели свободно выбирают это так, чтобы сохранить какой-то аспект синтаксического единообразия - сначала объявите тип? Или это было больше похоже на его предшественников?
Ответы
Ответ 1
Потому что вы можете это сделать:
Superclass x = new Subclass();
Тип ссылки может быть суперклассом фактического объявляемого объекта, поэтому вам нужно указать и то, и другое. Например, вы можете:
List<String> stringList = new ArrayList<String>();
Ваша программа взаимодействует с объектами, которые реализуют List, и вам не нужна реализация.
Ответ 2
Причиной, по-видимому, избыточного имени типа является то, что вы выполняете две отдельные операции, каждая из которых требует указания типа.
С левой стороны вы объявляете переменную (место хранения) с определенным типом. С правой стороны вы создаете новый объект с определенным типом. "=" В середине вызывает ссылку на новый объект, который вы создали, для размещения в созданном хранилище.
Типы с каждой стороны не обязательно должны быть одинаковыми. Это, например, юридический код:
Object number = new OddEven();
Причина того, что ключевое слово String появляется только один раз во втором примере, означает, что тип String подразумевается справа, так как "xxx" является константой String. Это просто сокращение:
String string = new String("xxx");
Ответ 3
Когда вы пишете:
OddEven number = new OddEven();
Фактически вы делаете две вещи: 1) вы объявляете переменную number
типа OddEven
и 2) вы назначаете ссылку на новый экземпляр класса OddEven
. Но поскольку переменная может содержать любой подтип типа, запись number = new OddEven();
будет недостаточной для того, чтобы компилятор знал реальный тип переменной number
. Таким образом, вы должны заявить об этом. Java - это строго типизированный язык, что означает, что каждая переменная и каждое выражение имеют тип, который известен во время компиляции. Вы можете прочитать все Глава 4. Типы, значения и переменные Спецификации языка Java (JLS), чтобы узнать об этом подробнее.
Теперь, когда вы пишете:
String str = "abc";
Все немного отличается. Символы, заключенные в двойные кавычки, "abc"
здесь, называются строковым литералом, который уже является ссылкой на экземпляр String
и всегда ссылается на тот же экземпляр класса String
. Цитирование раздела 3.10.5 Строковые литералы JLS:
Каждый строковый литерал является ссылкой (§4.3) в экземпляр (§4.3.1, §12.5) of класс String
(§4.3.3). String
объекты имеют постоянное значение. строка литералы - или, в более общем смысле, строки которые являются значениями постоянной выражения (§15.28) -are "интернированный", чтобы экземпляры, используя метод String.intern
.
Итак, String str = "abc";
, безусловно, не преобразован в String str = new String("abc");
, что абсолютно не эквивалентно, как я читал в некоторых комментариях и ответах. Выполнение следующего класса:
public class Test {
public static void main(String[] args) {
String one = "abc";
String two = "abc";
String abc = new String("abc");
System.out.println(one == two);
System.out.println(one == abc);
}
}
Производит вывод ниже:
true
false
И демонстрирует, что one
и two
являются ссылками на один и тот же экземпляр, но abc
является ссылкой на другой экземпляр (т.е. создается лишний ненужный объект).
На самом деле использование new String(String)
- это неэффективный способ построения новых строк и его следует использовать только для принудительного копирования подстроки в новый базовый массив символов, как в
String tiny = new String(monster.substring(10,20))
Ответ 4
Первый OddEven
- тип, второй - экземпляр. Это не должно быть даже OddEven
, это может быть любой подкласс OddEven
. Это не значит, что у вас есть тип дважды. В любой среде IDE есть шаблоны кода, где вы должны вводить имя только один раз.
Ответ 5
Первое объявление - это тип переменной, которую вы хотите использовать в области видимости, в этом случае это OddEven, второе объявление является конструктором, используемым для экземпляра (и в этом случае инициализации) ссылки.
Вы могли бы указать INumberInstance = new OddEven(), где INumberInstance - это некоторый класс, который OddEven может быть отличен (например, супер OddEven).
Ответ 6
Способ создания нового объекта в java:
Class_name reference_variable = new Class_name(param_if_any);
Но строковый класс является исключением.
Вы можете создать новый строковый объект как
String s = "abc";
или
String s = new String("abc");
Ответ 7
В дополнение к тому, что сказал Джим, Java - это статически типизированный язык. Это означает, что каждая переменная имеет тип, который известен во время компиляции.
Например:
public class A
{
public void foo() { }
}
public class B
{
public void foo() { }
}
public class Main
{
public static void main(final String[] argv)
{
A a = new A();
B b = new B();
a.foo();
b.foo();
}
}
компилятор просматривает "a.foo()" и "b.foo()" и проверяет, имеет ли тип A тип A и A имеет метод "foo", который не принимает аргументов. Компилятор делает то же самое для "b.foo()".
Если вы могли бы написать так:
public class Main
{
public static void main(final String[] argv)
{
a = new A(); // in Java you would really do Object a = new A();
b = new B(); // in Java you would really do Object b = new B();
a.foo();
b.foo();
}
}
тогда компилятор не смог бы выполнить эту проверку, и это должно было произойти во время выполнения.
Ответ 8
Вспомните "OddEven number" как определяющий объект и "новый OddEven();" как заполнение объекта.
Я не буду подробно разбираться в суперклассах и подклассах, потому что другие люди уже объяснили это.
Ответ 9
Дизайнерам Java не пришлось делать синтаксис избыточным. Scala - это другой язык, использующий JVM, а также статически типизированный. Scala использует тип вывода, чтобы вырезать многословие. Например, здесь объявление переменной типа MyPair называется x. MyPair связывает две переменные друг с другом. Это общий класс, поэтому вы можете указать, что первая переменная имеет тип Int, а второй тип String:
var x: MyPair[Int, String] = new MyPair[Int, String](1, "scala")
Scala type inferencing позволяет удалить объявление избыточного типа:
var x = new MyPair[Int, String](1, "scala")
И Scala даже вводит типы, основанные на аргументах конструктора, поэтому вы можете записать его следующим образом:
var x = new MyPair(1, "scala")
Ответ 10
Когда вы говорите String name = "foo"
, внутренний компилятор Java создает объект String со значением "foo" и присваивает свою ссылку переменной name
. Итак, вместо создания нового объекта String мы назначаем ссылку на другой объект String.
Btw, компилятор в любом случае создает для нас "foo" . Сначала он выглядит в String Pool, если он не существует, только тогда он создает "foo" . В противном случае компилятор возвращает ссылку из пула строк. Это некоторая оптимизация, которую выполняет компилятор Java внутри.
String name = "foo"
равен t23 >
Ответ 11
Рассмотрим следующий пример:
Мы можем указать тип объекта следующим образом:
List<String> abc;
В методе 1(), если вы хотите использовать список массивов, который подходит для наилучших для него требований, мы можем создать экземпляр следующим образом:
abc = new ArrayList<String>();
В методе2(), если вы хотите использовать список Linked array, который лучше всего подходит для этого требования, мы можем создать экземпляр, как показано ниже,
abc = new LinkedList<String>();
Итак, идея состоит в том, что мы можем указать тип "SuperClass" и создать экземпляр любого подкласса, подходящего для различных требований, таких как "LinkedList" и "ArrayList" в соответствующей операции динамически.