Типы обёртки
Класс Integer
Упаковка
Упаковка
Распаковка
Распаковка
Автоматическая упаковка
Автоматическая упаковка
Автоматическая распаковка
Автоматическая распаковка
Интересный пример
Неожиданный результат
Класс Integer
Медленный цикл
Медленный цикл
Ещё один медленный цикл
Ещё один медленный цикл
Ошибка с оператором ==
Ошибка с оператором ==
741.00K
Category: programmingprogramming

Типы, переменные, управляющие инструкции. Обёртки примитивных типов. (Тема 2.4)

1.

II. Типы, переменные,
управляющие инструкции
4. Обёртки примитивных типов
1

2.

Значения примитивных типов хранятся непосредственно в переменных и над ними
можно выполнять различные операции. Но они не являются объектами. Поэтому у
них нет методов, к ним нельзя обращаться используя ссылку типа класса Object и
их нельзя хранить в коллекциях.
Классы обёртки оборачивают примитивные значения и позволяют работать с ними
как с объектами. Их можно использовать в коллекциях или как возвращаемое
значение функции которая должна возвращать Object. Кроме того классы обёртки
предоставляют набор статических функций для работы с примитивными
значениями. После создания объекта класса обёртки примитивное значение внутри
обёртки не может быть изменено.
2

3. Типы обёртки

Примитивный тип
Тип обёртка
byte
Byte
short
Short
char
Character
int
Integer
long
Long
float
Float
double
Double
boolean
Boolean
Все обёртки примитивных типов находятся в пакете
java.lang. Этот пакет импортируется по умолчанию
поэтому импортировать его не нужно.
3

4. Класс Integer

public
public final
final class
class Integer
Integer extends
extends Number
Number implements
implements Comparable<Integer>
Comparable<Integer>
{{
private
private final
final int
int value;
value;
public
public
public
public
Integer(int
Integer(int value)
value)
Integer(String
Integer(String s)
s) throws
throws NumberFormatException
NumberFormatException
public
public static
static Integer
Integer valueOf(int
valueOf(int i)
i)
public
public int
int intValue(){
intValue(){
return
return value;
value;
}}
public
public static
static String
String toString(int
toString(int i)
i) {{
if
if (i
(i ==
== Integer.MIN_VALUE)
Integer.MIN_VALUE)
return
return "-2147483648";
"-2147483648";
int
size
=
int size = (i
(i << 0)
0) ?? stringSize(-i)
stringSize(-i) ++ 11 :: stringSize(i);
stringSize(i);
char[]
buf
=
new
char[size];
char[] buf = new char[size];
getChars(i,
getChars(i, size,
size, buf);
buf);
return
return new
new String(0,
String(0, size,
size, buf);
buf);
}}
}}
static
static void
void getChars(int
getChars(int i,
i, int
int index,
index, char[]
char[] buf)
buf)
...
...
C
Класс Integer – класс обёртка для int. Оборачиваемое значение хранится в поле value
значение которого не может быть изменено. Содержит конструктор для создания
объекта класса Integer по значению int и метод для получения значения int
хранящегося внутри объекта класса Integer. Содержит статические методы для
получения строкового представления для int.
4

5.

Упаковка и распаковка
5

6.

Процесс получения ссылки на объект класса обёртки по значению примитивного
типа называется упаковкой, а процесс получения значения примитивного типа по
объекту класса обёртки называется распаковкой.
6

7. Упаковка

