"Двойной кастинг"
В настоящее время я участвую в старшей школе в AP Java, и она задала мне вопрос о "двойном кастинге". Раньше я никогда не слышал об этом термине, но, видимо, ее учитель ожидает, что она узнает об этом для своего предстоящего финала.
Пример, предложенный ее преподавателем, состоял в том, что если вы хотите, чтобы Integer ввел строку, вам нужно будет сделать следующее, чтобы не получить ошибку компилятора:
Integer i = new Integer(5);
String s = (String)(Object) i;
Вопрос: когда вы хотите сделать это в реальной жизни?
Учитель представил только примеры, которые приводят к ошибке времени выполнения. Кроме того, я никогда не знал, что для этого существует термин, но это просто плохая идея, потому что есть только ошибка, когда эти два типа несовместимы.
Спасибо!
Ответы
Ответ 1
Да, я почти уверен, что ничего. Нет никакой причины, что двойное кастинг когда-либо понадобится - возможно, он может избавиться от предупреждения компиляции о небезопасном кастинге (в этом случае вы, вероятно, ошибаетесь), но в противном случае это просто не так.
Я имею в виду, есть авто toString
вызов, например. println("" + i)
, но даже тогда вам не нужно бросать объект сначала...
Изменить. После прочтения ответа Тома я внезапно не знаю об этом ответе - примитивы и (особенно) дженерики могут реально использовать это. У меня нет возможности проверить что-либо прямо сейчас, но каждый, кто читает этот ответ, должен определенно взглянуть на него (и, вероятно, увеличить его).
Я буду придерживаться строки, в которой нет никаких (или, по крайней мере, очень немногих и далеких) причин для этого, но предоставленный пример, безусловно, не имеет к этому никакого отношения.
Ответ 2
В то время как "двойное кастинг", конечно, не является общим термином, и вы не должны казаться какими-либо рекомендациями, вы должны знать, что происходит (a ClassCastException
).
Для полноты есть некоторые случаи, когда это не было бы CCE:
- Если значение действительно
null
.
- Материал, содержащий примитивы. (er, от
Object
до Integer
до [unboxing] int
или int
до [lossy] byte
до [positive] char
)
- Измените общие аргументы типа.
List<String>
до Object
до List<Integer>
.
Ответ 3
Определенно, хотя это просто предотвращает ошибки компилятора, неизбежно возникают ошибки времени выполнения. Кроме того, если два класса находятся в иерархии наследования, нет необходимости сбрасывать базовый класс и снова повышать.
Даже в вышеупомянутом вопросе, наконец, нужен API-метод для преобразования объектов.
Ответ 4
Как я узнал, в хорошем коде вы должны никогда иметь возможность кастинга, если нет другого варианта, и это явное литье введение служебных данных. toString()
- идеальное решение:
Integer i = new Integer(5);
String s = i.toString();
Ответ 5
Может быть, этот вопрос логичен? Я имею в виду, что есть метод, который вычисляет что-то (работает с целыми) и возвращает Object, а также использование метода, в котором результат выполняется для String. В общем, этот метод может быть переопределен несколько раз, такие функции были использованы до Java 1.5. Вы определяли Generic calss (но без Generics), а возврат каждого метода - Object, потому что есть несколько дочерних элементов, и каждый может возвращать собственный тип, я не знаю, но могу ответить, и двойное кастинг, подобный этому
public class Main {
public static void main(String[] args) {
AbstractToDO abstractToDO2 = new SomeToDoTwo();
String result2 = (String) abstractToDO2.toDo(); // here is second, all is good
System.out.println(result2);
AbstractToDO abstractToDO1 = new SomeToDoOne();
String result1 = (String) abstractToDO1.toDo(); // here is second, Runtime error
System.out.println(result1);
}
Object onePlusOne(){
return 1+1 +" ";
}
}
interface AbstractToDO{
Object toDo();
}
class SomeToDoOne implements AbstractToDO{
@Override
public Object toDo() {
return (Object)(1+1); // here is first casting, // we can use without (Object) casting
}
}class SomeToDoTwo implements AbstractToDO{
@Override
public Object toDo() {
return (Object)"1+1"; // here is first casting, // we can use without (Object) casting
}
}
Ответ 6
Недавно я столкнулся с этой проблемой и использовал ее. У меня есть массив объектов с 2 целыми значениями и строкой. Когда я прихожу, чтобы распаковать его, мне нужно преобразовать целые числа в двойные, чтобы сделать какое-то деление.
Проблема заключается в том, что когда я прихожу, чтобы отличать целочисленные значения, чтобы удвоить ошибки, потому что Java автоматически обнаруживает это как Integer
объект не int
примитив, и вы не можете преобразовать из Integer в double.
Поэтому решение должно использовать (double)(int)value
, прежде чем делать деление.
Итак, если вы сохраняете int как объекты и хотите преобразовать его в double для некоторого деления, java автоматически преобразует его в Integer, что делает невозможным деление.
Ответ 7
Хотя двойное кастинг может казаться избыточным в проспективном программистом, знание, по крайней мере, того, как работает синтаксис, может помочь вам понять основные действия Java.
Например:
Скажем, Animal
является суперклассом класса Dog
. И мы знаем, что класс Object
является суперклассом всех классов.
Dog d = new Dog();
Object a = d; //no errors occur
Здесь d
неявно отображается как объект Object
. Явно, это было бы Object a = (Object)d;
Как насчет здесь?
Dog d = new Dog();
Object a = (Animal)d; //no errors occur
Мы выполняем d
как объект Animal
, но компилятор неявно линяет его как объект Object
. Двойное литье.
Какая из них d
в конечном итоге лишена?
Очевидно, это будет Object a = (Object)(Animal)d;
Зная синтаксис двойного литья, мы бы знали, что d
в конечном итоге будет отличен как Object
, поэтому ошибок не будет.
Ответ 8
Реальный вариант использования:
static class Y extends X<Date> {
//some code
}
List<Y> n = new ArrayList<>();
someMethod((List<X<Date>>)(List<?>) n);
где
void someMethod(List<X<Date>>){
//some code
}