Числовые классы-обёртки в Java - PullRequest
6 голосов
/ 09 января 2010

Я пришла из мира PHP, и я так озадачена тем, как думать, когда объявляешь объекты в Java.

поэтому, когда вы традиционно делаете это так:

 Rectangle rect = new Rectangle();

причина - тип данных Rectangle.

Согласно странице учебника по Java класс обертки чисел является подклассом для Number. Так что это класс, но когда вы создаете его экземпляр, учебник делает это так:

 Integer x;
 x = 12;

Почему это не похоже на традиционный способ:

 Integer x = new Integer(12);
 or
 Integer x = new Integer();

А вот еще один пример:

 String s = new Integer(i).toString();

Так вот, s это объект String. что я получаю. Но вы получили новое целое число (я). Почему новый? Что это значит здесь и что происходит, когда он посылает «i» в конструктор. Где я могу увидеть, что делает конструктор с параметрами в Java API?

Много вопросов, но не могу найти в сети источники, объясняющие это.

Ответы [ 5 ]

10 голосов
/ 09 января 2010

Во-первых, вы можете просто использовать примитивные типы:

int x = 12;
double d = 3.3456;

Во-вторых, вы можете по желанию использовать обертки объектов для этих чисел:

Integer x = new Integer(12);
Double d = new Double(3.3456);

В-третьих, если вам нужно строковое представление, вы можете сделать это просто с помощью:

String s = Integer.toString(12);

или просто:

int x;
String s = "x = " + x;

или даже printf() как синтаксис:

int x = 12;
String s = String.format("x = %d", x);

Наконец, Java начиная с версии 5 поддерживает автоматическую коробку и распаковку, что может сбить вас с толку, если вы этого не ожидаете. Например:

Integer i = 1234; // autoboxes int to Integer

и

int i = new Integer(1234); // autounboxes Integer to an int

Просто используйте примитивные типы, если вам не нужны Number оболочки. Наиболее распространенная причина их использования - поместить их в коллекции (List s и т. Д.).

7 голосов
/ 09 января 2010

То, на что вы смотрите в первом примере, называется autoboxing / autounboxing. Java (начиная с версии 5) автоматически преобразует между 5 и Integer.valueOf(5), что создает оболочку типа Integer из примитива int. Но последнее (Integer x = new Integer(12)) абсолютно правильно.

Однако во втором случае это не работает, если вы хотите написать что-то вроде 5.toString(). Автобокс происходит только при назначении примитива типу оболочки или при передаче примитива там, где ожидается тип оболочки, и т. Д. Примитивы не являются объектами и поэтому не имеют свойств, на которые следует ссылаться.

Re: «почему новое», это потому, что все ссылочные (не примитивные) типы в Java размещаются динамически в куче. Таким образом (кроме автобоксов), единственный способ получить Integer (или другой ссылочный тип) - это явно выделить место для одного.

2 голосов
/ 09 января 2010

Некоторые вещи, на которые другие ответы не обращались:

Integer x = new Integer();

Это не будет работать, потому что класс Integer не имеет конструктора без аргументов (каким будет значение int получившегося объекта?).

String s = new Integer(i).toString();

Так вот, s это объект String. что я получить. Но вы получили новое целое число (я). Зачем новый? Что это значит здесь и что происходит, когда он отправляет «я» на конструктор. Где я могу увидеть, что конструктор делает с параметры в API Java?

Это означает то же, что и выше: объект Integer создается, передается содержимое переменной i (возможно, индекс цикла) в качестве аргумента конструктора, а затем вызывается метод toString() результирующего объекта, который возвращает строковое представление числа.

Что касается того, где вы можете искать такие вещи, документ Java API doc подробно описывает все аспекты стандартного API. Если этого недостаточно, JDK от Sun поставляется с полным исходным кодом стандартного API. Когда вы устанавливаете JDK, у вас есть возможность получить этот исходный код, и большинство IDE позволяют легко перейти к нему.

1 голос
/ 09 января 2010

Это странное поведение:

Integer x;
x = 12;

Это из-за java autoboxing .

Немного истории:

До Java 1.5 это было запрещено. У вас были примитивы (int, char, byte, boolean, float, double,long), а остальные в мире Java были классами (включая соответствующие оболочки: Integer, Character, Byte, Booelan, Float, Double, Long).

Основные структуры данных Java работали с объектами, поэтому, если вам нужно было сохранить числа в списке, вам нужно было «обернуть» свое значение (обертки - это просто обычные классы, которые содержат примитивный тип)

Например, это может быть моя собственная int оболочка:

 public class Entero { // integer in spanish... :P 
     private final int wrappedInt;

     public Entero( int i ) {
         this.wrappedInt = i;
     }

     public int getEntero() {
         return wrappedInt;
     }
 }

Ничего особенного, это в общих чертах, как реализованы классы "обертки" (конечно, там много служебных методов)

Итак, опять же, если вы хотите использовать его в списке (который содержит только объекты), вам придется:

 List list = // get the list from somewhere.... 
 list.add( new Integer( 1024 ) ); // wrap it
 .... 
 // use the list and at some point iterate it:
 Iterator iterator = list.iterator();
 while( iterator.hasNext() ) {
     Integer e = ( Integer ) iterator.next(); // unwrap it
     i = e.intValue();
 }

Звонок

 list.add( 1024 )

Непосредственно было невозможно, потому что 1024 - это литерал int, а не объект.

Тонны кода были написаны так, по годам.

Поскольку в Java 1.5 добавлено автобоксирование, которое в основном является синтаксическим сахаром, теперь компилятор внедряет "новый Integer (i) / integer.intValue ()", и код становится следующим:

list.add( 1024 ); // wrapped in the compiled code in the the .class file that is.
....
Iterator i = list.iterator();
while( i.hasNext() ) {
    int i = ( Integer ) i.next(); // unwrapped for you by the compiler under the hood
}

Удаление процесса переноса из исходного кода.

Кроме того, с помощью дженериков вы также сохранили кастинг:

 List<Integer> list = .... // <- you still have to say the list is of "Integers" not "int"

 .... 
 Iterator<Integer> i = list.iterator(); // The iterator has to use the "<Integer>"  generic mark
 while( i.hasNext() ){
     int x = i.next(); // but you can get the value directly. 
 }

По сути, дженерики - это знак того, что «проверьте, что используется, такого типа, и больше не отвлекайте меня от приведения», но дженерики - это еще одна тема.

1 голос
/ 09 января 2010

В дополнение к объектам Java также включает примитивные типы данных, такие как логические, байтовые, целые, длинные, char, float, double. Все они упоминаются в нижнем регистре и используются с литеральными значениями. Они всегда передаются по значению.

Существуют также соответствующие объекты Number: Boolean, Byte, Integer, Long и т. Д., Которые, как и все объекты, вместо этого передаются по ссылке. Поскольку это скорее объекты, чем примитивы, следует учитывать различные характеристики и характеристики производительности.

Современная Java имеет автоматическую упаковку и автоматическую распаковку для автоматического преобразования между примитивами и объектами, которые позволяют использовать синтаксис в том виде, в котором вы его использовали Integer i = 5 для автоматической вставки примитива 5 в объект Integer. Ранее вам пришлось бы использовать примитив int i = 5 или явный синтаксис, основанный на объектах Integer i = new Integer(5), а не смешивать типы, как вы можете сейчас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...