Downcasting в Java

Ошибка анализа: синтаксическая ошибка, неожиданная '['

Эта ошибка возникает в двух вариантах:

Вариант 1

$arr = [1, 2, 3];

Синтаксис инициализатора этого массива был введен только в PHP 5.4; это приведет к возникновению ошибки парсера в версиях до этого. Если возможно, обновите свою установку или используйте старый синтаксис:

$arr = array(1, 2, 3);

См. Также этот пример из руководства.

Вариант 2

$suffix = explode(',', 'foo,bar')[1];

Результаты функции разыменования массива также были введены в PHP 5.4. Если обновление невозможно, вам нужно использовать временную переменную:

$parts = explode(',', 'foo,bar');
$suffix = $parts[1];

См. Также этот пример из руководства.

174
задан Pshemo 24 June 2014 в 12:16
поделиться

6 ответов

Downcasting разрешают, когда существует возможность, что он успешно выполняется во время выполнения:

Object o = getSomeObject(),
String s = (String) o; // this is allowed because o could reference a String

В некоторых случаях это не успешно выполнится:

Object o = new Object();
String s = (String) o; // this will fail at runtime, because o doesn't reference a String

В других это будет работать:

Object o = "a String";
String s = (String) o; // this will work, since o references a String

, Когда бросок (такой как этот последний) сбои во времени выполнения ClassCastException будут брошены.

Примечание, что некоторые броски будут запрещены во время компиляции, потому что они никогда не будут успешно выполняться вообще:

Integer i = getSomeInteger();
String s = (String) i; // the compiler will not allow this, since i can never reference a String.
288
ответ дан Joachim Sauer 23 November 2019 в 20:31
поделиться

Используя Ваш пример, Вы могли сделать:

public void doit(A a) {
    if(a instanceof B) {
        // needs to cast to B to access draw2 which isn't present in A
        // note that this is probably not a good OO-design, but that would
        // be out-of-scope for this discussion :)
        ((B)a).draw2();
    }
    a.draw();
}
16
ответ дан Rolf Rander 23 November 2019 в 20:31
поделиться

Я полагаю, что это относится ко всем статически типизированным языкам:

String s = "some string";
Object o = s; // ok
String x = o; // gives compile-time error, o is not neccessarily a string
String x = (String)o; // ok compile-time, but might give a runtime exception if o is not infact a String

преобразование типа эффективно говорит: предположите, что это - ссылка на класс броска, и используйте его как таковой. Теперь, позволяет, говорят, что o действительно Целое число, предполагая, что это - Строка, не имеет никакого смысла и даст неожиданные результаты, таким образом должна быть проверка на этапе выполнения и исключение, чтобы уведомить среду выполнения, что что-то неправильно.

В практическом применении, можно записать код, работающий над более общим классом, но бросить его к подклассу, если Вы знаете то, что разделяет его на подклассы, и потребность рассматривать его как таковой. Типичный пример переопределяет Object.equals (). Предположите, что у нас есть класс для Автомобиля:

@Override
boolean equals(Object o) {
    if(!(o instanceof Car)) return false;
    Car other = (Car)o;
    // compare this to other and return
}
15
ответ дан Charaf JRA 23 November 2019 в 20:31
поделиться

Мы можем все видеть, что код, который Вы обеспечили, не будет работать во время выполнения. Поэтому мы знаем, что выражение new A() может никогда быть объектом типа B.

, Но это не то, как компилятор видит его. К тому времени, когда компилятор проверяет, разрешают ли броску, это просто видит это:

variable_of_type_B = (B)expression_of_type_A;

И поскольку другие продемонстрировали, такой бросок совершенно законен. Выражение справа могло очень хорошо оценить к объекту типа B. Компилятор видит, что A и B имеют отношение подтипа, таким образом, с представлением "выражения" кода, бросок мог бы работать.

компилятор не рассматривает особый случай, когда это знает точно , что будет действительно иметь тип объекта expression_of_type_A. Это просто рассматривает статический тип как A и полагает, что динамический тип мог быть A или любой потомок A, включая [1 110].

5
ответ дан Rob Kennedy 23 November 2019 в 20:31
поделиться

В этом случае, почему Java позволяет downcasting, если это не может быть выполнено во времени выполнения?

я полагаю, что это вызвано тем, что нет никакого пути к компилятору для знания во время компиляции, если бросок успешно выполнится или нет. Для Вашего примера просто видеть, что состав исполнителей перестанет работать, но существуют другие времена, где это не настолько ясно.

, Например, предположите, что типы B, C и D все расширяют тип A, и затем метод public A getSomeA() возвраты экземпляр или B, C или D в зависимости от случайным образом сгенерированного числа. Компилятор не может знать, какой точный тип выполнения будет возвращен этим методом, поэтому при позже кастинге результатов к B нет никакого способа знать, успешно выполнится ли бросок (или сбой). Поэтому компилятор должен предположить, что броски успешно выполнятся.

3
ответ дан matt b 23 November 2019 в 20:31
поделиться

@ Исходный плакат - см. Встроенные комментарии.

public class demo 
{
    public static void main(String a[]) 
    {
        B b = (B) new A(); // compiles with the cast, but runtime exception - java.lang.ClassCastException 
        //- A subclass variable cannot hold a reference to a superclass  variable. so, the above statement will not work.

        //For downcast, what you need is a superclass ref containing a subclass object.
        A superClassRef = new B();//just for the sake of illustration
        B subClassRef = (B)superClassRef; // Valid downcast. 
    }
}

class A 
{
    public void draw() 
    {
        System.out.println("1");
    }

    public void draw1() 
    {
        System.out.println("2");
    }
}

class B extends A 
{
    public void draw() 
    {
        System.out.println("3");
    }

    public void draw2() 
    {
        System.out.println("4");
    }
}
2
ответ дан 23 November 2019 в 20:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: