Урок 10

Преобразование ссылочных типов


1. Расширение

Расширение означает переход от более конкретного типа к менее конкретному, т.е. переход от детей к родителям.

Подобно случаю с примитивными типами, этот переход производится самой JVM при необходимости и незаметен для разработчика:

Box6 heavyBox = new HeavyBox(15, 10, 20, 5);
Box6 colorBox = new ColorBox(25, 12, 20, "красный");

Также расширяющим являются преобразованием от null-типа к любому объектному типу: 

Box6 box = null;

2. Сужение

Обратный переход, то есть движение по дереву наследования вниз, к наследникам, является сужением.

Пример 1. Сужающее преобразование

public class CastingDemo1 {
    public static void main(String[] args) {
        Box6 box1 = new HeavyBox1();
        // System.out.println(box1.weight);

        HeavyBox1 heavyBox1 = (HeavyBox1) box1;
        System.out.println("Weight: " + heavyBox1.weight);

        Box6 box2 = new ColorBox();
        HeavyBox1 heavyBox2 = (HeavyBox1) box2; //ClassCastException

        Box6 box3 = new Box6();
        HeavyBox1 heavyBox3 = (HeavyBox1) box3; //ClassCastException
    }
}

3. Оператор instanceof

Пример 2. Использование оператора instanceof

public class CastingDemo2 {
    public static void main(String[] args) {
        Box6 box1 = new HeavyBox1();
        if (box1 instanceof HeavyBox1) {
            System.out.println("Приведение 1");
        }
        if (box1 instanceof Box6) {
            System.out.println("Приведение 2");
        }
        if (box1 instanceof Object) {
            System.out.println("Приведение 3");
        }

        Box6 box2 = new ColorBox();
        if (box2 instanceof HeavyBox1) {
            System.out.println("Приведение 4");
        }

        Box6 box3 = new Box6();
        if (box3 instanceof HeavyBox1) {
            System.out.println("Приведение 5");
        }
    }
}

Пример 3. Использование оператора instanceof

public class CastingDemo3 {
    public static void main(String[] args) {
        Moveable moveable1 = new Transport();
        if (moveable1 instanceof Transport) {
            Transport transport = (Transport) moveable1;
            transport.start();
        }

        Moveable moveable2 = new Robot();
        if (moveable2 instanceof Transport) {
            Transport transport = (Transport) moveable1;
            transport.stop();
        }
    }
}

4. Несовместимые преобразования

Преобразования возможны только внутри одной иерархии.

Данный пример не откомпилируется: 

Box6 box1 = new HeavyBox1();
String str = (String) box1;

5. Преобразование типов для массивов

5.1. Массивы и примитивные типы

Переходы между массивами и примитивными типами являются запрещенными:

Пример 4. Переход между примитивным типом и массивом

public class ArrayCastingDemo1 {
    public static void main(String[] args) {
        int[] array = new int[5];
        //int someNumber =array;
        int someNumber = array[0];
    }
}

5.2. Примитивные и ссылочные массивы

Массив, основанный на примитивном типе, принципиально нельзя преобразовать к типу массива, основанному на ссылочном типе, и наоборот:

Пример 5. Переход между примитивным и ссылочным массивом

public class ArrayCastingDemo2 {
    public static void main(String[] args) {
        Integer[] array1 = new Integer[4];
        int[] array2 = new int[4];
        //  array1 = array2;
        //  array2 = array1;
    }
}

5.3. Массивы основанные на разных примитивных типах

Преобразования между типами массивов, основанных на различных примитивных типах, невозможно:

Пример 6. Переход между массивами, основанных на различных примитивных типах

public class ArrayCastingDemo3 {
    public static void main(String[] args) {
        int[] array1 = new int[5];
        long[] array2 = new long[5];
        // array2 = array1;
    }
}

5.4. Ссылочные массивы основанные на типах из одной иерархии

Массив, основанный на типе HeavyBox, можно привести к массиву, основанному на типе Box, если сам тип HeavyBox приводится к типу Box.

Пример 7. Переход между массивами, основанных на типах из одной иерархии

public class ArrayCastingDemo5 {
    public static void main(String[] args) {
        Box6[] boxArray = new Box6[5];
        HeavyBox1[] heavyBoxArray = new HeavyBox1[6];
        boxArray = heavyBoxArray;
        //heavyBoxArray = (HeavyBox1[]) boxArray;
    }
}

5.5. Массивы и другие ссылочные типы

Преобразования между массивами и другими объектными типами возможны только для класса Object и интерфейсов Cloneable и Serializable.

Пример 8. Переход между массивами и другими ссылочными типами

public class ArrayCastingDemo4 {
    public static void main(String[] args) {
        Box6[] array = new Box6[5];
        Object object = array;
        Cloneable cloneable = array;
        Serializable serializable = array;
    }
}

5.6. Ошибка ArrayStoreException

public class ArrayCastingDemo6 {
    public static void main(String[] args) {
        HeavyBox1[] heavyBox = new HeavyBox1[4];
        Box6[] box = heavyBox;
        box[0] = new Box6(); //ArrayStoreException
    }
}


0 comments
Leave your comment: