Приведення типів

Java відноситься до мов з сильною типізацією – Це означає, що під час компіляції практично завжди здійснюється перевірка на сумісність типів Java запобігає невірні присвоювання, забороняючи всі скільки сумнівні операції, і підтримує механізм приведення типів для тих випадків, коли сумісність може бути перевірена тільки під час виконання програми Ми будемо розглядати приведення типів на прикладі операції привласнення, але все сказане відноситься і до перетворень всередині виразів, і до присвоюванню значень параметрам методів

5131 Неявне приведення типів

Деякі приведення типів відбуваються автоматично, без втручання з вашого боку Існує дві категорії неявних привидів

Перша категорія неявних привидів типу відноситься до примітивних значень Числової змінної можна привласнити будь числове значення, що входить до допустимий діапазон даного типу Тип char може використовуватися усюди, де допускається використання int Значення з плаваючою точкою може бути присвоєно будь-якої змінної з плаваючою точкою, що має ту ж або більшу точність

Java також підтримує неявні приведення цілих типів у типи з плаваючою точкою, але не навпаки – при такому переході не відбувається втрати значимості, оскільки діапазон значень з плаваючою точкою ширше, ніж у будь-якого з цілих типів

Збереження діапазону не слід плутати із збереженням точності При деяких неявних перетвореннях можлива втрата точності Наприклад, розглянемо перетворення long в float Значення float є 32-розрядними, а значення long –

64-розрядними float містить менше значущих цифр, ніж long, навіть незважаючи на те,

що цей тип здатний зберігати числа з більшого діапазону Присвоєння значення long

змінної типу float може призвести до втрати даних Розглянемо наступний фрагмент:

long orig = 0x7effffffffffffffL

float fval = orig

long lose = (long)fval

Systemoutprintln(&quotorig = &quot + orig) Systemoutprintln(&quotfval = &quot + fval) Systemoutprintln(&quotlosw = &quot + lose)

Перші два оператора створюють значення long і привласнюють його змінної float Щоб продемонструвати, що при цьому відбувається втрата точності, ми виробляємо явне приведення fval до long і присвоюємо значення іншої змінної (явне приведення типів розглядається нижче) Результати, виведені програмою, дозволяють переконатися в тому, що значення float втратило частину своєї точності, так як значення вихідної змінної orig типу long відрізняється від того, що було отримано при явному зворотному приведенні значення змінної fval до типу long:

orig = 9151314442816847871 fval = 915131e+18

lose = 9151314442816847872

Другий тип неявного приведення – приведення за посиланням Обєкт, що відноситься до деякого класу, включає екземпляри кожного з супертіпа Ви можете використати посилання на обєкт типу в тих місцях, де потрібно посилання на будь-який з його супертіпа

Значення null може бути присвоєно посиланням на обєкт будь-якого типу, в тому числі і засланні на масив

5132 Явна приведення і instanceof

Коли значення одного типу не може бути присвоєно змінної іншого типу допомогою неявного приведення, досить часто можна скористатися явним приведенням типів (cast) Явна приведення вимагає, щоб нове значення нового типу якнайкраще відповідало старого значенням старого типу Деякі явні приведення неприпустимі (ви не зможете перетворити boolean в int), проте дозволяється, наприклад, явне приведення double до значення типу long, як показано в наступному фрагменті:

double d = 799

long l = (long)d

Коли значення з плаваючою точкою перетвориться до цілого типу, його дрібна частина відкидається наприклад, (int) -723 дорівнює -72 У класі Math є методи, які інакше здійснюють округлення чисел з плаваючою точкою при перетворенні в ціле – див розділ Клас Math.

Значення double також може явно перетворюватися до типу float, а значення цілого

типу – до меншого цілого типу При приведенні double до float можлива втрата точності або ж поява нульового або нескінченного значення замість існуючого раніше кінцевого

Приведення цілих типів полягає в зрізанні їх старших бітів Якщо значення більшого цілого уміщається в меншому типі, до якого здійснюється перетворення, то нічого страшного не відбувається Однак якщо величина більш широкого цілого типу лежить за межами вужчого типу, то втрата старших бітів змінює значення, а можливо – і знак Фрагмент:

short s = -134

byte b = (byte)s

Systemoutprintln(&quots = &quot + s + &quot, b = &quot + b)

