powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / В каких случаях компилятор (не)может увидеть неправильный downcast типов ?
16 сообщений из 16, страница 1 из 1
В каких случаях компилятор (не)может увидеть неправильный downcast типов ?
    #38250924
ozzmosis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте.

Дано: класс-родитель и класс-наследник. В методе класса-наследника идёт "очевидно-неправильная" попытка приведения типа (downcasting):
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
class Base {}
class Derv extends Base {
  void doIt( Base b) {
    System.out.println("Intro with object of class="+b.getClass().getName()+", hash="+b.hashCode());
    Derv y = (Derv)b; // прокатит на компиляции, но вывалится в рантайме
  }
}
class CastTesting {
  public static void main(String[] a) { new Derv().doIt( new Base() ); }
}


Этот код, однако, компилится без проблем.
Ошибка возникает только в рантайме:

Код: plaintext
1.
2.
3.
4.
5.
D:\JAVA\>java CastTesting
Intro with object of class=Base, hash=11077203
Exception in thread "main" java.lang.ClassCastException: Base cannot be cast to Derv
        at Derv.doIt(CastTesting.java:5)
        at CastTesting.main(CastTesting.java:9)

Так вот, вопросик у мну такой: компилятор разве не может засечь эту неверную попытку приведения типов ?
...
Рейтинг: 0 / 0
В каких случаях компилятор (не)может увидеть неправильный downcast типов ?
    #38250929
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нет, такое приведение он отследить не может. Ведь Derv это наследник Base. Поэтому переменная b может ссылаться как на экземпляр Base так и на Derv. Сканирование всех возможных маршрутов рантайма для вычисления возможного значения какой-то переменной, это как-то уж слишком.
Компилятор умеет обнаруживаь ситуации, когда переменная и класс кастинга из совсем разных иерархий. А так как множественного наследования классов нет, то переменная не может содержать в себе экземпляр из другой иерархии.
...
Рейтинг: 0 / 0
В каких случаях компилятор (не)может увидеть неправильный downcast типов ?
    #38250939
ozzmosis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
хм... досадно, конечно :(
с формальным параметром метода - ладно, всё ясно.
Но он не "видит" бредятину еще и вот тут:
Код: java
1.
2.
3.
4.
5.
6.
7.
class Base {}
class Derv extends Base {}
class CastTesting {
  public static void main(String[] a) {
    Derv y = (Derv)new Base(); // это уже не формальный параметр, тут сразу вроде бы всё определяется
  }
}
...
Рейтинг: 0 / 0
В каких случаях компилятор (не)может увидеть неправильный downcast типов ?
    #38250953
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ozzmosisНо он не "видит" бредятину еще и вот тут:

Компилятор вычисляет только примитивы и строки. Base.<init> это, грубо говоря, метод возращающий тип Base, который может ссылаться и на Derv.
Для выявления подобных проблем есть масса анализаторов кода. FindBugs, Sonar и пр.
...
Рейтинг: 0 / 0
В каких случаях компилятор (не)может увидеть неправильный downcast типов ?
    #38425892
ozzmosis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
BlazkowiczКомпилятор умеет обнаруживаь ситуации, когда переменная и класс кастинга из совсем разных иерархий .Всё-таки подниму тему. Ибо логику компилятора осилить не в состоянии до сих пор .
Вот этот пример:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
interface Flyable { public void fly(); }
class Animal {}
class Bird { // no "extends", no "implements" here!
  public static void main(String[] args) {
    // -!- Animal b1 = (Animal) new Bird();  // inconvertible types
    // -!- Flyable b2 = new Bird(); // incompatible types
    // compiles OK but ClassCastException in runtime.
    // Why does it COMPILES ??
    Flyable b3 = (Flyable) new Bird(); 
  }
}

- компилируется ОК, но вываливает в рантайме CCE.
Что мешает компилятору послать нахрен этот код ? Здесь в наглую делается downcast к интерфейсу, который НЕ реализован классом Bird!
Спотыкаюсь на этой фишке уже надцатый раз, блин... :-/
...
Рейтинг: 0 / 0
В каких случаях компилятор (не)может увидеть неправильный downcast типов ?
    #38425896
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ozzmosis, вопрос интересный и провокационный. Наверное ответ лежит в том
что компиллятор на какой-то фазе (opcodes) сознательно не делает проверки.
...
Рейтинг: 0 / 0
В каких случаях компилятор (не)может увидеть неправильный downcast типов ?
    #38425903
ozzmosis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
maytonozzmosis, вопрос интересный и провокационный . Наверное ответ лежит в том
что компиллятор на какой-то фазе (opcodes) сознательно не делает проверки.Нет, я далёк мыслей на тему "трололо" :)
Я не могу понять логику его работы вот именно в этом вопросе. Почему он не отсекает практически очевидные ляпы.
...
Рейтинг: 0 / 0
В каких случаях компилятор (не)может увидеть неправильный downcast типов ?
    #38425928
