views:

179

answers:

3

Hi all. I am implementing a sort of ORM in Java. I am trying to do a static find method that is only in the parent class. Let me get to the point:

public class DB {
  public static Object find (int id) {
    // i want to return anew instance of the calling subclass
  }
}

public class Item extends DB {
  // nothing here
}

public class Test {
  public static void main () {
    Item i = (Item) Item.find(2);
    ...
  }
}

I don't know how to have the find method know which of its inherited class is calling it, so that i can return the right instance (and maybe call the right constructor, etc.) And the inherited class could be anything, no limit.

I've tried stacktrace, but it's only traced from Test to DB.

Any ideas?

Thank you everyone!

+1  A: 

Static methods are not inherited, so you can't do this. A common approach to this problem (not including using one of tons of available ORM solutions) is to split your class hierarchy into two:

  • "Entity" (e.g. classes representing your actual data)
  • and "DAO" (Data Access Object) - classes that contain methods to manipulate data persistence.
ChssPly76
A: 

I think you may find the "Generic DAO" article at IBM developerworks useful.

Short: use Generics wisely.

BalusC
A: 

A word to the wise: It's probably a bad idea to try and implement your own ORM. Projects like hibernate have covered this task in great detail, so if you roll your own you are likely to reinvent the wheel and possibly attempt to solve problems that have already been solved.

More on topic, ChssPly76 is correct in that you cannot accomplish this because of how static methods are handled in Java. When the VM loads the bytecode for the static method invocation, it will perform a lookup to find where the method actually is located. It won't find it on the Item class, so it will instead bind the call to DB.find.

However! It may be possible to achieve what you are trying to do with some bytecode wrangling. Viewing the bytecode (using javap -c) for the static method call in your example, we get the following:

invokestatic Method Item.find:(I)Ljava/lang/Object

Thus, once your call reaches DB.find, you could follow the stacktrace back to the callsite, and then inspect the bytecode at the callsite to retrive the actual target of the call. In theory, anyway, as I haven't seen this myself in practice. Also, beware of hacking bytecode like this, for here be dragons.

Kudos for identifying the active record pattern, and wanting to use it in Java. I do agree it's a design pattern that makes more sense than most DB access patterns found in Java, and it's one of the strengths of Ruby and PHP.

toluju
yes, it makes me appreciate activerecord a lot more! thanks for the insight on the bytecode, that's hardcore! it was very interesting to see that.
mooman