1

I'm trying to write a generic method that looks like this:

private static <T> Class<? extends T> immutableVersionOfClass(Class<T> clazz) {
    return new ByteBuddy()
            .subclass(clazz)
            .method(not(returns(VOID)))
            .intercept(to(GetterInterceptor.class))
            .method(returns(VOID))
            .intercept(to(SetterInterceptor.class))
            .make()
            .load(clazz.getClassLoader())
            .getLoaded();
}

but when final class is passed as an argument I get an exception: java.lang.IllegalArgumentException: Cannot subclass primitive, array or final types I'd like my method to be able to subclass also final classes. Is there any workaround for this problem?

k13i
  • 4,011
  • 3
  • 35
  • 63

1 Answers1

3

There is no way to subclass a final class. It's forbidden by the language spec.

ByteBuddy largely respects the language specification, so even if you wanted to extend a final class, you couldn't unless you were able to manipulate the byte code of the class you wanted to override to be not final, although at that point you're messing with things you really shouldn't be.

Makoto
  • 104,088
  • 27
  • 192
  • 230
  • 2
    That's exactly what I want to do, i.e. manipulate the byte code in order to make it non final. – k13i Aug 24 '18 at 23:17
  • In this case, you have to redefine the original class that you are subclassing. You have to do so before the class is loaded, look into Java agents for how to do so. – Rafael Winterhalter Aug 26 '18 at 20:36
  • You can say “ByteBuddy largely respects the language specification”, you could also say, ByteBuddy just catches an error early that would come anyway later on, as the JVM will reject the subclass of a final class, if you ignore the final nature of the superclass when generating the code… – Holger Aug 27 '18 at 10:12