2010-08-22 14 views
10

Jak mogę wyrzucić wyjątek z konstruktora wyliczającego? np:Jak rzucić wyjątek z konstruktora wyliczeniowego?

public enum RLoader { 
    INSTANCE; 
    private RLoader() throws IOException { 
    .... 
    } 
} 

produkuje Błąd

typ wyjątku Unhandled IOException

+6

Dlaczego chcesz to zrobić? Dla mnie to brzmi jak nadużycie koncepcji enum. Wartości enum mają być stałymi, których tworzenie nie jest zależne od niczego. Nawet jeśli z technicznego punktu widzenia mógłbyś to zrobić (rzucając niesprawdzony wyjątek zamiast sprawdzonego), sugerowałbym zmianę twojego projektu. Jeśli próbujesz zaimplementować Singleton za pomocą tego wyliczenia, lepiej jest zaimplementować go ręcznie jako normalną klasę. –

+2

Wdrażam Singleton, ale w jaki sposób wdrożenie go ręcznie jako normalnej klasy byłoby lepsze? Nadal musiałbym rzucić wyjątek od kodu wywoływanego przez statyczny inicjator. Możesz rzucić niezaznaczone wyjątki z konstruktora wyliczeniowego. – tukushan

+0

Jest coś * złośliwego * na temat wyrzucania wyjątku, jedynie przez uzyskanie dostępu do wartości wyliczeniowej. Nie tak źle, gdy jest to metoda singleton getInstance(). –

Odpowiedz

15

Ponieważ przypadki są tworzone w statycznego inicjatora, rzucić ExceptionInInitializerError zamiast.

+5

Mimo że jest to możliwe rozwiązanie, nie sądzę, że byłoby sensownie rozwiązać problem w ten sposób. –

0

Ten scenariusz nie działa.

Próbujesz rzucić sprawdzane Exception od konstruktora.

Ten konstruktor jest wywoływany przez deklarację wejścia enum INSTANCE, więc sprawdzany wyjątek nie może być obsługiwany poprawnie.

Moim zdaniem to zły styl, aby rzucić Wyjątki od konstruktora, ponieważ konstruktor zwykle nie powinien wykonywać żadnej pracy, a zwłaszcza nie tworzyć błędów.

Także jeśli chcesz rzucić IOException Zakładam, że chcesz zainicjować coś z pliku, więc powinieneś rozważyć ten artykuł na dynamic enums.

+3

Jeśli zły styl wyrzuca wyjątki z konstruktora, co zrobić, gdy jeden z argumentów do konstruktora jest nieprawidłowy i uniemożliwi działanie klasy? Wolę zawieść szybko, rzucając wyjątek, aby uzyskać znaczący ślad stosu.Biorąc to pod uwagę, zgadzam się z tobą, że OP nie powinien starać się rzucić wyjątku w konstruktorze ** enum **. –

+0

@Kirk Woll: Preferuję używanie metod fabrycznych, które zapewniają poprawność parametrów. Również skupiałem się głównie na sprawdzonych wyjątkach, RuntimeException byłby lepszym sposobem sygnalizowania błędu weryfikacji IMO. –

+2

Ekskluzywne wykorzystanie metod fabryk do tworzenia wszystkich obiektów? Och, biedny woebegotten ** nowy operator **. :) –

3

Mam przypadek, w którym chcę używać wyrażeń jako kluczy w niektórych ustawieniach klas. Baza danych będzie przechowywać wartość ciągu, co pozwoli nam zmienić stałe wyliczeniowe bez konieczności udpate bazy danych (trochę brzydki, wiem). Chciałem rzucić wyjątek runtime w konstruktorze enum jako sposób na kontrolowanie długości argumentu string, aby uniknąć trafienia w bazę danych, a następnie uzyskanie naruszenia ograniczeń, gdybym mógł go łatwo wykryć.

public enum GlobalSettingKey { 
    EXAMPLE("example"); 

    private String value; 

    private GlobalSettingKey(String value) { 
     if (value.length() > 200) { 
      throw new IllegalArgumentException("you can't do that"); 
     } 
     this.value = value; 
    } 

    @Override 
    public String toString() { 
     return value; 
    } 
} 

Kiedy stworzyliśmy szybki test na to, uważam, że wyjątek rzucony nie był mój, ale zamiast tego był ExceptionInInitializerError.

Może to głupie, ale myślę, że jest to dość poprawny scenariusz dla chcącego rzucić wyjątek w statycznym inicjalizatorze.

+2

Ale oryginalny wyjątek jest powiązany z ExceptionInInitializerError, więc jeśli wywołasz na nim "getCause()", otrzymasz oryginalny wyjątek. – shrini1000

Powiązane problemy