3

I have an Operator interface for handling math operator that has two method like so:

public interface Operator
{
  double calculate(double firstNumber,double secondNumber);
  char getSign();
}

for each operator I have a class that implement Operator interface like so:

public class Plus implements Operator
{   
  public double calculate(double firstNumber,double secondNumber)
  {
     return firstNumber + secondNumber;
  }
  public char getSign()
  {
     return '+';
  }
}

And so on... In this code I use Reflections :

Reflections reflections = new Reflections("mypackage");
Set<Class<? extends Operator>> classes = reflections.getSubTypesOf(Operator.class);

Reflections is not the part of java Reflection API.I should just use java Reflection capability. Can anyone help me to change this code that only use java Reflection API?

marzie
  • 203
  • 3
  • 11
  • I don't think the Core Java API has a feature to scan the classpath for subtypes. – Thilo Aug 24 '15 at 08:37
  • My purpose is to pick correct class that implement Operator automatically Do you have a better idea? – marzie Aug 24 '15 at 08:40
  • 1
    Just use some registry (maybe a simple map) to keep track of the available math operator implementations. – Thilo Aug 24 '15 at 08:41
  • What about an enumeration? – mavroprovato Aug 24 '15 at 08:41
  • 1
    have you consider to use enums? you could define enum which extends your interface pass somehow implementations in, then all what you need to do is do `MyEnum.values()` – user902383 Aug 24 '15 at 08:42
  • Related: http://stackoverflow.com/questions/492184/how-do-you-find-all-subclasses-of-a-given-class-in-java – Thilo Aug 24 '15 at 08:50

2 Answers2

3

Instead of using the Reflections API, you can

  • search your class path for directories and JARs
    • for the directories look for each class file
    • for the JAR scan through the files for each class file
  • read the byte code of the class file with a library like ASM.
    • if the class implement your interface add it
    • otherwise check all the super classes and interfaces of the class to see if they implement the interface.

The reason you have to read the byte code is you want to avoid loading all the classes just to see the inheritance hierarchy, esp as some of the classes might not load or could take a long time.

Needless to say, using a library which does this for you is easier. If youw ant to write this yourself I suggest you read the source of the Reflections API to see how it does it.


A simpler solution is to use an enum

enum Operators implement Operator {
    PLUS {
        public double calculate(double x, double y) {
           return x + y;
        }
        public char getSign() {
           return '+';
        }
    },
    MINUS {
        public double calculate(double x, double y) {
           return x - y;
        }
        public char getSign() {
           return '-';
        }
    },
    TIMES {
        public double calculate(double x, double y) {
           return x * y;
        }
        public char getSign() {
           return '*';
        }
    },
    DIVIDE {
        public double calculate(double x, double y) {
           return x / y;
        }
        public char getSign() {
           return '/';
        }
    }
}

To get all the operators you can use

Operator[] operators = Operators.values();
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Later I use Map to handle the operator but I should change my program and remove dependency to Map . My app should have this ability to pich automatically from .class file(compiled class of Plus,Minus,...) from a folder – marzie Aug 24 '15 at 08:52
  • @marzie In that case you need to search for the package/folder for classes to load. It would help if you only put Operator(s) in that package. While expensive, you should only need to do this once. – Peter Lawrey Aug 24 '15 at 09:15
  • @ Peter Lawrey I put Operators in the same package but I don't know how to call proper class with java Reflection API – marzie Aug 24 '15 at 09:24
  • @marzie You call Class.forName(className). To work out what name to call, you need to look in the directory for that package. To find that you need to search the class path. – Peter Lawrey Aug 24 '15 at 09:34
0

You cannot scan the class path for the sub types. If you can correlate, even for JPA you would have to specify the entity names as part of configuration. Use a similar approach to specify the list of classes you like to scan through and check if the instanceof. Reflections API only can help with you in that case if not.

Karthik R
  • 5,523
  • 2
  • 18
  • 30