ozzmosis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
PS. Если с помощью междуморда можно скомпилировать кастинг совсем несвязанных классов, то через общий класс-предок можно сделать почти то же самое: прикастовать др. к др. классы, являющиеся собратьями (siblings) в иерархии, но также не связанные друг с другом. См. Рыбу и Птицу ниже:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
class Test {
  // case-1:
  static interface Rollable { public void Roll(); }
  static class Tank{ }
  static class Ship{ }
  //..................
  // case-2:
  static class Animal {}
  static class Bird extends Animal {}
  static class Fish extends Animal{}
  public static void main(String[] args) {

    // test-1: compiles OK, CCE in runtime:
    Ship v = (Ship) (Rollable) new Tank();

    // test-2: compiles OK, CCE in runtime:
    Fish f = (Fish) (Animal) new Bird();
  }
}


В общем, весело. Запоминать эту особенность - в лом, да и бестолку. Ибо понимания нет, почему так происходит.
...
Рейтинг: 0 / 0
В каких случаях компилятор (не)может увидеть неправильный downcast типов ?
    #38425943
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я переписал исходник немножко по другому правда пришлось добавить
пометку что main отбрасывает classCastException.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
public class Animal {

    public static void main(String[] args) throws Exception{
        // -!- Animal b1 = (Animal) new Bird();  // inconvertible types
        // -!- Flyable b2 = new Bird(); // incompatible types
        // compiles OK but ClassCastException in runtime.
        // Why does it COMPILES ??
        Flyable b3 = (Flyable) Class.forName("Bird").newInstance();
    }

}


И мне кажется что мой пример более общо отображает смысл создания объекта
на стеке с операцией последующего кастинга. Честно я согласен с ТС что
можно ужесточить проверки на этапе компилляции но javac почему-то
более либерален и позволяет шире трактовать то что возвращает оператор new.
...
Рейтинг: 0 / 0
В каких случаях компилятор (не)может увидеть неправильный downcast типов ?
    #38425947
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, смысл еще понятнее если Class.forName("Bird").newInstance() заменить на

Код: java
1.
Class.forName(args[0]).newInstance()
...
Рейтинг: 0 / 0
В каких случаях компилятор (не)может увидеть неправильный downcast типов ?
    #38425980
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А в тривиальном случае (без кастинга) компиллятор сразу ругается.

Код: java
1.
2.
3.
4.
5.
6.
Bird.java:8: error: incompatible types
    Flyable b3 = new Bird();
                 ^
  required: Flyable
  found:    Bird
1 error



Ваш случай - одноразовый. Баг находится на первом же coverage test. Мой случай
с параметризированным кастингом на неизвестный класс - понятное дело не может
проверяться компиллятором. Здесь просто не напасёшся правил и "защит от дурака".
...
Рейтинг: 0 / 0
В каких случаях компилятор (не)может увидеть неправильный downcast типов ?
    #38426044
rfq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ozzmosisЧто мешает компилятору послать нахрен этот код ? Здесь в наглую делается downcast к интерфейсу, который НЕ реализован классом Bird!
Спотыкаюсь на этой фишке уже надцатый раз, блин... :-/
Вопрос, конечно, интересный...
Я думаю, что приведения рассматриваются компилятором как переход на ручное управление, типа программист сам берет на себя ответственность за последствия. Ну берет так берет. Может, он именно что хочет чтобы здесь всегда выбрасывалось исключение.
А насчет "надцатый" раз, то подозреваю, у вас плохо спроектирована система типов. Попробуйте использовать дженерики.
...
Рейтинг: 0 / 0
В каких случаях компилятор (не)может увидеть неправильный downcast типов ?
    #38426082
