Преобразование и приведение типов в Java

Уточним:

Приведение - это явное преобразование

А оно (это самое преобразование) может быть и неявным, так например, возможно такое присваивание - где преобразование между двуме целочисленными типами будет выполнено автоматически:

int a = 12234234;
double b =  a;

Вообще преобразование происходит автоматически если выполняются два момента:

  1. типы совместимы (например - как в примере выше - оба целочисленные)
  2. размер "принимающего" типа больше чем у того, который преобразуется (так называемое "преобразование с расширением")

Несовместимость и Приведение =)

Если одно из условий выше не выполнено -можно заняться явным преобразованием -приведением типов, так например, по мере необходимости можно выполнить "преобразование с сужением":

int a;
byte b = (byte) a;

Кстати - b будет вычисляться как остаток от деления b на диапазон типа byte (то есть возможны потери данных)

Вообще приведение подчиняется схеме:

переменная_нового_типа  = (новый_тип) имя переменной;

Аналогичным образом можно приводить целочисленные значения к типам с "плавающей точкой", при обратном же преобразовании будет отбрасываться дробная часть.

Автоматическое повышение типа в выражениях

Чтобы результат операции или их комбинации не вылез за диапазон Ява автоматически "повысит" целочисленные типы малого размера до int - это в принципе удобно - так как не надо бояться ошибок, но в свою очередь тоже порождает последние , причём в несколько "неочевидных" ситуациях, например:

byte b = 50;
b =  b * 2; // ОШИБКА: byte меньше int
//а потому автоматическое преобразование невозможно!
// Возможное решение:
b =  (byte) (b * 2);  // явное преобразование (приведение типов)

Можно сказать, что существуют следующие правила повышения типов (в порядке "усиления" - т.е. если участвует double - то независимо от числа операндов других типов в выражении мы получим именно double - т. к. он наиболее информативен - 64 бита + возможность хранить дробную часть):

  1. char, byte, char в выражениях всегда повышаются до int
  2. если в выражении участвует тип long - то именно к этому типу будет приведён результат
  3. если в выражении участвует float - то результат приводится к float
  4. если один из операндов имеет тип double - то к этому типу будет приведён весь результат

Правда, перечисленные правила оставляют несколько вопросов - а именно - что будет, например, если в выражении участвуют два "супер-типа" double и long?

В соответствии с логикой Ява выберет дабл, так как он может хранить дробные значения (хотя по размеру равен long).
Проиллюстрировать данный момент можно так:

 public class Test {

        public static void main(String[] args) {
        double b = 1000;
        long a = 1000;
        Object c = a - b; // присвоим "обобщённому" типу
        Class cls = c.getClass();   // получим тип
        // напечатаем тип в консоли:
        System.out.println("The type of the object is: " + cls.getName());
        }

    }
// Результат:
// The type of the object is: java.lang.Double

При этом интересно заметить - что при выборе между длинной и возможностью сохранить дробную часть выбрано будет последнее (результат с участием double и float будет приведён к меньшему по размеру float):

 public class Test {

        public static void main(String[] args) {
        float b = 1000; // float 32 bit
        long a = 10000000; // long 64 bit
        Object c = a - b; // присвоим "обобщённому" типу
        Class cls = c.getClass();   // получим тип
        // напечатаем тип в консоли:
        System.out.println("The type of the object is: " + cls.getName());
        }
    }
// Результат:
//The type of the object is: java.lang.Float

Движемся дальше =)

Key Words for FKN + antitotal forum (CS VSU):