2016-11-11 3 views
2

Я пытаюсь прояснить это, поэтому я полностью понимаю, каков тип. Пожалуйста, поправьте меня на что-то неправильное, поскольку я сам изучаю Java уже около 2 месяцев в очень медленном темпе.Тип литья/впускавание в Java

Предположим, я создал класс под названием SubObject. И я знаю, что все классы, которые не имеют прямого явного суперкласса, считаются подклассами класса Object.

Object obj1 = new SubObject(); 
    SubObject subObj1 = (SubObject) obj1; 
    System.out.println(subObj1); //prints out com.examplePackage.SubObject1234e1234; 

Так что я успешно downcasted ссылки базового класса (Object) для его производного класса (подобъект). Однако ...

Object obj2 = new Object(); 
SubObject subObj2 = (SubObject) obj2;//this throws the ClassCastException error. 

Мое понимание ошибки ClassCastException является то, что он унаследовал RuntimeException поймать его во время компиляции, чтобы показать, что код попытался бросить объект к подклассу, которого он не является экземпляром. Поскольку subObj2 НЕ является экземпляром SubObject, а скорее Object, он несовместим.

У меня есть 2 вопроса: 1. Есть ли недостатки/ошибки в моем понимании? 2. В какой ситуации на самом деле используется downcasting? Спасибо всем за помощь.

ответ

1

Актуальность RuntimeException в том, что она 'unchecked'. Поэтому разработчик не вынужден заниматься этим. Обычный подход к этому - проверить (используя оператор if и используя что-то вроде instanceOf), чтобы увидеть, разрешено ли бросить, прежде чем разрешить трансляцию.

Так,

if(subObj2 instanceof SubObject) { 
    SubObject s2 = (SubObject) obj2; 
    ... 
} 

Однако, это считается «код запах» - то есть то, что является необычным и который звонит тревогу в сознании старших разработчиков. Как правило, вы должны добиваться такого рода через полиморфизм, хотя это не всегда возможно или желательно. Для большинства типов программ тип литья не должен быть необходим большую часть времени.

Однако ваше мышление в целом правильное.

0

A Ситуация, в которой может случиться Downcasting, находится в контексте шаблона проектирования завода. В этом шаблоне проектирования детали реализации нескольких дочерних классов можно абстрагировать, просто используя их родительский класс.

Рассмотрим следующий пример:

import java.util.ArrayList; 

public class Factory { 

private ArrayList<Product> products = new ArrayList<Product>(); 

public static void main(String[] args){ 
    Factory factory = new Factory(); 

    factory.addProduct(new Ball("1")); 
    factory.addProduct(new ToyCar("2")); 
    factory.addProduct(new Dice("3")); 

    Product popProduct = factory.popProduct(); 

    Ball downcastBall = (Ball)popProduct; 

    System.out.println(downcastBall.getId()); 
} 

public void addProduct(Product prodIn){ 
    products.add(prodIn); 
} 

public Product popProduct(){ 
    Product returnProd = products.get(0); 
    products.remove(0); 
    return returnProd; 
} 
} 

Классы Ball, ToyCar и плашек все расширить класс продукта и реализовать метод GetId() его, так что трое детей могут быть обработаны, как только продукты. Это называется полиморфизмом.

I Опубликуйте остальную часть кода, чтобы вы могли поиграть с ней.

Класс Болл:

public class Ball extends Product{ 

public Ball(String id) { 
    super(id); 
} 

public String getId(){ 
    return "ball!"; 
} 
} 

ToyCar класс:

public class ToyCar extends Product{ 

private String ToyCarId; 

public ToyCar(String id) { 
    super(id); 

} 

public String getId(){ 
    return this.ToyCarId; 
} 
} 

игральные кости Класс:

public class Dice extends Product{ 

private String diceId; 

public Dice(String id) { 
    super(id); 

} 

public String getId(){ 
    return this.diceId; 
} 
} 

И, наконец, класс продукта:

public class Product { 

private String id; 

public Product(String id){ 
    this.id = id; 
} 

public String getId(){ 
    return this.id; 
} 
}