Приведение типов в Java

Приведение типов (type casting) — это преобразование значения одного типа в другой. В Java типизация строгая, поэтому компилятор требует явного указания преобразования там, где возможна потеря данных.

Различают расширяющее преобразование (widening, неявное), когда меньший тип превращается в больший без потерь (например, int double), и сужающее преобразование (narrowing, явное), которое нужно записать с помощью (тип) — оно может привести к потере точности или переполнению.

Синтаксис

// Неявное (widening)
int  i = 10;
double d = i;          // OK

// Явное (narrowing)
double x = 3.99;
int    y = (int) x;    // нужно (int)

Пример 1. Расширяющее преобразование

public class Widening {
    public static void main(String[] args) {
        int adc = 512;
        double voltage = adc * (5.0 / 1023.0);
        System.out.println("Напряжение: " + voltage);
    }
}

Вывод:

Напряжение: 2.502443792766373

Пример 2. Сужающее преобразование с потерей дробной части

public class Narrowing {
    public static void main(String[] args) {
        double temp = 36.78;
        int rounded = (int) temp;
        System.out.println("Исходная: " + temp);
        System.out.println("После (int): " + rounded);
    }
}

Вывод:

Исходная: 36.78
После (int): 36

Пример 3. Переполнение при сужении

public class Overflow {
    public static void main(String[] args) {
        int big = 300;
        byte b = (byte) big;   // byte: -128..127
        System.out.println("int = " + big);
        System.out.println("byte = " + b);
    }
}

Вывод:

int = 300
byte = 44

Пример 4. Целочисленное деление и приведение

public class IntDivision {
    public static void main(String[] args) {
        int a = 7, b = 2;
        int  intDiv    = a / b;
        double realDiv = (double) a / b;
        System.out.println("int деление: " + intDiv);
        System.out.println("real деление: " + realDiv);
    }
}

Вывод:

int деление: 3
real деление: 3.5

Пример 5. char и int

public class CharInt {
    public static void main(String[] args) {
        char c = 'A';
        int code = c;          // widening: char -> int
        char next = (char)(c + 1);
        System.out.println("Код 'A' = " + code);
        System.out.println("Следующий символ = " + next);
    }
}

Вывод:

Код 'A' = 65
Следующий символ = B

Пример 6. Шкалирование значения датчика

public class SensorScale {
    public static void main(String[] args) {
        int raw = 800;                  // 0..1023
        int percent = (int)((raw / 1023.0) * 100);
        System.out.println("Освещённость: " + percent + "%");
    }
}

Вывод:

Освещённость: 78%

Подводные камни

  • Потеря данных. При (int) double дробная часть отбрасывается, а не округляется. Для округления используйте Math.round().

  • Переполнение. Сужение int byte/short молча урезает старшие биты — отрицательные значения могут возникнуть «из ниоткуда».

  • Целочисленное деление. 5 / 2 даст 2. Хотя бы один операнд должен быть double/float, чтобы получить 2.5.

  • Приведение объектов. Между ссылочными типами тоже бывает каст: (String) obj. Если объект не того типа — будет ClassCastException в рантайме.

  • Boolean не приводится. В Java boolean нельзя привести к числовым типам — это не C.

См. также

Примечание

Лицензия и источники

Концепция описана на основе официального Java Tutorial от Oracle (https://docs.oracle.com/javase/tutorial/), Oracle Free Documentation License. Перевод, примеры и пояснения — © AlashEd Wiki.