Oto prosty przykład użycia wyjątku:
class IntegerExceptionTest {
public static void main(String[] args) {
try {
throw new IntegerException(42);
} catch (IntegerException e) {
assert e.getValue() == 42;
}
}
}
Treść instrukcji TRy zgłasza wyjątek z daną wartością, który jest przechwytywany przez klauzulę catch.
Natomiast poniższa definicja nowego wyjątku jest zabroniona, ponieważ tworzy sparametryzowany typ:
class ParametricException<T> extends Exception { // compile-time error
private final T value;
public ParametricException(T value) { this.value = value; }
public T getValue() { return value; }
}
Próba skompilowania powyższego zgłasza błąd:
% javac ParametricException.java
ParametricException.java:1: a generic class may not extend
java.lang.Throwable
class ParametricException<T> extends Exception { // compile-time error
^
1 error
To ograniczenie jest rozsądne, ponieważ prawie każda próba przechwycenia takiego wyjątku musi się nie powieść, ponieważ typu nie można ponowić. Można by się spodziewać, że typowe użycie wyjątku będzie wyglądać następująco:
class ParametricExceptionTest {
public static void main(String[] args) {
try {
throw new ParametricException<Integer>(42);
} catch (ParametricException<Integer> e) { // compile-time error
assert e.getValue()==42;
}
}
}
Jest to niedozwolone, ponieważ typu w klauzuli catch nie można ponowić. W chwili pisania tego tekstu kompilator Sun zgłasza kaskadę błędów składniowych w takim przypadku:
% javac ParametricExceptionTest.java
ParametricExceptionTest.java:5: <identifier> expected
} catch (ParametricException<Integer> e) {
^
ParametricExceptionTest.java:8: ')' expected
}
^
ParametricExceptionTest.java:9: '}' expected
}
^
3 errors
Ponieważ wyjątki nie mogą być parametryczne, składnia jest ograniczona, więc typ musi być zapisany jako identyfikator, bez następującego parametru.