2013-09-15 4 views
7

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

/** Get a list of records */ 
public ArrayList<Record> foo() throws BazException{ 

    // Create the list 
    static ArrayList<Record> records = new ArrayList<Record>(); 

    // Use MyLibrary to load a list of records from the file 
    String str = SomeoneElsesLibrary.loadData(new File("mydata.dat"), new DataLoader(){ 

     // will be called once for each record in the file 
     String processRecord(Record r){ 

      // if there's no "bar", invalid record 
      if(! r.hasField("bar")){ 
       throw new BazException(); 
      } 
      records.add(r); 
     } 
    }); 
    return records; 
} 

Очевидно, что это не работает, потому что SomeoneElsesLibrary понятия не имеет, что такое BazException есть. Я также не могу сказать processRecord() throws BazException, потому что тогда прототип больше не будет соответствовать. Я начинаю думать, что моя общая структура для этой реализации неверна. (Я оправляюсь от приступов Node.JS и должен переучиться примерно большинство шаблонов Java.) Как бы я реструктурировал свой код, чтобы сделать его более идиоматической Java?

Псевдокод в порядке, или даже просто описание. Кроме того, не чувствуйте, что вам нужно использовать анонимный внутренний класс, как я это делал в первый раз; Я просто ищу «способ Java» для этого.

+1

Не можете ли вы объявить 'BazException' как непроверенный? –

+0

Есть (хакерские) способы бросить исключения, которые не объявлены в предложении throws – Eric

+0

Есть ли в библиотеке Исключение, которое может обернуть ваше собственное, поскольку это будет «причиной»? –

ответ

1

Исключение относится к методу, может бросить его, а не к классу (SomeoneElsesLibrary) ,

Существует два типа исключений, проверенных (подтип исключения) и непроверенных (подтип RuntimeException). Проверенный должен быть явно объявлен в сигнатуре метода, который может его выбросить. Непроверенный может распространяться без объявления в сигнатуре метода и без обработки никаким блоком try/catch.

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

Вы можете обрабатывать непроверенную исключение в Foo() с помощью Try/Catch ...

public ArrayList<Record> foo(){ 
    static ArrayList<Record> records = new ArrayList<Record>(); 

    try{ 
     SomeoneElsesLibrary.loadData(...); 
    } catch (BazException be){ // you just handle the exception here 
    } 

    return records; 
} 

... или не

public ArrayList<Record> foo(){ 
    static ArrayList<Record> records = new ArrayList<Record>(); 

    // if SomeoneElsesLibrary.loadData raise the BazException 
    // it is propagated to the caller of foo() 
    SomeoneElsesLibrary.loadData(...); 

    return records; 
} 

Вместо этого проверил исключение всегда должны быть обработаны.

+0

Итак, если я брошу свое 'BazException' в вызове' loadData() ', поймайте его, а затем выбросите его снова, я смогу разрешить' foo() 'бросать' BazException'. Хорошее объяснение, спасибо большое. –

+0

Если BazException не отмечен (extends RuntimeException), он может быть напрямую передан вызывающему устройству foo(), в котором будет работать блок try/catch для его обработки. – Modestino

+0

Хорошо. Моя новая версия бросает BazRuntimeException, ловит ее, а затем бросает BazException (это уже не RuntimeException), поэтому для обработки BazException требуется что-либо, что вызывает 'foo()'. –

5

Ryan, убедитесь, что ваше BazException является расширением исключения RuntimeException (исключение без проверки), а не Exception (отмечено).

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

Для получения дополнительной информации, посмотрите на некоторую информацию о непроверенных исключений (т.е. RuntimeException или Error):

http://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html

Смежные вопросы