Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I Throw or Catch Instances of a Generic Class in java?

Tags:

java

generics

I know that I can't throw or catch instances of generic class in Java,for example ,the following code compiles wrongly:

public static <T extends Throwable> void test(Class<T> t){
    try{
        //do work
    }
    catch (T e){// ERROR--can't catch type variable
    Logger.global.info(...)
    }
}

Would anyone can explain the exactly reason for Java to forbidden throw or catch instances of generic class?

like image 485
J.zhou Avatar asked Nov 14 '15 08:11

J.zhou


2 Answers

You can't catch a generic exception, because the Java Language Specification explicitly forbids it. In 14.20 The try statement it says:

It is a compile-time error if a type variable is used in the denotation of the type of an exception parameter.

The section does not explain why, but the most like reason is that <T extends Throwable> is erased to Throwable, so your code would actually be compiled as if it was:

public static void test(Class<? extends Throwable> t){
    try{
        //do work
    }
    catch (Throwable e){
    Logger.global.info(...)
    }
}

This is not the intent expressed by your code (and very likely not what you want), therefor the language specification explicitly forbids it.

Note that throwing generic exceptions is allowed, but this is usually only relevant in the context of having some wrapper around another method that throws the exception.

like image 55
Mark Rotteveel Avatar answered Sep 29 '22 08:09

Mark Rotteveel


You can not do this because the 'generic type erasure'. The generic information is lost after the compile time, after generate the bytecode class file there are not any generic information and at compile time you have not specified the concrete type for generic T.

See this code for type erasure check, the result is Equal:

A

package a;


public class A {

    public static void main(String[] args) {

        final B<String, Integer> b = new B<String, Integer>();

        b.check();
    }

}

B

package a;

import java.util.ArrayList;
import java.util.List;

public class B<T, E> {

    public void check(){

        final List<T> listT = new ArrayList<T>();
        final List<E> listE = new ArrayList<E>();

        if (listT.getClass().equals(listE.getClass())) {
            System.out.println("Equal");
        }
    }

}

See this link too: http://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#cannotCatch

like image 43
Francisco Hernandez Avatar answered Sep 29 '22 08:09

Francisco Hernandez