2010-09-27 4 views
5

Я на самом деле путаюсь по обоим темам, может ли кто-нибудь объяснить мне.autoboxing и generics

ArrayList<Long> queryParms = new ArrayList<Long>(); 
  1. СОБРАННОЙ одна называется генерики или Autoboxing и что распаковка?
  2. Это лучшая практика?
  3. Некоторые говорят, что Autoboxing - это зло.
  4. Если я использую дженерики, могу ли я избежать автобоксинга и распаковки?

ответ

8
  1. Вышеприведенный пример дженериков. Автоматическое боксирование - это автоматическое преобразование компилятором примитивного типа в тип обертки и наоборот. В вашем случае, например, из long переменной в Long переменной:

    long param = 13L; 
    queryParms.add(param); 
    
  2. Использование дженериков? Да. Он позволяет указать, что будет содержать ваш список. Вы должны использовать их. Использование автоматического бокса? Да, это упрощает код, и вам не нужно беспокоиться о конверсиях между примитивными типами переменных в оболочку (и наоборот).

  3. Авто-бокс не злой (ИМХО). Это некоторые угловые случаи, когда авто-бокс может быть очень раздражающим, но если вы знаете, как это работает, вам не стоит беспокоиться об этом. Вот the Sun (now Oracle) paper on auto-boxing, если вам нужно больше узнать об этом.

  4. Если вы хотите создать список, содержащий обертки (в вашем случае, Long), вам придется иметь дело с преобразованием типов. Вы можете использовать явное преобразование типов или использовать авто-бокс.

+4

Непреднамеренный авто (un) бокс может быть высокопрофессиональным бором, если он выполняется в цикле, выполняемом много раз. Это может быть причиной того, что некоторые люди считают это злым. Тем не менее, настоящая проблема здесь - небрежное кодирование (и отсутствие профилирования), а не сама языковая функция. –

+1

Если я использую дженерики, могу ли я избежать автобоксинга и распаковки? – John

+0

@John Вы можете избежать ненужных автобоксинга и распаковки, тщательно изучив, использовать ли примитивный или обертковый тип и проверять, вызывает ли какой-либо вызов метод бокса. Однако, поскольку вам необходимо использовать тип обертки с дженериками, обычно нет способа избежать этого. – Carlos

2

Автообновление - это когда примитив автоматически преобразуется в объект. Например:

Long autoboxedLong = 3; 

Примечания верхнего корпуса л, что делает autoboxedLong объект вместо примитива.

обратного автоматическая распаковки, который позволяет писать:

long autounboxedLong = autoboxedLong; 

т.е. вы автоматически для преобразования объекта в примитив. Однако это опасно, потому что autoboxedLong может быть null. Тогда этот код будет генерировать исключение NullPointerException.

Ваш пример не об автобоксинге, но при вставке объектов в ваш список вводится автобоксинг. Вы можете:

queryParams.add(1); 

и автобоксинг автоматически связывают ваш примитивный длинный 1 с длинным объектом.

1

Нет Вышеприведенный не называется autoboxing.When вы

queryParms.add(22l);//here primitive type 22 is converted to wrapper class Long type.This  
        //is called autoboxing. 
1

вас пример создает ArrayList с родовым типом Long. Таким образом, список будет содержать объекты типа long. Outoboxing делает примитивы из объектов и наоборот.Таким образом, вы можете использовать свой список, как:

long x = queryParms.get(0); 

или

queryParams.add(4L); 
0

В Java 5.0, классы-оболочки стали проще в использовании. Java 5.0 представила автоматическое преобразование между примитивным типом и соответствующим классом-оболочкой.

