Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2007.12.23;
Скачать: [xml.tar.bz2];

Вниз

Похоливарим еще? (java, checked exceptions)   Найти похожие ветки 

 
mephasm   (2007-11-16 12:14) [40]

отлов соответственно такой
catch (SAXException e)
{
 //...
}
catch (IOException e)
{
 //...
}


 
Romkin ©   (2007-11-16 12:27) [41]

mephasm   (16.11.07 12:14) [40]
Это что, способ нае... компилятора? То есть объявлено у тебя в заголовке SAXException, порождаешь ты именно его, а перехватывать надо IOException? Та вторая, я вижу, как SAXException не перехватится?
Прикольно :)


 
Юрий Зотов ©   (2007-11-16 12:50) [42]

> Сусл ©   (16.11.07 10:54) [21]

> обозначенная тобой проблема (невозможность выбросить исключение
> иного типа в потомке) является прямым следствием того, что ты очень
> много внимания уделяешь расширению поведения посредством
> наследования.

Нет , Дима, обозначенная мною проблема (невозможность выбросить исключение иного типа в потомке) является прямым следствием другого - ограничений, существующих в языке (причем ограничений, ИМХО, искусственных). Не будь этих ограничений - не было бы и никаких проблем. Хоть наследуйся, хоть агрегируйся, хоть еще что хошь делай. Пример - хоть та же Delphi.

Да, существует еще и агрегация (кстати, спасибо за совет почитать по этому поводу книжку - правда, агрегированием я пользуюсь столько же, сколько пишу компоненты, а это лет так 10, наверное - но в книжке все круто - "паттерны", панимашь...). Но согласись, что когда я проектирую архитектуру классов для решения конкретной задачи, то имею полное право юзать и наследование, и агрегацию, и их смесь и еще что угодно (что, собственно, всегда и делаю) - но при этом должен исходить из самой задачи, из эффективности и удобства ее решения, простоты расширения и сопровождения - и т.д. Но уж никак не из ограничений, существующих в том или ином языке.

Что бы я хотел видеть? Вот что.

1. Соглашение о том, что любой метод может выбросить любое исключение.

2. Требование компилятора о том, что все реально выбрасываемые методом исключения должны декларироваться в его заголовке (как оно сейчас и есть).

3. При замещении метода его заголовок наследуется, но кроме списка реально выбрасываемых исключений (который в потомке имеет право быть и таким же, и другим, но в любом случае должен удовлетворять п.2).

И все проблемы сняты. И с документированностью тоже все ОК. Чем плохо?


 
Игорь Шевченко ©   (2007-11-16 12:52) [43]


> при этом должен исходить из самой задачи, из эффективности
> и удобства ее решения, простоты расширения и сопровождения
> - и т.д. Но уж никак не из ограничений, существующих в том
> или ином языке.


Юра, тебе не кажется, что две части этой фразы противоречат друг другу ?


 
Romkin ©   (2007-11-16 12:53) [44]


> 3. При замещении метода его заголовок наследуется, но кроме
> списка реально выбрасываемых исключений (который в потомке
> имеет право быть и таким же, и другим, но в любом случае
> должен удовлетворять п.2). И все проблемы сняты. И с документированностью
> тоже все ОК. Чем плохо?

Хм. Вот пользуешь ты где-то предка, метод его вызываешь, исключения перехватываешь. А вместо него приходит потомок, с другим списком исключений. И куда деваться?


 
Юрий Зотов ©   (2007-11-16 13:07) [45]

> mephasm   (16.11.07 12:10) [38]

>...
>catch (IOException e)
>{
> throw new SAXException("I/O error: " + e.toString(), e);
>}

Спасибо, но приделывать костыли я тоже умею и выше уже показал этот способ.

Однако же, задачу Вы не решили, даже и с костылями. Я не просил Вас перехватывать IOException, это задачка для младшего ясельного возраста. Я просил выкинуть IOException из перекрытого метода parse. Хоть c nested, хоть как угодно. А уж потом говорить о том, кому остается плакать.

Или не говорить совсем. А сразу начинать плакать.


 
Mystic ©   (2007-11-16 13:08) [46]

> Игорь Шевченко ©   (16.11.07 11:20) [34]

Автор = ?


 
Игорь Шевченко ©   (2007-11-16 13:10) [47]

Mystic ©   (16.11.07 13:08) [46]

