3

In java it is possible to access the class without using (in other words typing) the name of the class. An example

public class Example {

    /**
     * Non static context, can only be called from an instance.
     */
    public void accessClass() {
        System.out.println(this.getClass());
    }

}

However in a static context there is no similar method but only the .class static field. This question is focused in accessing the .class from within the java class itself, not from other classes.

public class Example2 {
    //field used to demonstrate what is meant by "indirectly referencing the class name.
    private static Class<Example2> otherClass = Example2.class;
    private static int intField = 1;
   /**
     * Non static context, can only be called from an instance.
     */
     public static void accessClass() {

        // The .class static field can be accessed by using the name of the class
        System.out.println(Example2.class);

        // However the following is wrong
        // System.out.println(class);

        // Accessing static fields is in general possible
        System.out.println(intField);

        // Accessing a static field of the same Class is also possible, but does not satisfy the answer since the class name has been written in the declaration of the field and thus indirectly referenced.
        System.out.println(otherClass);

    }

}

Is there a way to access the .class object of a class from a static context of the same class without referencing the class name (neither directly nor indirectly)?

Another restriction is that the answer is not allowed to instantiate the class or use the .getClass() instance method.

I have created some examples above that try to demonstrate my findings. I was surprised to notice that I could not find a way to access the .class field without typing the class name from within the same class.

Is this just a side-effect of some design decisions, a or is there any fundamental reason that accessing .class is not possible without the class name?

Spyros K
  • 2,480
  • 1
  • 20
  • 37

3 Answers3

4

One way I found is to get the current stack trace first:

StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
StackTraceElement current = stackTrace[1];

Then, call getClassName and pass that to Class.forName:

Class<?> clazz = Class.forName(current.getClassName());
Sweeper
  • 213,210
  • 22
  • 193
  • 313
2

A Java 9 approach using the StackWalker API

Class<?> currentClass = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE)
        .walk(s -> s.map(StackFrame::getDeclaringClass).findFirst().orElseThrow());

This approach avoids using the class name completely.


As for reasons why whis is not a core language feature, I can only guess, but one thing that comes to my mind are some complications around nested classes that would complicate implementing such a feature through some keyword. It wouldn't make much sense to add this without a way to refer to possibly multiple outer classes from within a nested class, etc.

Another reason is that this is not extremely useful - this is not a feature I've ever missed. With todays IDEs and their powerful refactoring tools, using the class name is not very problematic, even if the class is later renamed. Even when generating source code, substituting the class name is relatively straightforward.

Hulk
  • 6,399
  • 1
  • 30
  • 52
  • Useful to see also the StackWalker API, had not really noticed it in the past. I completely agree to the reasons explained for the `,class` in static contect not being available as a core language feature. Thank you. – Spyros K Jan 15 '19 at 13:14
1

Revisiting this question, I add an oneliner that achieves the same result. The MethodHandles class of utilities returns the Class<?> in a single line, with a relatively good performance. This is easier to memorize, read and copy-paste around. These properties are useful in cases like creating loggers.

final Class<?> clazz = MethodHandles.lookup().lookupClass();

For a performance benchmark comparison see here the answer by Artyom Krivolapov

Spyros K
  • 2,480
  • 1
  • 20
  • 37