От примитивного типа к нему класс оболочки корректов называется autoboxing, обратный процесс называется распаковкой. Автосообщение и распаковка также применяются к вызовам методов. Например, вы можете передать аргумент типа int методу, который имеет формальный параметр типа Integer.

  • Исключено исключение NullpointerException При освобождении ссылки на нулевой класс-оболочку на свой примитивный тип. Например, код будет скомпилирован, но во время выполнения он выкинет исключение NullpointerException.

    Long L = null; long l = L; ... 
    
  • Конверсия бокса преобразует значения примитивного типа в соответствующие значения ссылочного типа. Но примитивные типы не могут быть расширены/сужены к классам Wrapper и наоборот. Например,

    байт b = 43; Целое число I1 = 23; // Постоянное целочисленное значение Целое число I2 = (int) b; // Присвоение типа int Long L1 = 23; // компилируем ошибку, потому что 23 - целое значение Long L2 = (Long) 23; // не может отличать целочисленное значение от длинного класса оболочки Long L3 = 23L; Длинный L4 = (длинный) 23;

Это ограничение также применяется к вызову методы:

public class MyClass 
{ 
    public void method(Long i) 
    { 
     System.out.println("Here"); 

    } 
    public static void main(String[] args) 
    { 
     MyClass s = new MyClasslass(); 
     //s.method(12); 
     // error  s.method(12L); 
     // ok 
    } 

} 
•When invoking a method from multiple overloading methods, For the matching method process, the Java compiler will perferance the order of primitive types (Widening Primitive Conversion), wrapper class (Boxing Conversion), and var-args. For example, 
public class MyClass 
{ 
    public void method(Long x, Long y) 
    { 
     System.out.println("method(Long x, Long y)"); 

    } 
    public void method(long x, long y) 
    { 
     System.out.println("method(long x, long y)"); 

    } 
    public void method(long... x) 
    { 
     System.out.println("method(long... x)"); 

    } 
    public static void main(String[] args) 
    { 
     long x, y; 
     x = y = 0; 
     MyClass s = new MyClass(); 
     s.method(x, y); 

    } 

} 

В результате method(long x, long y). Компилятор Java будет проверять соответствующие примитивные типы, затем он будет искать типы Wrapper.

public class MyClass 
{ 
    public void method(Long x, Long y) 
    { 
     System.out.println("method(Long x, Long y)"); 

    } 
    public void method(int x, int y) 
    { 
     System.out.println("method(int x, int y)"); 

    } 
    public void method(long... x) 
    { 
     System.out.println("method(long... x)"); 

    } 
    public static void main(String[] args) 
    { 
     long x, y; 
     x = y = 0; 
     MyClass s = new MyClass(); 
     s.method(x, y); 

    } 

} 

Результат method(Long x, Long y). Компилятор Java дает предпочтение соответствующей сигнатуре метода класса Wrapper, отличной от примитивного метода varargs.

public class MyClass 
{ 
    public void method(Double x, Double y) 
    { 
     System.out.println("method(Double x, (Double y)"); 

    } 
    public void method(int x, int y) 
    { 
     System.out.println("method(int x, int y)"); 

    } 
    public void method(long... x) 
    { 
     System.out.println("method(long... x)"); 

    } 
    public static void main(String[] args) 
    { 
     long x, y; 
     x = y = 0; 
     MyClass s = new MyClass(); 
     s.method(x, y); 

    } 

} 

Результат method(long ...x). Компилятор не будет сузить «длинное» примитивное значение до «int»; Кроме того, он не может долго затягивать Double Class. Можно использовать только метод var-args.

public class MyClass 
{ 
    public void method(Long x, Long y) 
    { 
     System.out.println("method(Long x, Long y)"); 

    } 
    public static void main(String[] args) 
    { 
     int x, y; 
     x = y = 0; 
     MyClass s = new MyClass(); 
     s.method(x, y); 

    } 

} 

Аргументы не могут быть «длинными», а затем «Long». Вы получите ошибку компиляции.

  • Чтобы сохранить память, два экземпляра следующих объектов-оболочек всегда будут ==, когда их примитивные значения одинаковы. Пожалуйста, прочитайте, почему преобразование autoboxing иногда возвращает одну и ту же ссылку?
+0

Пожалуйста, отформатируйте это. Посмотрите страницу форматирования wiki: http://stackoverflow.com/editing-help – mtk

Смежные вопросы