Автор - Эрик Рэймонд, "Искусство программирования для Unix"


 
Юрий Зотов ©   (2007-11-16 13:14) [48]

> Romkin ©   (16.11.07 12:53) [44]

> Вот пользуешь ты где-то предка, метод его вызываешь, исключения
> перехватываешь. А вместо него приходит потомок, с другим списком
> исключений. И куда деваться?

Хм... девствит-но... значит надо изменить формулировку: список исключений методом-потомком тоже наследуется, но может им расширяться.


 
Игорь Шевченко ©   (2007-11-16 13:16) [49]

Юрий Зотов ©   (16.11.07 13:14) [48]


> значит надо изменить формулировку: список исключений методом-
> потомком тоже наследуется, но может им расширяться.


То есть, работать с классом, как с предком, не имея представления о том, каким по счету потомком он является, в таком аксепте не выйдет ?


 
mephasm   (2007-11-16 13:25) [50]

Юрий Зотов ©   (16.11.07 13:07) [45]

Возможно вы немного меня не поняли.
Посмотрите повнимательнее откуда выбрасывается IOException.
Этот метод реализует SAXHandler, который выбрасывает SAXException.

public void startElement (String name, AttributeList attrs)
throws SAXException {

Если вы выбросите из него NestedException то оно пролетит через метод parse.
Даже не нужно ничего перегружать.


 
Romkin ©   (2007-11-16 13:43) [51]

Юрий Зотов ©   (16.11.07 13:14) [48]

> Хм... девствит-но... значит надо изменить формулировку:
> список исключений методом-потомком тоже наследуется, но
> может им расширяться

А разница-то какая? Ну появилось новое исключение, что, там, где вызывается метод предка, его знать будут?


 
Romkin ©   (2007-11-16 13:45) [52]


> public void startElement (String name, AttributeList attrs)throws
> SAXException {Если вы выбросите из него NestedException
> то оно пролетит через метод parse.Даже не нужно ничего перегружать.
>

То есть, получается, как в Delphi. Вопрос: зачем тогда java требует писать список эксепшенов, если все равно можно сделать "пролет"?


 
Petr V. Abramov ©   (2007-11-16 13:46) [53]

> Юрий Зотов ©   (16.11.07 13:14) [48]
> список исключений методом-потомком тоже наследуется, но может им расширяться.
а если я в наследнике какое-то исключение глушу, то может и сужаться.


 
mephasm   (2007-11-16 13:59) [54]

Romkin ©   (16.11.07 13:45) [52]

>То есть, получается, как в Delphi. Вопрос: зачем тогда java требует писать список эксепшенов, если все равно можно сделать "пролет"?

Вопрос был в том, можно ли это сделать в принципе или нет.
Видимо, декларации требуются для красоты.

Any Exception that can be thrown by a method is part of the method"s public programming interface. Those who call a method must know about the exceptions that a method can throw so that they can decide what to do about them. These exceptions are as much a part of that method"s programming interface as its parameters and return value.

Но если вы делаете пролет, то ведь вы знаете, что пролетит, правда?


 
Сусл ©   (2007-11-16 14:15) [55]


> These exceptions are as much a part of that method"s programming
> interface as its parameters and return value.

офигеть, я в посте [17] почти тоже самое сказал :)

По моему мнению throws ничем не отличается по вкладу в документацию от списка параметров, скажем.

да... как будто я java придумал! :)


 
Romkin ©   (2007-11-16 14:21) [56]

mephasm   (16.11.07 13:59) [54]

> Вопрос был в том, можно ли это сделать в принципе или нет.
> Видимо, декларации требуются для красоты.

Да не может такого быть, чтобы для красоты!
Сам же указываешь: Those who call a method must know about the exceptions that a method can throw so that they can decide what to do about them.
А тут, если я не ошибся, ты показал, что метод легко может выбросить под видом описанного исключения другое. И перехват, как я понял, надо делать именно этого другого исключения, как объявленное оно не перехватиться, я правильно понял?
Но тогда, получается, что тот, кто вызывает метод, может получить информацию о том, какие именно исключения выбрасываются, не из заголовка метода, но только каким-то другим способом, из документации, исходников этого метода, вербально от создателя?

