What is the best way to approximate class.getSimpleName() without loading class?
Given a fully qualified class name that can be loaded with Class.forName(), is there a way to transform the name into what would be the result of loading the class and invoking getSimpleName() without actually attempting to load the class? I need this capability for reflection purposes.
I'm going to say that you can't do it simply based on the name.
You can try to split on .
and $
, but this example code demonstrates that it is not always obvious where the simple name begins:
class Ideone
{
private static class Bar {};
public static void main (String[] args) throws java.lang.Exception
{
class Foo$o {
class Bar$bar {}
};
class Foo$o$Bar {
class Bar$bar {}
};
class Foo$o$Bar$Bar$bar {}
print(Ideone.class);
print(Bar.class);
print(Foo$o.class);
print(Foo$o.Bar$bar.class);
print(Foo$o$Bar.Bar$bar.class);
print(Foo$o$Bar$Bar$bar.class);
}
private static void print(Class<?> clazz) {
System.out.printf("fqn=%s, sn=%s%n", clazz.getName(), clazz.getSimpleName());
}
}
Output:
fqn=Ideone, sn=Ideone
fqn=Ideone$Bar, sn=Bar
fqn=Ideone$1Foo$o, sn=Foo$o
fqn=Ideone$1Foo$o$Bar$bar, sn=Bar$bar
fqn=Ideone$1Foo$o$Bar$Bar$bar, sn=Bar$bar
fqn=Ideone$2Foo$o$Bar$Bar$bar, sn=Foo$o$Bar$Bar$bar
Ideone demo
ie if you were to say "the bit of the name after the final $
or .
", you'd be wrong.
The only conclusive way to do this is to load the class, potentially without initializing it:
Class<?> clazz = Class.forName(className, false, someClassLoadeR);
As demonstrated by the answer of @AndyTurner you cannot derive the simple name from the qualified class string in all cases.
But if the constraint without actually attempting to load the class does not forbid to read the contents of the class file, you could do the following (for the edge cases):
InputStream
for the class file contents via Class.getResourceAsStream()
Class.getSimpleName()
. The super class name allows you to replace Class.getSimpleBinaryString()
which relies on an already loaded class.