Java - Язык:В чем разница между автоматической упаковкой и кастингом?
-
20-08-2019 - |
Вопрос
Этот вопрос речь идет о том, "Почему автобоксинг делает некоторые вызовы неоднозначными в Java?"
Но, читая ответы, я вижу ряд ссылок на кастинг, и я не уверен, что полностью понимаю разницу.
Кто-нибудь может дать простое объяснение?
Решение
Боксирование - это когда вы преобразуете примитивный тип в ссылочный, отмена боксирования - это обратное.Приведение - это когда вы хотите, чтобы один тип обрабатывался как другой тип, между примитивными типами и ссылочными типами это означает неявную или явную операцию упаковки.Должно ли это быть явным, зависит от языковой особенности.
Другие советы
И приведение, и упаковка / распаковка имеют отношение к типам и кажущемуся (или реальному) преобразованию, но упаковка / распаковка специфичны для взаимосвязи между примитивными типами и их соответствующими типами-оболочками, в то время как приведение - это термин для явного или неявного изменения типа в более общем смысле.
Кастинг это общий термин с двумя связанными, но разными значениями:
Обработка значения одного типа как будто это было значение другого типа.Двумя примерами этого первого использования являются:
1.1.Учитывая этот класс
B
расширяет классA
, вы можете попроситьmyB
пример того , чтоB
рассматриваться как экземплярA
написав((A) myB)
везде, где есть ссылка на экземплярA
может появиться.На самом деле это не приводит к созданию нового экземпляраA
.1.2.Коллекции, созданные до Java5, хранили весь контент как
Object
;обычно для этого требовалось использовать приведение после извлечения объекта из коллекции.Например, если бы вы сохранилиString
вMap
и нужно было получить его длину, вы бы написали что-то вроде((String) myMap.get(someKey)).length()
где приведение потребовалось бы для того, чтобы вызватьlength
способString
.Опять же, это не вызывает новогоString
быть созданным.Явно преобразование от одного типа к другому (т.е.явное изменение представления).Пример этого второго использования содержится в выражении
((int) (float_var + 0.5F))
который округляет переменную с плавающей запятой путем добавления 0,5 (что дает значение с плавающей запятой), а затем явно преобразует это значение в целое число.Результирующее целочисленное значение (после(int)
актерский состав) является произведенный из другого значения путем внутреннего вычисления.
Приведение может быть выполнено при наличии отношения суперкласс / подкласс или интерфейс / разработчик (значение 1 выше) или когда эти два типа являются примитивными числовыми типами (значение 2).Вы можете посмотреть "расширение" и "сужение" для получения более подробной информации.
Бокс относится к переносу примитивных типов в объекты-контейнеры, обычно выполняется только тогда, когда у вас должен быть объект (напримерхранение значения в коллекции).Типы primitive и wrapper представлены парами:
int Integer
long Long
boolean Boolean
... ...
Распаковка коробки просто означает извлечение примитивного значения из его объектной оболочки.
Начиная с Java5, когда вы пишете выражение, которое использует примитивное значение, где требуется соответствующий тип оболочки (например, помещение целого числа в коллекцию), компилятор автоматически вставляет код, который фактически оборачивает это примитивное значение.Аналогично, он предоставит вам код для разворачивания.
Таким образом, вместо того, чтобы писать (на языке до Java5) что-то вроде:
Map myMap = new HashMap();
...
myMap.put(someKey,Integer.valueOf(3));
...
int nextValue = (myMap.get(someKey)).intValue() + 1;
вы можете написать:
Map<KeyType,Integer> myMap = new HashMap<KeyType,Integer>();
...
myMap.put(someKey,3);
...
int nextValue = myMap.get(someKey) + 1;
и код упаковки / распаковки вставляется компилятором.
List<String> list = (List<String>)object;
это актерский состав.
void doSomething(Integer i) { ... }
...
doSomeething(5);
это автоматический бокс.
Integer getSomething();
...
int i = getSomething();
происходит автоматическая распаковка коробки.
Автобоксинг был введен в Java 5 для предотвращения такого кода, как :
map.put("ABC", new Integer(5));
map.put("DEF", new Integer(6));
Теперь вы можете сказать :
map.put("ABC", 5);
Хотя это проще - у этого есть несколько подводных камней, если вы не полностью уверены в том, что делаете.
Упаковка - это перенос значения внутрь контейнера, такого как примитивное значение int внутри целочисленного объекта
Кастинг - это просто способ взглянуть на типаж.
Первый создает другой вид значения, второй просто изменяет способ обработки уже существующего значения
За исключением того, что приведение между примитивными типами фактически изменяет их представление.(Это не проясняет ситуацию, не так ли?)
Упаковка и распаковка - это тип приведения в Java, при котором вы приводите примитив к его классу-оболочке или обратному, напримерлогическое значение в логическое значение (box) или Логическое значение в логическое значение (unbox).
Типы приведений в Java, с примером:
преобразование идентификатора (§5.1.1) Строка в строку
расширяющееся примитивное преобразование (§5.1.2) байт в int
упрощенное преобразование с сужением (§5.1.3) int в байт
расширяющееся преобразование ссылки (§5.1.5) Целое число в число
преобразование сужающейся ссылки (§5.1.6) Число в целое
преобразование пакета (§5.1.7) из int в Integer
преобразование при распаковке (§5.1.8).Целое число в int
Автоматическая упаковка или autounboxing происходит, когда компилятор выполняет преобразование упаковки / распаковки для вас (это явно не отображается в исходном коде как приведенное выражение), напримерсмотрите вопрос, на который вы ссылались.
Может ли автоупаковка и распаковка быть применена в следующем случае ?
Long one = 10;
long two = 15;
Long three = 20;
if(one == three) //will this be unboxed or do we need to put a explicit
//condition like if(one.intValue() == three.intValue())
System.out.println("Equal");
else
System.out.println("Not Equal");
if(one == two) //will this be unboxed or do we need to put a explicit
//condition like if(one.intValue() == two)
System.out.println("Equal");
else
System.out.println("Not Equal");