То есть, правильно ли я понял, что в твоем варианте в [38], если будет переопределено IOException:
catch (IOException e)
{
throw new SAXException("I/O error: " + e.toString(), e);
}
то в [40] оно поймается именно как IOException, в блоке
catch (IOException e)
{
//...
}

но не выше, где catch SAXException?


 
mephasm   (2007-11-16 14:25) [57]

Romkin ©   (16.11.07 14:21) [56]

Угу. Только вы сами создаете Handler и сами выбрасываете из него IOExcepiton.
Парсер ничего об этом не знает. Все под контролем.
Если вы написали хандлер, а исключения поручили перехватывать другому программисту, то да, остается тихо умереть в сторонке.


 
Romkin ©   (2007-11-16 14:30) [58]


> Если вы написали хандлер, а исключения поручили перехватывать
> другому программисту, то да, остается тихо умереть в сторонке.
>

Перефразирую... Если я написал потомка, в его методе сделал этот хандлер, а другой программист юзает предка либо опирается на объявление моего класса (а я забыл сказать, например, что я это сделал), и у него нет catch IOException, то что случится в случае его возникновения?


 
mephasm   (2007-11-16 14:37) [59]

Romkin ©   (16.11.07 14:30) [58]

Не совсем ясно, что вы имеете в виду.
Если вы написали потомка парсера, то ему должно быть безразлично, что выбрасывает SAXHandler. Так как метод parse выбрасывает общий SAXException, то к этому методу нет ни каких претензий. Вы в переопределенной версии этого метода можете конечно перехватывать IOException, но это будет только сужение набора выбрасываемых исключений, а никак не расширение.

Если вы написали потомка хандлера, добавив выброс еще какого-нибудь исключения, и используете его в том месте, где нужно использовать родителя, то да, в логе у вас появится это самое исключение. Но вы это конечно заметите и исправите.


 
Romkin ©   (2007-11-16 14:49) [60]

mephasm   (16.11.07 14:37) [59]

> Если вы написали потомка хандлера, добавив выброс еще какого-
> нибудь исключения, и используете его в том месте, где нужно
> использовать родителя, то да, в логе у вас появится это
> самое исключение. Но вы это конечно заметите и исправите.
>

А, в логе. Это я и спрашивал. Что будет, если исключение не перехватить. То есть, оно мирно всплывает на самый верх.
Правда, маленькое замечание: править придется то место, где используется родитель, добавив перехват исключения. Похоже, на подобное и намекал Зотов, затевая топик.
То есть, если есть какой-то код, использующий предка, а я пишу потомка, перекрывая метод, то использовать nested exception я не могу, поскольку точно знаю, что не перехватят, так ведь?


 
kaif ©   (2007-11-16 14:52) [61]

Я считаю, что любое принуждение приводит рано или поздно к одному - к обману. Требование обработать исключение приводит к тому, что нерадивый программист его в большинстве случаев просто подавляет, что еще хуже, чем если бы он его вообще никак не обработал - тогда его бы поймал обработчик верхнего уровня (как это сделано в Delphi), а пользователь вместо того чтобы недоумевать и гадать, "а что произошло с моей попыткой, например, соединиться с базой данных?" увидел бы хоть какое-то сообщение об ошибке, говорящее хотя бы о том, что ошибка все же здесь произошла.
Дело даже не в наследовании классов.
Вообще такой подход наводит меня на мысль о том, что у Джавы есть проблемы с архитектурой, скорее всего в части сборки мусора. Не удивлюсь, если выяснится, что сие сомнительное благо было лишь не очень изящным способом решить собственные архитектурные недочеты в идеологии Джава-машины.


 
Romkin ©   (2007-11-16 15:00) [62]


> Я считаю, что любое принуждение приводит рано или поздно
> к одному - к обману.

Ну нет. Ограничения и принуждения нужны. Они полезны и позволяют избежать ошибок.
Вот только:
1. Они должны быть разумными, и не ограничивать возможности
2. Из них не должно быть исключений.
Например, принуждение к тому, чтобы каждое имя было описано и объявлено до использования. Разумно же? И не ограничивает в использовании: только опиши.
А тут - вроде нельзя выбросить необъявленное исключение, но если очень хочется...


 
mephasm   (2007-11-16 15:03) [63]

Romkin ©   (16.11.07 14:49) [60]

А вы знаете какой-то подход, которым можно решить эту проблему в принципе?


 
Petr V. Abramov ©   (2007-11-16 15:04) [64]