public
public static
static void
void main(String[]
main(String[] args)
args) {{
boolean
boolean boo
boo == false;
false;
Boolean
wboo
=
Boolean wboo = new
new Boolean(boo);
Boolean(boo);
System.out.println("boolean
System.out.println("boolean variable's
variable's value:
value: "" ++ wboo);
wboo);
byte
byte bb == 2;
2;
Byte
wbyte
Byte wbyte == new
new Byte(b);
Byte(b);
System.out.println("byte
System.out.println("byte variable's
variable's value:
value: "" ++ wbyte);
wbyte);
short
short ss == 4;
4;
Short
Short wshort
wshort == new
new Short(s);
Short(s);
System.out.println("short
System.out.println("short variable's
variable's value:
value: "" ++ wshort);
wshort);
int
int ii == 16;
16;
Integer
Integer wint
wint == new
new Integer(i);
Integer(i);
System.out.println("int
System.out.println("int variable's
variable's value:
value: "" ++ wint);
wint);
long
long ll == 123;
123;
Long
Long wlong
wlong == new
new Long(l);
Long(l);
System.out.println("long
System.out.println("long variable's
variable's value:
value: "" ++ wlong);
wlong);
float
float ff == 12.34f;
12.34f;
Float
wfloat
Float wfloat == new
new Float(f);
Float(f);
System.out.println("float
System.out.println("float variable's
variable's value:
value: "" ++ wfloat);
wfloat);
}}
double
double dd == 12.56d;
12.56d;
Double
Double wdouble
wdouble == new
new Double(d);
Double(d);
System.out.println("double
System.out.println("double variable's
variable's value:
value: "" ++ wdouble);
wdouble);
7

8. Упаковка

boolean
boolean variable's
variable's value:
value: false
false
byte
byte variable's
variable's value:
value: 22
short
short variable's
variable's value:
value: 44
int
int variable's
variable's value:
value: 16
16
long
variable's
value:
long variable's value: 123
123
float
float variable's
variable's value:
value: 12.34
12.34
double
double variable's
variable's value:
value: 12.56
12.56
8

9. Распаковка

public
public class
class UnwrapDemo
UnwrapDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
Boolean
Boolean wboo
wboo == new
new Boolean(false);
Boolean(false);
boolean
boolean boo
boo == wboo.booleanValue();
wboo.booleanValue();
System.out.println("boolean
System.out.println("boolean variable's
variable's value:
value: "" ++ boo);
boo);
Byte
Byte wbyte
wbyte == new
new Byte((byte)2);
Byte((byte)2);
byte
b
=
wbyte.byteValue();
byte b = wbyte.byteValue();
System.out.println("byte
System.out.println("byte variable's
variable's value:
value: "" ++ b);
b);
Short
Short wshort
wshort == new
new Short((short)4);
Short((short)4);
short
short ss == wshort.shortValue();
wshort.shortValue();
System.out.println("short
System.out.println("short variable's
variable's value:
value: "" ++ s);
s);
Integer
Integer wint
wint == new
new Integer(16);
Integer(16);
int
int ii == wint.intValue();
wint.intValue();
System.out.println("int
System.out.println("int variable's
variable's value:
value: "" ++ i);
i);
Long
Long wlong
wlong == new
new Long(123);
Long(123);
long
long ll == wlong.longValue();
wlong.longValue();
System.out.println("long
System.out.println("long variable's
variable's value:
value: "" ++ l);
l);
Float
Float wfloat
wfloat == new
new Float(12.34);
Float(12.34);
float
f
=
wfloat.floatValue();
float f = wfloat.floatValue();
System.out.println("float
System.out.println("float variable's
variable's value:
value: "" ++ f);
f);
}}
}}
Double
Double wdouble
wdouble == new
new Double(12.56);
Double(12.56);
double
d
=
wdouble.doubleValue();
double d = wdouble.doubleValue();
System.out.println("double
System.out.println("double variable's
variable's value:
value: "" ++ d);
d);
9

10. Распаковка

boolean
boolean variable's
variable's value:
value: false
false
byte
byte variable's
variable's value:
value: 22
short
short variable's
variable's value:
value: 44
int
int variable's
variable's value:
value: 16
16
long
variable's
value:
long variable's value: 123
123
float
float variable's
variable's value:
value: 12.34
12.34
double
double variable's
variable's value:
value: 12.56
12.56
10

11.

Автоматическая упаковка и распаковка
11

12.

Автоматическая упаковка и распаковка позволяет не указывать явно функции
для упаковки и распаковки. Функции для упаковки и распаковки компилятор
добавит автоматически. Автоматическая упаковка происходит при присваивании
значения примитивного типа переменной типа класса обёртки. Автоматическая
распаковка происходит при присваивании ссылки на объект класса обёртки
переменной примитивного типа или при использовании ссылок на объекты
классов обёрток в качестве операндов которые должны быть примитивами.
12

