Search code examples
javadynamiccompiler-constructionclassloader

Compile with a reference a dynamically loaded class


First suppose that I have an abstract class, let's call it AbstractClass. Suppose

public abstract AbstractClass {
    public abstract void F();
}

Suppose that I have a class, let's call it ClassA. ClassA extends AbstractClass. ClassA is saved in a folder. (It has to be loaded onto the classpath.) Now suppose that I am writing a new class within the program,

ClassB

and I want ClassB to be able to reference ClassA. Something along the lines of

public class ClassB extends AbstractClass {

    ClassA A = new ClassA();

    public void F() {
         A.F();
    }

}

Now, I have had no trouble using a class loader to get classA and use it dynamically. I have also had no problem writing a class like ClassA dynamically based on user input, compiling it within the program (using ecj.jar), and then loading it and calling methods from it.

I cannot figure out though how to reference a dynamically loaded class in a class that I am now writing and compiling dynamically. I don't know how to write the import, etc. Loading classA and putting

import classA;

into the classB.java file does not do the trick.

This is my first question on StackOverflow (long time reader), so go easy on me. Thanks in advance.

--

Context: A program that uses probability distributions entered by the user. I have an abstract class AbstractDistribution which has abstract methods for the distribution's CDF, PDF, inverse CDF, etc. So far this has worked well, dynamically writing compiling and loading distributions that extend AbstractDistribution, getting newInstance() of them and using them like any other class. However, if I have written and dynamically loaded a distribution Dist1, I want to be able to write a Dist2 that can call (for example), the PDF of Dist1.


Solution

  • Don't make B refer to A directly - make B refer to AbstractClass and take a reference to an instance in its constructor:

    public class ClassB extends AbstractClass {
    
        private final AbstractClass other;
    
        public ClassB(AbstractClass other) {
            this.other = other;
        }
    
        public void F() {
             other.F();
        }    
    }
    

    At this point you need to work out how you're going to get hold of a reference to the other instance of AbstractClass (whether it's a ClassA or something else) but it does get rid of the direct dependency.

    I'm sure there will be more exact details to work out, but if you can break the direct dependency like this, it should make the dynamic compilation aspect less of a problem.