> kaif ©   (16.11.07 14:52) [61]
с архитектурой машины все нормально.
а указанная проблема, я думаю, возникла как и большинство других в этом мире: хотели, как лучше (задокументировать поднимаемые исключения), а получилось, как всегда (см. [0])


 
Petr V. Abramov ©   (2007-11-16 15:07) [65]

> mephasm   (16.11.07 15:03) [63]
достаточно у наследника разрешить менять throws


 
mephasm   (2007-11-16 15:07) [66]

Petr V. Abramov ©   (16.11.07 15:07) [65]

Уже говорилось, что его нельзя будет замаскировать под предка.


 
Petr V. Abramov ©   (2007-11-16 15:12) [67]

> mephasm   (16.11.07 15:07) [66]
где? суть не понял


 
Romkin ©   (2007-11-16 15:16) [68]

Petr V. Abramov ©   (16.11.07 15:07) [65]

> достаточно у наследника разрешить менять throws

Еще один. в [38] и [40] тебе показали, фактически, как возбуждать исключение, которого нет в заголовке метода.
А смысл? Тот, кто юзает предка, ничего нафиг о потомке не знал. И не перехватывает он их!

mephasm   (16.11.07 15:03) [63]

> А вы знаете какой-то подход, которым можно решить эту проблему
> в принципе?

Сначала нужно установить, есть ли здесь проблема :)
Сейчас я понял только, что требование "Any Exception that can be thrown by a method is part of the method"s public programming interface. Those who call a method must know about the exceptions that a method can throw so that they can decide what to do about them." можно обойти довольно легко и легитимно, с помощью механизма nested exception.
Но все дело в том, что, например, Delphi вполне нормально существует и без этого требования.
А что мешает в java просто перехватывать все все сообщения на самом верхнем уровне?


 
mephasm   (2007-11-16 15:18) [69]

Petr V. Abramov ©   (16.11.07 15:12) [67]

Если мы используем наследника в обличии предка, то такой поступок аналогичен выбросу NestedException, так как у предка выбрасываемое исключение незадекларированно.
Но NestedException мы используем между разнородными слоями, его выброс не затрагивает один из слоев, оно возвращается в тот слой, откуда выбрасывалось.
Этот слой о нем осведомлен.


 
mephasm   (2007-11-16 15:23) [70]

Romkin ©   (16.11.07 15:16) [68]

>А что мешает в java просто перехватывать все все сообщения на самом верхнем уровне?

Ничто. Вы можете написать контейнер, который будет это делать.


 
Romkin ©   (2007-11-16 15:36) [71]

mephasm   (16.11.07 15:23) [70]

> Ничто. Вы можете написать контейнер, который будет это делать.

Тогда почему бы не предположить следующее: переводим требование об объявлении exception в заголовке метода в рекомендацию, пусть варнинг выдается, а не ошибка.
Тогда и никаких nested exception не понадобиться, и переопределять exception не надо.
Фактически, все эксепшены будут работать как рантайм, которые уже есть.
Какие здесь подводные камни?


 
Petr V. Abramov ©   (2007-11-16 15:38) [72]

> mephasm   (16.11.07 15:23) [70]

Romkin ©   (16.11.07 15:16) [68]
> А смысл? Тот, кто юзает предка, ничего нафиг о потомке не знал.
ну и что? Смысл throws - задокументировать исключения или какой другой? Throws предка несет информацию о том, что ПРЕДОК возбуждает такие-то исключения, а потомки - что угодно. В чем проблема?

> mephasm   (16.11.07 15:23) [70]
> Вы можете написать контейнер, который будет это делать.
как их поднять-то в наследниках, чтоб до контейнера дошли?


 
mephasm   (2007-11-16 15:44) [73]

Romkin ©   (16.11.07 15:36) [71]

Это не решить проблему с незадекларированными исключениями потомков.

Petr V. Abramov ©   (16.11.07 15:38) [72]
>как их поднять-то в наследниках, чтоб до контейнера дошли?
Использовать базовый Exception в декларации throw всех ваших методов.


 
Romkin ©   (2007-11-16 15:46) [74]


> Это не решить проблему с незадекларированными исключениями
> потомков.

Да и не надо, ее нет :) Delphi же живет с этим, и ничего. Или особенности есть?


 
mephasm   (2007-11-16 15:51) [75]

Ну вот, похоливарили :)


 
Romkin ©   (2007-11-16 15:53) [76]

Да уж :)))


 
Petr V. Abramov ©   (2007-11-16 15:57) [77]

> Использовать базовый Exception в декларации throw всех ваших методов.
и получить орден от индусского правительства за такое кол-во дополнительных строк кода :)


 
Romkin ©   (2007-11-16 16:01) [78]


> > Использовать базовый Exception в декларации throw всех
> ваших методов.и получить орден от индусского правительства
> за такое кол-во дополнительных строк кода :)

Да не надо ничего использовать. Показали же уже, что ограничение на исключения в заголове метода легко обходится. Оно просто не действует, было бы желание.


 
iZEN ©   (2007-11-16 20:20) [79]


> Romkin ©   (16.11.07 16:01) [78]
>
>
> > > Использовать базовый Exception в декларации throw всех
> > ваших методов.и получить орден от индусского правительства
> > за такое кол-во дополнительных строк кода :)
>
> Да не надо ничего использовать. Показали же уже, что ограничение
> на исключения в заголове метода легко обходится. Оно просто
> не действует, было бы желание.


public class A {
  public void startElement(String name, AttributeList attrs) throws SAXException {
       try {
           if (name.equals("SCHEDULE")) {
               this.ParseStartSchedule(attrs);
               return;
           }
           return;
       } catch (IOException e) {
           throw new SAXException("I/O error: " + e.toString(), e);
       } catch (ScheduleParseException e) {
           throw new SAXException("ScheduleParseError" + e.toString(), e);
       }
   }
...
}


Это не "обход". Проверяемое исключение SAXException всё же бросается. Компилятор пропустит этот код как валидный — контракт базового класса соблюдён.

А что было бы, если бы метод startElement был перегружен в потомке и в него долбавили бы throws IOException:

public class B extends A {
  public void startElement(String name, AttributeList attrs) throws SAXException, IOException {
     ...
  }
...
}

Тогда ранее написанный класс, использующий объект базового класса A, не смог бы вызвать полиморфно метод объекта класса B только из-за того, что сигнатуры методов РАЗНЫЕ. (Компилятор включает в сигнатуру методов информацию  о checked exceptions). Вообще же, javac выдаст ошибку при компиляции класса B:

/path/to/B.java:29: parseString(java.lang.String, AttributeList) in B cannot override parseString(java.lang.String, AttributeList) in A; overridden method does not throw java.io.IOException.

то есть использовать класс B и объекты в давно написанной программе, в которой определён класс A, будет невозможно. Программист класса A жёстко определил, какие исключения может бросать метод parseString и все перегруженные методы в будущих потомках класса A.

Чтобы "добавить" ещё одно проверяемое исключение программисту класса B, ему можно идти двумя путями:

1) Объявить потомка класса SAXException, например, IOSAXException и бросать экземпляр потомка:
throw new IOSAXException();

либо

2) "Завернуть" IOException в SAXException и бросить:
throw new SAXException("I/O error: " + e.toString(), e);
как уже было показано выше.

Контракт на полиморфные вызовы не нарушен. Программисты могут спать спокойно.


 
iZEN ©   (2007-11-16 20:22) [80]

Извиняюсь

/path/to/B.java:29: parseString(java.lang.String, AttributeList) in B cannot override parseString(java.lang.String, AttributeList) in A; overridden method does not throw java.io.IOException.

следует читать как:

/path/to/B.java:29: startElement(java.lang.String, AttributeList) in B cannot override parseString(java.lang.String, AttributeList) in A; overridden method does not throw java.io.IOException.



Страницы: 1 2 3 4 5 6 вся ветка

Форум: "Прочее";
Текущий архив: 2007.12.23;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.64 MB
Время: 0.063 c
15-1195739912
alsov
2007-11-22 16:58
2007.12.23
Сборка серверой части приложения на Oracle


2-1196315820
ryden
2007-11-29 08:57
2007.12.23
проблема с MDI приложением


15-1195736888
Denis__
2007-11-22 16:08
2007.12.23
Лукьяненко


15-1195559648
xayam
2007-11-20 14:54
2007.12.23
Что мне не нравится в BDS/RAD Studio?


15-1195852567
Evanescence
2007-11-24 00:16
2007.12.23
как в php-nuke 8 заменить динамические адреса на статические?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский