Какая польза от TypeCasting в Java

мы можем добиться вывода двумя способами: один - с приведением типов, а другой - без приведения типов.

A a=new B() // without typecaste

A a  = (A)a// with Typecaste

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


person Sandeep Kumar    schedule 02.09.2016    source источник
comment
Какой выход вы имеете в виду?   -  person xenteros    schedule 02.09.2016


Ответы (6)


Предположим, у вас есть список Animal. и у вас есть Tigers и Lions в нем.

ArrayList<Animal> animals = new ArrayList<>();
//add some Tigers and some Lions
//sort so Tigers are at the beggining of the list
Tiger t = (Tiger)animals.get(0);

Без приведения вы получите несоответствие типов во время компиляции. С броском вы рискуете только ClassCastException, который можно легко поймать с try-catch

Это просто пример правильного использования приведения классов в Java.

person xenteros    schedule 02.09.2016

Приведение предназначено для "противоположного направления", то есть для преобразования в выражение подтипа исходного выражения.

Пример

Данный

Object o = "Hello World";
String s = o;

не компилируется, а

String s = (String) o;

компилирует. Однако это может привести к ClassCastException, например. если Integer был сохранен в o.

person fabian    schedule 02.09.2016

Кастинг имеет разные применения. К сожалению, в вашем примере нет полезного примера приведения, поскольку вы создаете экземпляр A (a), а затем приводите его к A.

Вам нужно понимать, что существуют кажущиеся типы и фактические типы. Очевидным типом будет List<T> list;. Здесь мы видим, что это список. Но фактический тип может быть ArrayList<T> (List<T> list = new ArrayList<>();). В этом сценарии мы можем с осторожностью привести кажущийся тип к фактическому типу. Это позволит нам затем использовать функциональность фактического типа. Например, давайте посмотрим на какой-нибудь код; данный:

List<Integer> list = new ArrayList<>();
ArrayList<Integer> aList;
LinkedList<Integer> lList = new LinkedList<>();

Мы можем сделать это без проблем (хотя в целом опасно)...

// Dangerous but OK with a cast
// list might not be an ArrayList 
aList = (ArrayList<Integer>) list;
// Use ArrayList methods
aList.trimToSize(); 
list = lList;
LinkedList<Integer> danger = (LinkedList<Integer>) list;

... но также можно сделать:

aList = (ArrayList<Integer) list; 
// Use ArrayList methods
aList.trimToSize();
// list = lList;
LinkedList<Integer> danger = (LinkedList<Integer>) list;

Последний фрагмент дает ClassCastException, потому что list не является LinkedList.

Однако кастинг выходит за рамки этого. Рассмотрим, когда у вас есть два целых числа, которые вы хотите разделить. Без приведения вы могли бы получить целочисленный результат, где более уместно число с плавающей запятой. Рассмотреть возможность:

int i = 2;
int j = 3;
System.out.println("No cast: " + i/j + " ;With cast: " + (double)i/j);

Выход:

Без приведения: 0; С приведением: 0,6666666666666666

Итак, это зависит от варианта использования.

person ChiefTwoPencils    schedule 02.09.2016

A a = new B();

будет работать, только если B наследуется от A.

Если B наследуется от A, приведение типа не требуется, поскольку B является A. Приведение типа необходимо, если вам нужно привести тип к подклассу:

A a = new B();
B b = (B) a;

Хотя это было бы незаконно:

A a = new A();
B b = (B) a;

поскольку a не является B.

person Hugo G.    schedule 02.09.2016

Java неявно выполняет присваивание, поэтому в предоставленном вами коде оператор приведения является избыточным; a уже имеет тип A:

A a = new B(); // without typecast operator (implicit upcast)
A a = (A)a; // with redundant typecast operator

Одна из причин наличия оператора приведения заключается в том, что вы также можете захотеть выполнить приведение вниз (что не делается неявно в Java). Например, когда a является ссылкой типа A на объект класса B (например, когда B является подклассом A), может потребоваться понижающее приведение для доступа к определенным методам:

A a = new B(); // implicit upcast
C c = ((B)a).methodOfBOnly(); // explicit downcast

Вы также можете проверить этот вопрос о том, почему Java не сделать неявное понижение.

Могут быть случаи, когда приведение к более высокому уровню также должно быть выполнено явно. Например, если класс содержит перегруженные методы

C method(A x){/*does one thing*/}
C method(B x){/*does another*/}

и предполагая, что b имеет тип B, вызовы method((A)b) и method(b) будут вести себя по-разному.

person Linus    schedule 02.09.2016

A a=new B() 

применимо только тогда, когда class B расширяет class A. Таким образом, дополнительные методы, доступные в class B, кроме class A, будут доступны и в reference a.

Когда ты это сделаешь

A a  = (A)a

Тогда на самом деле вы преобразовываете объект class B в объект class A. И это правда, что дочерний тип может быть приведен к родительскому. После этого оператора reference a не сможет вызвать какой-либо метод class B, которого нет в class A, потому что теперь reference a указывает на объект class A.

Это полезно во многих сценариях. Например, вы хотите иметь коллекцию объектов, указывающих на один и тот же базовый класс. Вместо того, чтобы поддерживать отдельные коллекции для каждого подкласса, вы поддерживаете единую коллекцию базового класса. И затем, когда вы хотите использовать любой дочерний объект, вы вводите для этого объект базового класса в объект дочернего класса.

ArrayList<Base> children = new ArrayList<Base>();
children.add(new Child1());
children.add(new Child2());

Console.WriteLine(((Child1)children.get(0)).getChildName());
Console.WriteLine(((Child2)children.get(1)).getChildName());

Теперь в базовом классе нет методов с именами getChild1Name или getChild2Name. И вам нужно привести объект базового класса к соответствующему дочернему классу, чтобы сделать это.

person Umair Farooq    schedule 02.09.2016
comment
Они просят Java. List не может быть создан. Ваши примеры написания имен не только не компилируются, но и противоречат хорошему полиморфному дизайну. - person ChiefTwoPencils; 02.09.2016
comment
Не говоря уже о том, что у вас есть заброс назад. - person Linus; 02.09.2016
comment
@ChiefTwoPencils Спасибо, что указали на это. Я просто привел общий пример использования коллекции. Это не было специфичным для языка. Хотя они поставили тег JAVA, но в вопросе они просто задали общий вопрос. - person Umair Farooq; 02.09.2016
comment
@ Линус, я не понял твоего комментария. Не могли бы вы уточнить это? - person Umair Farooq; 02.09.2016
comment
@UmairFarooq, если B расширяет A, то приведение от B к A является восходящим преобразованием. Понижение будет от A до B; обратное тому, что у вас во втором абзаце. Кроме того... кастинг не меняет класс. a является ссылкой типа A на объект класса B. Приведение вверх или вниз, объект всегда относится к классу B, манипулируются только типом, на который ссылается компилятор. - person Linus; 02.09.2016