Подтвердить что ты не робот

"Двойной кастинг"

В настоящее время я участвую в старшей школе в AP Java, и она задала мне вопрос о "двойном кастинге". Раньше я никогда не слышал об этом термине, но, видимо, ее учитель ожидает, что она узнает об этом для своего предстоящего финала.

Пример, предложенный ее преподавателем, состоял в том, что если вы хотите, чтобы Integer ввел строку, вам нужно будет сделать следующее, чтобы не получить ошибку компилятора:

Integer i = new Integer(5);
String s = (String)(Object) i;

Вопрос: когда вы хотите сделать это в реальной жизни?

Учитель представил только примеры, которые приводят к ошибке времени выполнения. Кроме того, я никогда не знал, что для этого существует термин, но это просто плохая идея, потому что есть только ошибка, когда эти два типа несовместимы.

Спасибо!

4b9b3361

Ответ 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
}