在不加载类的情况下逼近class.getSimpleName()的最佳方法是什么?

时间:2016-04-20 21:20:09

标签: java reflection

给定一个完全限定的类名,可以加载Class.forName(),有没有办法将名称转换为加载类和调用getSimpleName()的结果没有真正尝试加载课程? 我需要这种能力用于反思。

2 个答案:

答案 0 :(得分:4)

我要说你根据名字不能这样做。

您可以尝试拆分.$,但此示例代码表明,简单名称的开头并不总是很明显:

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());
    }
}

输出:

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

即。如果你在最后的$.之后说“名字的一点”,你就错了。

这样做的唯一结论是加载类,可能没有初始化它:

Class<?> clazz = Class.forName(className, false, someClassLoadeR);

答案 1 :(得分:1)

正如@AndyTurner的答案所证明的那样,在所有情况下都无法从限定的类字符串中派生出简单的名称。

但是如果约束没有实际尝试加载类并不禁止读取类文件的内容,则可以执行以下操作(对于边缘情况):

  1. 通过InputStream
  2. 获取课程文件内容Class.getResourceAsStream()
  3. 解析类文件的开头并从常量池中读取超类名称。
  4. (由@shmosel评论)实现Class.getSimpleName()的逻辑。超类名称允许您替换依赖于已加载类的Class.getSimpleBinaryString()