maxkar
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ozzmosisЯ не могу понять логику его работы вот именно в этом вопросе. Почему он не отсекает практически очевидные ляпы.

Потому что система типов в java достаточно простая и компилятор работает с ней слишком прямолинейно. Учитывается только compile-time тип выражения. И при этом тип X обозначает на самом деле "здесь может быть Х или любой его наследник". Так что (чисто теоретически), выражение типа "Bird" в рантайме может иметь значение FlyingBird.

Никакой дополнительной проверки вроде "здесь может быть X или любой его наследник до колена Y" в компиляторе нет. Т.е. компилятор "не знает", что в вашем примере "именно bird, а не ее наследник". Нужные проверки при желании реализуются, но это может отказаться сложно и не факт, что принесет большую пользу. Может быть, в pmd или jlint есть подобные проверки, посмотрите.

А еще компилятор умеет отлавливать ошибки в случаях, когда точно знает, что наследников не может быть. Сделайте ваш класс Bird final и посмотрите на реакцию.
...
Рейтинг: 0 / 0
В каких случаях компилятор (не)может увидеть неправильный downcast типов ?
    #38426218
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ozzmosisЧто мешает компилятору послать нахрен этот код ? Здесь в наглую делается downcast к интерфейсу, который НЕ реализован классом Bird!
Реализация компилятора это всегда баланс между временем компиляции и количеством фич и проверок.
Раскопай реализации javac и посмотри. То что компилятор отлавливает некоторые ошибки в compile time, это ещё не значит что обязан отлавливать все остальные. Возможно с интерфейсами связан какой-то особый случай.
...
Рейтинг: 0 / 0
В каких случаях компилятор (не)может увидеть неправильный downcast типов ?
    #38426275
Озверин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ozzmosisBlazkowiczКомпилятор умеет обнаруживаь ситуации, когда переменная и класс кастинга из совсем разных иерархий .Всё-таки подниму тему. Ибо логику компилятора осилить не в состоянии до сих пор .
Вот этот пример:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
interface Flyable { public void fly(); }
class Animal {}
class Bird { // no "extends", no "implements" here!
  public static void main(String[] args) {
    // -!- Animal b1 = (Animal) new Bird();  // inconvertible types
    // -!- Flyable b2 = new Bird(); // incompatible types
    // compiles OK but ClassCastException in runtime.
    // Why does it COMPILES ??
    Flyable b3 = (Flyable) new Bird(); 
  }
}

- компилируется ОК, но вываливает в рантайме CCE.
Что мешает компилятору послать нахрен этот код ? Здесь в наглую делается downcast к интерфейсу, который НЕ реализован классом Bird!
Спотыкаюсь на этой фишке уже надцатый раз, блин... :-/

мешает то, что у всех есть общий потомок - Object.
...
Рейтинг: 0 / 0
В каких случаях компилятор (не)может увидеть неправильный downcast типов ?
    #38426276
Озверин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Озверинozzmosisпропущено...
Всё-таки подниму тему. Ибо логику компилятора осилить не в состоянии до сих пор .
Вот этот пример:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
interface Flyable { public void fly(); }
class Animal {}
class Bird { // no "extends", no "implements" here!
  public static void main(String[] args) {
    // -!- Animal b1 = (Animal) new Bird();  // inconvertible types
    // -!- Flyable b2 = new Bird(); // incompatible types
    // compiles OK but ClassCastException in runtime.
    // Why does it COMPILES ??
    Flyable b3 = (Flyable) new Bird(); 
  }
}

- компилируется ОК, но вываливает в рантайме CCE.
Что мешает компилятору послать нахрен этот код ? Здесь в наглую делается downcast к интерфейсу, который НЕ реализован классом Bird!
Спотыкаюсь на этой фишке уже надцатый раз, блин... :-/

*предок

мешает то, что у всех есть общий потомок - Object.
...
Рейтинг: 0 / 0
16 сообщений из 16, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / В каких случаях компилятор (не)может увидеть неправильный downcast типов ?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]