виводить наступний результат (оскільки старші біти s втрачаються при збереженні значення в b):

s = -134, b = 122

char можна перетворити до будь-якого цілого типу і навпаки При приведенні цілого типу в char використовуються тільки молодші 16 біт, а інші біти відкидаються При перетворенні char в цілий тип старші 16 біт заповнюються нулями Проте згодом робота з цими бітами здійснюється точно так само, як і з будь-якими іншими У наведеному нижче фрагменті програми максимальний символ Unicode перетворюється до типу int (неявно) і до типу short (явно) Значення типу int (0x0000ffff) виявляється позитивним, оскільки старші біти символу обнулені Однак при приведенні до типу short виходить негативна величина, так як старшим бітом типу short є знаковий біт:

class CharCast {

public static void main(String[] args) {

int i = \uffff;

short s = (short)\uffff;

Systemoutprintln(&quoti = &quot + i) Systemoutprintln(&quots = &quot + s)

}

}

А ось як виглядає результат роботи:

i = 65535 s = -1

Явна приведення типів може застосовуватися і до обєктів Хоча обєкт розширеного типу дозволяється використовувати замість обєкта супертіпа, зворотне, взагалі кажучи, невірно Припустимо, у вас є наступна ієрархія обєктів:

Посилання типу Coffee не обовязково відноситься до типу Mocha – обєкт також може мати тип Latte Отже, невірно, взагалі кажучи, ставити посилання на обєкт типу Coffee там, де потрібна посилання на обєкт типу Mocha Подібне приведення називається звуженням (narrowing), Або знижуючим приведенням, В ієрархії класів Іноді його також називають ненадійним приведенням (unsafe casting), Оскільки воно не завжди допустимо Перехід від типу, розташованого нижче в ієрархії, до розташованого вище називається що підвищує приведенням типу крім того, вживається термін надійне приведення, Оскільки воно працює у всіх випадках

Але іноді ви абсолютно точно знаєте, що обєкт Coffee насправді є екземпляром класу Mocha У цьому випадку можна здійснювати явне понижувальний приведення Це робиться таким чином:

Mocha fancy = (Mocha)joe

Якщо таке приведення спрацює (тобто посилання joe дійсно вказує на обєкт типу Mocha), то посилання fancy буде вказувати на той же обєкт, що і joe, однак з її допомогою можна отримати доступ до додаткових функцій, що надаються класом Mocha Якщо ж перетворення виявиться неприпустимим, буде порушено виняток ClassCastException У разі, якщо приведення навіть потенційно НЕ може бути правильним (наприклад, якби Mocha взагалі не був подклассом того класу, до якого належить joe), буде видано повідомлення про помилку під час компіляції програми Таким чином запобігають можливі проблеми, повязані з невірними припущеннями з приводу ієрархії класів

Іноді метод не вимагає, щоб обєкт ставився до розширеного типу, але може надати обєктам розширеного типу додаткові функції Можна виконати приведення типу і обробити виняток, однак використання винятків для подібних цілей виявляється порівняно повільним і тому вважається проявом поганого стилю Для визначення того, чи відноситься обєкт до конкретного типу, застосовується метод instanceof, який повертає true для допустимих перетворень:

public void quaff(Coffee joe) {

// ..

if (joe instanceof Mocha) { Mocha fancy = (Mocha)joe

/ / .. Використовувати функціональність Mocha

}

}

Посилання null не вказує ні на який конкретний обєкт, так що результат виразу

null instanceof Type

завжди дорівнює false для будь-якого типу Type

5133 Строкове приведення

Клас String відрізняється від інших: це неявно використовується в операторі конкатенації

+, А рядкові літерали посилаються на обєкти String Приклади нам вже зустрічалися в програмах: при виконанні конкатенації Java намагається перетворити в String все, що ще не відноситься до цього типу Подібні приведення визначені для всіх примітивних типів і здійснюються викликом методу toString обєкта (див розділ Метод toString)

Якщо перетворити в String порожню посилання, то результатом буде рядок null. Якщо для даного класу метод toString не визначений, то використовується метод, успадкований від класу Object і повертає строкове представлення типу обєкта

Джерело: Арнольд К, Гослінг Д – Мова програмування Java (1997)

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*