Java SneakyThrow of exceptions, type erasure

前端 未结 4 961
误落风尘
误落风尘 2020-11-27 19:44

Can someone explain this code?

public class SneakyThrow {


  public static void sneakyThrow(Throwable ex) {
    SneakyThrow.sneakyTh         


        
4条回答
  •  南方客
    南方客 (楼主)
    2020-11-27 20:18

    Let us look at the code below :

    public class SneakyThrow {
    
    
      public static void sneakyThrow(Throwable ex) {
        SneakyThrow.sneakyThrowInner(ex);
      }
    
      private static  T sneakyThrowInner(Throwable ex) throws T {
        throw (T) ex;
      }
    
    
    
      public static void main(String[] args) {
        SneakyThrow.sneakyThrow(new Exception());
      }
    
    
    }
    

    Let us see why is it behaving like this.

    First of all any cast to a type parameter ignored by compiler. JVM will directly cast it. So, throw (T) ex; will not be checked for type safety by compiler. But, by the time code reaches the JVM , type erasure takes place. Hence code will be like : [Note : Actual code will be byte code . Below is just to explain what type erasure does.]

    public class SneakyThrow {
    
    
        public static void sneakyThrow(Throwable ex) {
            SneakyThrow.sneakyThrowInner(ex); // Note : Throwable is checked exception but we don't mention anything here for it
        }
    
        private static  Throwable sneakyThrowInner(Throwable ex) throws Throwable {
            throw (Throwable) ex;
        }
    
    
        public static void main(String[] args) {
            SneakyThrow.sneakyThrow(new Exception());
    
        }
    
    
    }
    

    First thing to note is every thing will run smooth and no ClassCastException will be thrown as JVM is easily able to type cast ex to Throwable.

    Second thing to note here is that Compiler always forced us to catch or pass on the checked exception received. No such checks are made by JVM. Here, after we type casted, ideally , SneakyThrow.sneakyThrowInner(ex); should be forced to handle the Throwable exception but remember , the byte code of this version is reached to JVM. Hence, we somehow fooled the compiler.

    Do like this :

    public class SneakyThrow {
    
    
        public static void sneakyThrow(Throwable ex) {
            SneakyThrow.sneakyThrowInner(ex);
        }
    
        private static  T sneakyThrowInner(Throwable ex) throws T {
            throw (T) ex;
        }
    
    
        public static void main(String[] args) {
            try {
                SneakyThrow.sneakyThrow(new Exception());
            }catch (Throwable ex){
                System.out.println("Done Succesfully"); // Added to show everything runs fine
            }
        }
    
    
    }
    

    Output : Done Succesfully

提交回复
热议问题