13. Автоматическая упаковка

public
public class
class AutoWrapDemo
AutoWrapDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
boolean
boolean boo
boo == false;
false;
Boolean
Boolean wboo
wboo == boo;
boo;
System.out.println("boolean
System.out.println("boolean variable's
variable's value:
value: "" ++ wboo);
wboo);
byte
byte bb == 2;
2;
Byte
Byte wbyte
wbyte == b;
b;
System.out.println("byte
System.out.println("byte variable's
variable's value:
value: "" ++ wbyte);
wbyte);
short
short ss == 4;
4;
Short
Short wshort
wshort == s;
s;
System.out.println("short
System.out.println("short variable's
variable's value:
value: "" ++ wshort);
wshort);
int
int ii == 16;
16;
Integer
wint
Integer wint == i;
i;
System.out.println("int
System.out.println("int variable's
variable's value:
value: "" ++ wint);
wint);
long
long ll == 123;
123;
Long
wlong
Long wlong == l;
l;
System.out.println("long
System.out.println("long variable's
variable's value:
value: "" ++ wlong);
wlong);
float
float ff == 12.34f;
12.34f;
Float
Float wfloat
wfloat == f;
f;
System.out.println("float
System.out.println("float variable's
variable's value:
value: "" ++ wfloat);
wfloat);
}}
double
double dd == 12.56d;
12.56d;
Double
Double wdouble
wdouble == d;
d;
System.out.println("double
System.out.println("double variable's
variable's value:
value: "" ++ wdouble);
wdouble);
}}
13

14. Автоматическая упаковка

boolean
boolean variable's
variable's value:
value: false
false
byte
byte variable's
variable's value:
value: 22
short
short variable's
variable's value:
value: 44
int
int variable's
variable's value:
value: 16
16
long
variable's
value:
long variable's value: 123
123
float
float variable's
variable's value:
value: 12.34
12.34
double
double variable's
variable's value:
value: 12.56
12.56
14

15. Автоматическая распаковка

public
public class
class AutoUnwrapDemo
AutoUnwrapDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
Boolean
Boolean wboo
wboo == new
new Boolean(false);
Boolean(false);
boolean
boo
=
wboo;
boolean boo = wboo;
System.out.println("boolean
System.out.println("boolean variable's
variable's value:
value: "" ++ boo);
boo);
Byte
Byte wbyte
wbyte == new
new Byte((byte)2);
Byte((byte)2);
byte
b
=
wbyte;
byte b = wbyte;
System.out.println("byte
System.out.println("byte variable's
variable's value:
value: "" ++ b);
b);
Short
Short wshort
wshort == new
new Short((short)4);
Short((short)4);
short
short ss == wshort;
wshort;
System.out.println("short
System.out.println("short variable's
variable's value:
value: "" ++ s);
s);
Integer
Integer wint
wint == new
new Integer(16);
Integer(16);
int
int ii == wint;
wint;
System.out.println("int
System.out.println("int variable's
variable's value:
value: "" ++ i);
i);
Long
Long wlong
wlong == new
new Long(123);
Long(123);
long
long ll == wlong;
wlong;
System.out.println("long
System.out.println("long variable's
variable's value:
value: "" ++ l);
l);
Float
Float wfloat
wfloat == new
new Float(12.34);
Float(12.34);
float
f
=
wfloat;
float f = wfloat;
System.out.println("float
System.out.println("float variable's
variable's value:
value: "" ++ f);
f);
}}
}}
Double
Double wdouble
wdouble == new
new Double(12.56);
Double(12.56);
double
double dd == wdouble;
wdouble;
System.out.println("double
System.out.println("double variable's
variable's value:
value: "" ++ d);
d);
15

16. Автоматическая распаковка

boolean
boolean variable's
variable's value:
value: false
false
byte
byte variable's
variable's value:
value: 22
short
short variable's
variable's value:
value: 44
int
int variable's
variable's value:
value: 16
16
long
variable's
value:
long variable's value: 123
123
float
float variable's
variable's value:
value: 12.34
12.34
double
double variable's
variable's value:
value: 12.56
12.56
16

17.

Кеширование обёрток
17

18.

Неизменность объектов классов обёрток позволяет использовать один объект
несколько раз. Для повышения производительности объекты классов обёрток
Boolean, … , Integer, Long для некоторого диапазона значений примитивных
типов кешируются. Если используется автоматическая упаковка компилятор
добавляет инструкции для получения ссылки на объект обёртки из кеша
объектов обёрток если необходимый объект обёртка содержится в кеше.
18

19. Интересный пример

public
public static
static void
void main(String[]
main(String[] args)
args) {{
Integer
Integer ii == 127;
127;
Integer
Integer jj == 127;
127;
System.out.println("i==j
System.out.println("i==j >>
>> "" ++ (i
(i ==
== j));
j));
Integer
Integer aa == 127;
127;
Integer
Integer bb == new
new Integer(127);
Integer(127);
System.out.println("a==b
System.out.println("a==b >>
>> "" ++ (a
(a ==
== b));
b));
}}
Integer
Integer kk == 128;
128;
Integer
Integer ll == 128;
128;
System.out.println("k==l
System.out.println("k==l >>
>> "" ++ (k
(k ==
== l));
l));
C
Проводится упаковка примитивных типов в объекты. Используется два
вида упаковки автоматическая и не автоматическая. Ссылки на объекты
проверяются на равенство.
19

20. Неожиданный результат

i==j
i==j >>
>> true
true
a==b
a==b >>
>> false
false
k==l
k==l >>
>> false
false
Получается что ссылка на обёртку 127 равна ссылке
на обёртку 127 в первом случае но не равна во
втором, а ссылка на обёртку 128 не равна ссылке на
обёртку 128.
20

21. Класс Integer

public
public final
final class
class Integer
Integer extends
extends Number
Number implements
implements Comparable<Integer>
Comparable<Integer>
{{
private
private final
final int
int value;
value;
public
public Integer(int
Integer(int value)
value)
private
private static
static class
class IntegerCache
IntegerCache {{
static
static final
final int
int high;
high;
static
final
Integer
static final Integer cache[];
cache[];
static
static {{
final
final int
int low
low == -128;
-128;
int
int hh == 127;
127;
...
//
high
... // high value
value may
may be
be configured
configured by
by property
property
high
high == h;
h;
cache
cache == new
new Integer[(high
Integer[(high -- low)
low) ++ 1];
1];
int
j
=
low;
int j = low;
for(int
for(int kk == 0;
0; kk << cache.length;
cache.length; k++)
k++)
cache[k]
cache[k] == new
new Integer(j++);
Integer(j++);
}}
}}
}}
private
private IntegerCache()
IntegerCache() {}
{}
public
public static
static Integer
Integer valueOf(int
valueOf(int i)
i) {{
if
if (i
(i >=
>= -128
-128 &&
&& ii <=
<= IntegerCache.high)
IntegerCache.high)
return
return IntegerCache.cache[i
IntegerCache.cache[i ++ 128];
128];
else
else
return
return new
new Integer(i);
Integer(i);
}}
...
...
C
Класс Integer содержит кеш объектов обёрток для значений int от -128 до 127. При автоматической
упаковке компилятор добавляет вызов valueOf. Если нужный объект обёртки есть в кеше
возвращается ссылка на него, если нет возвращается ссылка на объект создаваемый с помощью
конструктора. При этом новый объект обёртки в кеш не добавляется.
21

22.

Ошибки с автоматической
упаковкой / распаковкой
22

23. Медленный цикл

public
public class
class SlowCycleDemo
SlowCycleDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
long
long time
time == System.currentTimeMillis();
System.currentTimeMillis();
for
for (Long
(Long ii == 0L;
0L; ii <=
<= 100000000L;
100000000L; i++)
i++) {{
}}
time
time == System.currentTimeMillis()
System.currentTimeMillis() -- time;
time;
}}
}}
System.out.println("It
System.out.println("It took
took "" ++ time
time ++ "" milliseconds
milliseconds to
to execute
execute this
this cycle");
cycle");
C
Замеряется время выполнения 100000000 итераций пустого цикла. В качестве счётчика
итераций цикла используется переменная типа Long т.е. типа класса обёртки. Это значит что
увеличение счётчика потребует распаковку и упаковку. Затрат на упаковку и распаковку можно
избежать если в качестве счётчика использовать переменную примитивного типа long.
23

24. Медленный цикл

It
It took
took 1375
1375 milliseconds
milliseconds to
to execute
execute this
this cycle
cycle
It
It took
took 156
156 milliseconds
milliseconds to
to execute
execute this
this cycle
cycle
Показан вывод для цикла который использует в качестве
счётчика Long и для цикла который использует в качестве
счётчика long. Использование long почти на порядок
быстрее, так как не требует затрат на распаковку и
упаковку.
24

25. Ещё один медленный цикл

public
public class
class AnotherSlowCycleDemo
AnotherSlowCycleDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
long
long time
time == System.currentTimeMillis();
System.currentTimeMillis();
Long
Long sum
sum == 0L;
0L;
for
for (long
(long ii == 0;
0; ii <=
<= 100000000L;
100000000L; i++)
i++) {{
}}
}}
}}
sum
sum +=
+= i;
i;
time
time == System.currentTimeMillis()
System.currentTimeMillis() -- time;
time;
System.out.println(time);
System.out.println(time);
System.out.println("Sum
System.out.println("Sum is:
is: "" ++ sum);
sum);
C
Замеряется время выполнения 100000000 итераций цикла в котором
происходит накопление значений в переменной типа Long т.е. типа
класса обёртки. Это значит что операция += потребует распаковку и
упаковку. Затрат на упаковку и распаковку можно избежать если
использовать переменную примитивного типа long.
25

26. Ещё один медленный цикл

It
It took
took 1110
1110 milliseconds
milliseconds to
to execute
execute this
this cycle
cycle
Sum
Sum is:
is: 5000000050000000
5000000050000000
It
It took
took 203
203 milliseconds
milliseconds to
to execute
execute this
this cycle
cycle
Sum
Sum is:
is: 5000000050000000
5000000050000000
Показан вывод для цикла который использует для
накопления значений переменную типа Long и для
цикла который использует для накопления значений
переменную типа long. Использование long в 5-6 раз
быстрее, так как не требует затрат на распаковку и
упаковку.
26

27. Ошибка с оператором ==

public
public class
class WrapErrorDemo
WrapErrorDemo {{
public
public static
static void
void main(String[]
main(String[] args)
args) {{
System.out.println("Compare
System.out.println("Compare
System.out.println("Compare
System.out.println("Compare
System.out.println("Compare
System.out.println("Compare
}}
50
50 and
and 100
100 :: "" ++ compare(50,
compare(50, 100));
100));
100
100 and
and 50
50 :: "" ++ compare(100,
compare(100, 50));
50));
50
50 and
and 50
50 :: "" ++ compare(50,
compare(50, 50));
50));
System.out.println("Compare
System.out.println("Compare 200
200 and
and 200
200 :: "" ++ compare(200,
compare(200, 200));
200));
public
public static
static int
int compare(Integer
compare(Integer first,
first, Integer
Integer second)
second) {{
}}
}}
return
return first
first << second
second ?? -1
-1 :: (first
(first ==
== second
second ?? 00 :: 1);
1);
C
При передаче значений примитивных типов в качестве параметров в
метод compare происходит автоматическая упаковка. Оператор >
приводит к автоматической распаковке и сравнению примитивных
значений. Оператор == может применяться к ссылкам и поэтому не
приводит к распаковке и сравнению значений примитивов. Вместо этого
он сравнивает ссылки которые будут равны только для кешированных
объектов обёрток.
27

28. Ошибка с оператором ==

Compare
Compare
Compare
Compare
Compare
Compare
Compare
Compare
50
50 and
and 100
100 :: -1
-1
100
100 and
and 50
50 :: 11
50
50 and
and 50
50 :: 00
200
200 and
and 200
200 :: 11
Два различных объекта обёртки для значения 200
располагаются в различных областях памяти
поэтому оператор == вернёт false и получится что
200 > 200.
28
English     Русский Rules