Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Am I abusing/misusing Java reflection?

I'm writing a program to read data from a file, which may be in one of several format (different versions of the same format, actually) and I'm using reflection for calling the appropriate function for each format. Assuming that file format is a number specified on the first byte of the file:

Class DataFile extends Model {
...
Blob file
...
public void parse() throws Exception{

    InputStream is = file.get();

    Class c = Class.forName("models.DataFile");
    Method m = c.getMethod("parse_v"+is.read(), (Class []) null);
    m.invoke(this, (Object []) null);
}

public void parse_v0() throws Exception{
   ...
}

public void parse_v1() throws Exception{
   ...
}
}

My question is, am I abusing/misusing reflection? I have the feeling that I should be using inheritance and create a different class for each file type with its own "parse" procedure, but I don't know the file type until I start parsing... and then I cannot "downcast" and just use something like ((DataFile_v1) this).parse() so I am a little lost.

Thank you for your time!

like image 633
Johan B. Avatar asked Aug 04 '11 15:08

Johan B.


2 Answers

There's nothing fundamentally wrong with this, but a more flexible and extensible way to do the same thing would be to use the version information as a key in a Map, and have the values in the Map be handler objects. Then any code can register a handler (the handlers can all implement a common interface) and your reader code can just look up the handler in the Map and invoke it.

Be sure to handle the case where the Map doesn't include a handler for a particular version!

like image 161
Ernest Friedman-Hill Avatar answered Sep 18 '22 23:09

Ernest Friedman-Hill


If you make a DataFile interface define a parse method, and implement the interface with multiple classes (DataFile_v1, etc.), then the calling code doesn't have to know which implementation was chosen.

DataFile dataFile = dataFileFactory.getForVersion(is.read());
dataFile.parse(file);

I'd argue that this is a better approach from a general design perspective. However, at some point you will need to create some kind of mapping between the version number and the DataFile implementations. (In this case I'm doing it in an imaginary dataFileFactory.) You'll have to determine whether it would be more appropriate to select an implementation using reflection or some other method.

like image 27
StriplingWarrior Avatar answered Sep 19 '22 23:09

StriplingWarrior