Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simulate static abstract and dynamic linking on static method call in Java

Tags:

Introduction

As a disclaimer, I'v read Why can't static methods be abstract in Java and, even if I respectfully disagree with the accepted answer about a "logical contradiction", I don't want any answer about the usefulness of static abstract just an answer to my question ;)

I have a class hierarchy representing some tables from a database. Each class inherits the Entity class which contains a lot of utility methods for accessing the database, creating queries, escaping characters, etc.

Each instance of a class is a row from the database.

The problem

Now, in order to factorize as much code as possible, I want to add information about related columns and table name for each class. These informations must be accessible without a class instance and will be used in Entity to build queries among other things.

The obvious way to store these data are static fields returned by static methods in each class. Problem is you can't force the class to implement these static methods and you can't do dynamic linking on static methods call in Java.

My Solutions

  1. Use a HashMap, or any similar data structure, to hold the informations. Problem : if informations are missing error will be at runtime not compile time.
  2. Use a parallel class hierarchy for the utility function where each corresponding class can be instantiated and dynamic linking used. Problem : code heavy, runtime error if the class don't exist

The question

How will you cope with the absence of abstract static and dynamic linking on abstract method ?

In a perfect world, the given solution should generate a compile error if the informations for a class are missing and data should be easily accessible from withing the Entity class.

The answer doesn't need to be in Java, C# is also ok and any insight on how to do this without some specific code in any language will be welcomed.

Just to be clear, I don't have any requirement at all besides simplicity. Nothing have to be static. I only want to retrieve table and columns name from Entity to build a query.

Some code

class Entity {     public static function afunction(Class clazz) { // this parameter is an option         // here I need to have access to table name of any children of Entity     } }  class A extends Entity {     static String table = "a"; }  class B extends Entity {     static String table = "b"; } 
like image 476
krtek Avatar asked Mar 05 '11 12:03

krtek


People also ask

Can we use static and abstract together in Java?

Java For Testers A static method belongs to class not to object instance thus it cannot be overridden or implemented in a child class. So there is no use of making a static method as abstract.

Can we use abstract and static both with a method?

If you declare a method in a class abstract to use it, you must override this method in the subclass. But, overriding is not possible with static methods. Therefore, an abstract method cannot be static.

How can we call static method from abstract class in Java?

Yes, of course you can define the static method in abstract class. you can call that static method by using abstract class,or by using child class who extends the abstract class. Also you can able to call static method through child class instance/object.

How do you call a static method from another static method in Java?

Call a static Method in Another Class in Java In the case of a static method, we don't need to create an object to call the method. We can call the static method by using the class name as we did in this example to call the getName() static method.


1 Answers

You should use the Java annotation coupled with the javac annotation processor, as it's the most efficient solution. It's however a bit more complicated than the usual annotation paradigm.

This link shows you how you can implement an annotation processor that will be used at the compile time.

If I reuse your example, I'd go this way:

@Target(ElementType.TYPE) @Retention(RetentionType.SOURCE) @interface MetaData {   String table(); }  abstract class Entity {}  @MetaData(table="a") class A extends Entity {}  @MetaData(table="b") class B extends Entity {}  class EntityGetter {   public <E extends Entity> E getEntity(Class<E> type) {     MetaData metaData = type.getAnnotation(MetaData.class);     if (metaData == null) {       throw new Error("Should have been compiled with the preprocessor.");       // Yes, do throw an Error. It's a compile-time error, not a simple exceptional condition.     }     String table = metaData.table();     // do whatever you need.   } } 

In your annotation processing, you then should check whether the annotation is set, whether the values are correct, and make the compilation fail.

The complete documentation is available in the documentation for the package javax.annotation.processing.

Also, a few tutorials are available on the Internet if you search for "java annotation processing".

I will not go deeper in the subject as I never used the technology myself before.

like image 124
Olivier Grégoire Avatar answered Oct 15 '22 16:10

Olivier Grégoire