Явное приведение типов, массив производных классов - PullRequest
0 голосов
/ 26 сентября 2019
class Animal{ }
class Cat extends Animal{ }

public class Main
{     
    public static void main(String ab[])
    {   
        Animal[] objAnimal = {new Cat()};
        Cat objCat0 = (Cat)objAnimal[0]; // a valid operation.
        Cat[] objCatArray = (Cat[]) objAnimal; //not a valid operation.
    }
}

Я пытаюсь понять, что происходит за кулисами.

Почему Cat objCat0 = (Cat)objAnimal[0]; является допустимой операцией, а Cat[] objCatArray = (Cat[]) objAnimal; - нет?

1 Ответ

0 голосов
/ 26 сентября 2019
Animal[] objAnimal = {new Cat()};

- это ярлык для

Animal[] objAnimal = new Animal[] {new Cat()};

, который является ярлыком для

Animal[] objAnimal = new Animal[1];
objAnimal[0] = new Cat();

Скомпилированный код идентичен.Итак, при рассмотрении последнего варианта должно стать очевидным, что вы можете выполнить

Cat objCat0 = (Cat)objAnimal[0];

, поскольку ранее вы сохранили ссылку на экземпляр Cat, созданный с помощью new Cat(), на objAnimal[0], тогда как

Cat[] objCatArray = (Cat[]) objAnimal;

недопустим, поскольку objAnimal содержит ссылку на экземпляр массива Animal[], созданный с помощью new Animal[1].Тот факт, что в одном элементе хранится ссылка Cat, не меняет тип массива.В любой момент может быть последующий objAnimal[0] = new Animal();.

Используемый в вашем вопросе синтаксис инициализатора массива существует для удобства, но не меняет логику.Таким образом,

Animal[] objAnimal = {new Cat()};
objAnimal[0] = new Animal();

действителен и

Cat[] objCatArray = (Cat[]) objAnimal;

должен потерпеть неудачу, так как в противном случае вы могли бы впоследствии использовать

Cat cat = objCatArray[0];

без приведения, несмотря на возможность objAnimal[0] = new Animal() назначение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...