1. Преобразуване на типове
Променливите от примитивни типове (с изключение на boolean
типа) се използват за съхраняване на различни видове числа. Въпреки че типовете променливи никога не са се променяли, има място, където можете да конвертирате от един тип в друг. И това място е наmeaning .
Променливи от различни типове могат да бъдат присвоени една на друга. Когато направите това, стойността на променлива от един тип се преобразува в стойност от друг тип и се присвоява на втората променлива. В това отношение можем да идентифицираме два вида преобразуване на типове: разширяване и стесняване.
Разширяването е като преместване на стойност от малка кошница в голяма: тази операция е безпроблемна и безболезнена. Стесняването се случва, когато преместите стойност от голяма кошница в малка: може да няма достатъчно място и ще трябва да изхвърлите нещо.
Ето видовете, сортирани по размер на кошницата:
2. Разширяване на типовите преобразувания
Често е необходимо променлива от един числов тип да се присвои на променлива от друг числов тип. Как правиш това?
Java има 4 цели числа:
Тип | Размер |
---|---|
byte |
1 byte |
short |
2 bytes |
int |
4 bytes |
long |
8 bytes |
Променливите, съхранявани в по-малки кошници, винаги могат да бъдат присвоени на променливи, съхранявани в по-големи кошници.
int
, short
а byte
променливите могат лесно да бъдат присвоени на long
променливи. short
и byte
променливите могат да бъдат присвоени на int
променливи. И byte
променливите могат да бъдат присвоени на short
променливи.
Примери:
Код | Описание |
---|---|
|
Този code ще се компorра добре. |
Такова преобразуване от по-малък към по-голям тип се нарича преобразуване на разширяващ се тип.
Какво ще кажете за реалните числа?
При тях всичко е същото - размерът има meaning:
Тип | Размер |
---|---|
float |
4 bytes |
double |
8 bytes |
float
променливите могат да бъдат присвоени на double
променливи без ниHowви проблеми. Но нещата са по-интересни с целочислените типове.
Можете да присвоите всяка променлива с цяло число към float
променлива. Дори long
типът, който е дълъг 8 byteа. И можете да присвоите Howвото искате - всяка променлива с цяло число or float
променлива - към double
променлива:
Код | Забележка |
---|---|
|
|
Обърнете внимание, че преобразуването в реален тип може да доведе до загуба на точност поради липсата на достатъчно значими цифри.
При преобразуване от цели числа към числа с плаваща запетая, частите от по-нисък ред на числата могат да бъдат изхвърлени. Но тъй като се разбира, че дробните числа съхраняват приблизителни стойности, такива операции за присвояване са разрешени.
3. Стесняващи преобразувания на типове
Какво ще кажете за другите възможности? Ами ако трябва да присвоите long
стойност на int
променлива?
Представете си променлива като кошница. Разполагаме с кошници с различни размери: 1, 2, 4 и 8 byteа. Не е проблем да прехвърлите ябълки от по-малка кошница в по-голяма. Но при преместване от по-голяма кошница в по-малка, някои от ябълките може да се загубят.
Тази трансформация — от по-голям тип към по-малък тип — се нарича преобразуване на стесняващ тип . Когато извършвате операция за присвояване като тази, част от число може просто да не се побере в новата променлива и следователно може да бъде отхвърлена.
Когато стесняваме тип, трябва изрично да кажем на компилатора, че не правим грешка, че нарочно изхвърляме част от числото. За това се използва операторът typecast. Това е име на тип в скоби .
В такива ситуации компилаторът на Java изисква от програмиста да посочи оператора за преобразуване на типа. В общи линии изглежда така:
(type) expression
Примери:
Код | Описание |
---|---|
|
Всеки път операторът за придаване на типа трябва да бъде посочен изрично |
Тук a
е равно на 1
и може би операторът typecast изглежда пресилен. Но Howво, ако a
бяха по-големи?
Код | Описание |
---|---|
|
|
Един мorон се вписва перфектно в a long
и в int
. Но когато присвоите един мorон на short
променлива, първите два byteа се изхвърлят и само последните два byteа се запазват. И когато се присвоява на byte
, единственото нещо, което остава, е последният byte.
Как се подреждат числата в паметта:
Тип | Двоичен запис | Десетичен запис |
---|---|---|
int |
0b 00000000 00001111 01000010 01000000 | 1000000 |
short |
0b 01000010 01000000 | 16.960 |
byte |
0b 01000000 | 64 |
char
Тип
A char
, подобно на a short
, заема два byteа, но за да преобразувате един в друг, винаги трябва да използвате оператор за typecast. Проблемът тук е, че short
типът е със знак и може да съдържа стойности от -32,768
до +32,767
, но char
типът е без знак и може да съдържа стойности от 0
до 65,535
.
Отрицателните числа не могат да се съхраняват в char
, но могат да се съхраняват в short
. И short
не може да съхранява числа, по-големи от 32,767
, но такива числа могат да се съхраняват в char
.
4. Вид на израза
Какво става, ако променливи от различни типове се използват в един и същи израз? Логично разбираме, че те първо трябва да бъдат преобразувани в общ тип. Но кое?
Към по-голямата, разбира се.
Java винаги преобразува в по-големия тип. Грубо казано, първо се разширява единият тип и едва след това се извършва операцията със стойности от същия тип.
Ако an int
и a long
са включени в израз, стойността на int
ще бъде преобразувана в a long
и едва тогава операцията ще продължи:
Код | Описание |
---|---|
|
a ще бъде разширен до a long и след това ще се извърши добавянето. |
Числа с плаваща запетая
Ако цяло число и число с плаваща запетая ( float
or double
) са включени в израз, цялото число ще бъде преобразувано в число с плаваща запетая ( float
or double
) и едва тогава ще бъде изпълнена операцията.
Ако операцията включва a float
и a double
, тогава float
ще се преобразува в a double
. Което всъщност се очаква.
Типовете byte
, short
и char
винаги се преобразуват в int
, когато взаимодействат един с друг. Има основателна причина, поради която int
типът се счита за standardн целочислен тип.
Ако умножите a byte
по a short
, ще получите a int
. Ако умножите a byte
по a byte
, ще получите a int
. Дори ако добавите a byte
и a byte
, получавате a int
.
Причините за това са няколко. Примери:
Код | Описание |
---|---|
|
110 * 120 е 13,200 , което е малко по-голямо от максималната стойност на byte типа:127 |
|
110 + 120 е 230 , което също е малко по-голямо от максималната стойност на byte типа:127 |
Като цяло, когато умножаваме 8-битово (1 byte) число с 8-битово (1 byte) число, получаваме число, което заема 16-битови бита (2 byteа)
В резултат на това всички операции с цели числа, които са по-малки от int
винаги незабавно се преобразуват в int
s. И това означава, че ако искате да съхраните резултата от изчислението в променлива от тип, който е по-малък от int
, тогава винаги ще трябва изрично да посочите оператора за преобразуване на типа.
Примери:
Код | Описание |
---|---|
|
Изразът byte * byte ще бъде anint |
|
Изразът byte + byte ще бъде anint |
|
Изразът byte + int ще бъде int Буквалният е int . |
5. Важен нюанс
Операторът typecast има доста висок приоритет.
Това означава, че ако даден израз съдържа, например, добавяне и оператор за привеждане на типа, привеждането на типа ще бъде извършено преди добавянето.
Пример:
Код | Описание |
---|---|
|
Операторът за typecast ще бъде приложен само към a променливата, която вече е byte . Този code няма да се компorра. |
|
Това е правилният начин. |
Ако искате да преобразувате целия израз в конкретен тип, а не само един компонент на израза, увийте целия израз в скоби и поставете оператора за преобразуване на типа отпред.
GO TO FULL VERSION