简体   繁体   中英

java - Class whose name is known at compile time and which extends other class at runtime

I wish to create an open source implementation (subclass) of a propriertary adapter (super)class. I have two distinct requirements:

  1. I need to extend the subclass at runtime, not at compile time
  2. The class name of my subclass must be known at compile time.

Use case: since the superclass has a propriertary license, I cannot include its source nor reference a prebuilt binary in my open source project's build. The actual runtime usage of my subclass will occur in proprietary, closed-source framework code. This framework will create an instance of my subclass by name. For that reason, my subclass name needs to be known in advance.

The latter issue seems to preclude approaches like cglib which create a new class name at runtime.

Example code:

package com.proprietary;
public class Adapter {}

package org.free;
public class AdapterImpl
    // com.proprietary is not available at compile time
    // extends com.proprietary.Adapter 
{}

package com.proprietary;
public class Framework {

     public static void main(String[] args) {
         // Simplified: class name is not hard-coded in reality,
         // but comes from external config
         Class c = Class.forName("org.free.AdapterImpl");
         ...
     }
}

Maybe check out ByteBuddy .

You can "make" a new class dynamically, with features that can help support your constraints:

  • Using Class.forName to load the third party proprietary class without linking to it in your code, you pass the class name as a configuration point
  • Naming strategy gives you control on the name of generated class
  • intercept( Implementation ) to insert your custom code.

Example:

Class<?> dynamicType = new ByteBuddy()
  .subclass(Class.forName(thatPeskyProprietaryClass))
  .namingStrategy(...)
  .method(ElementMatchers.named("someMethod"))
  .intercept(...)
  .make()
  .load(getClass().getClassLoader())
  .getLoaded();

You are going down the wrong rabbit hole.

First of all, this is not possible: you can't extend a class at runtime. The nature of a class is "fixed" at compile time; and then a .class file is written that contains that "nature". This can't be changed afterwards. Class C has class C; and you can't "enhance" C at runtime to say C extends D all of a sudden.

Beyond that: making a subclass only makes sense when you intend to exploit polymorphism.

Meaning:

class A { }
class B extends A {}

makes sense ... when your "client code" deals with both class names, A and B (most of the time).

So unless we are talking about some framework, where "your" objects need to extend A to allow integration in that framework, there is not much benefit from forcing your B to extend A "later on". Because as said: within your source code (compiler view) B would not be an A; so you couldn't write any code that benefits from B extending A.

So, the "closest" thing I can see here: use composition . Your class should contain a field pointing to an instance of that library class; and that instance is created using reflection .

And then your class provides a nice, clean interface to access the behavior that can be found in A.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM