Эта ошибка возникает в двух вариантах:
$arr = [1, 2, 3];
Синтаксис инициализатора этого массива был введен только в PHP 5.4; это приведет к возникновению ошибки парсера в версиях до этого. Если возможно, обновите свою установку или используйте старый синтаксис:
$arr = array(1, 2, 3);
См. Также этот пример из руководства.
$suffix = explode(',', 'foo,bar')[1];
Результаты функции разыменования массива также были введены в PHP 5.4. Если обновление невозможно, вам нужно использовать временную переменную:
$parts = explode(',', 'foo,bar');
$suffix = $parts[1];
См. Также этот пример из руководства.
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.
Используя Ваш пример, Вы могли сделать:
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();
}
Я полагаю, что это относится ко всем статически типизированным языкам:
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
}
Мы можем все видеть, что код, который Вы обеспечили, не будет работать во время выполнения. Поэтому мы знаем, что выражение new A()
может никогда быть объектом типа B
.
, Но это не то, как компилятор видит его. К тому времени, когда компилятор проверяет, разрешают ли броску, это просто видит это:
variable_of_type_B = (B)expression_of_type_A;
И поскольку другие продемонстрировали, такой бросок совершенно законен. Выражение справа могло очень хорошо оценить к объекту типа B
. Компилятор видит, что A
и B
имеют отношение подтипа, таким образом, с представлением "выражения" кода, бросок мог бы работать.
компилятор не рассматривает особый случай, когда это знает точно , что будет действительно иметь тип объекта expression_of_type_A
. Это просто рассматривает статический тип как A
и полагает, что динамический тип мог быть A
или любой потомок A
, включая [1 110].
В этом случае, почему Java позволяет downcasting, если это не может быть выполнено во времени выполнения?
я полагаю, что это вызвано тем, что нет никакого пути к компилятору для знания во время компиляции, если бросок успешно выполнится или нет. Для Вашего примера просто видеть, что состав исполнителей перестанет работать, но существуют другие времена, где это не настолько ясно.
, Например, предположите, что типы B, C и D все расширяют тип A, и затем метод public A getSomeA()
возвраты экземпляр или B, C или D в зависимости от случайным образом сгенерированного числа. Компилятор не может знать, какой точный тип выполнения будет возвращен этим методом, поэтому при позже кастинге результатов к B
нет никакого способа знать, успешно выполнится ли бросок (или сбой). Поэтому компилятор должен предположить, что броски успешно выполнятся.
@ Исходный плакат - см. Встроенные комментарии.
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");
}
}