Search code examples
javareflectionstatic-initializerstatic-initialization

Java - Class type from inside static initialization block


Is it possible to get the class type from inside the static initialization block?

This is a simplified version of what I currently have::

class Person extends SuperClass {

   String firstName;

   static{
      // This function is on the "SuperClass":
      //  I'd for this function to be able to get "Person.class" without me
      //  having to explicitly type it in but "this.class" does not work in 
      //  a static context.
      doSomeReflectionStuff(Person.class);     // IN "SuperClass"
   }
}

This is closer to what I am doing, which is to initialize a data structure that holds information about the object and its annotations, etc... Perhaps I am using the wrong pattern?

public abstract SuperClass{
   static void doSomeReflectionStuff( Class<?> classType, List<FieldData> fieldDataList ){
      Field[] fields = classType.getDeclaredFields();
      for( Field field : fields ){
         // Initialize fieldDataList
      }
   }
}

public abstract class Person {

   @SomeAnnotation
   String firstName;

   // Holds information on each of the fields, I used a Map<String, FieldData>
   //  in my actual implementation to map strings to the field information, but that
   //  seemed a little wordy for this example
   static List<FieldData> fieldDataList = new List<FieldData>();

   static{
      // Again, it seems dangerous to have to type in the "Person.class"
      //   (or Address.class, PhoneNumber.class, etc...) every time.
      //   Ideally, I'd liken to eliminate all this code from the Sub class
      //   since now I have to copy and paste it into each Sub class.
      doSomeReflectionStuff(Person.class, fieldDataList);
   }
}

Edit

I picked the accepted answer based on what applied best to my problem, however it seems to me that all three of the current answers have their merits.


Solution

  • No, it's not possible without grabbing the stacktrace (which is imo nastier than your initial approach and for which I would in any way prefer Thread#getStackTrace() above new Exception()).

    Rather do that job in a non-static initializer (or the default constructor) of the abstract class where you check the initialized status.

    public abstract class SuperClass {
    
        {
            if (!isInitialized(getClass())) {
                initialize(getClass());
            }
        }
    
    }
    

    The called methods in turn can be safely static.