静态访问.class对象而不使用类名,在java中

edqdpe6u  于 2023-09-29  发布在  Java
关注(0)|答案(3)|浏览(121)

在java中,可以在不使用(换句话说,键入)类名的情况下访问类。例

public class Example {

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

}

但是在静态上下文中,没有类似的方法,只有.class静态字段。这个问题集中在从Java类本身内部访问.class,而不是从其他类访问。

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

    }

}

有没有一种方法可以从一个类的静态上下文中访问一个类的.class对象,而不引用类名(既不直接也不间接)?
另一个限制是,答案不允许示例化类或使用.getClass()示例方法。
我在上面举了几个例子来说明我的发现。我惊讶地发现,如果不从同一个类中键入类名,就无法访问.class字段。
这仅仅是一些设计决策的副作用,还是有什么根本原因导致没有类名就无法访问.class

m4pnthwp

m4pnthwp1#

我发现的一种方法是首先获取当前堆栈跟踪:

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

然后,调用getClassName并将其传递给Class.forName

Class<?> clazz = Class.forName(current.getClassName());
y1aodyip

y1aodyip2#

使用StackWalker API的Java 9方法

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

这种方法完全避免了使用类名。
至于whis不是核心语言特性的原因,我只能猜测,但我想到的一件事是嵌套类的一些复杂性,这些复杂性会使通过一些关键字实现这样的特性变得复杂。如果没有从嵌套类中引用可能的多个外部类的方法,那么添加this就没有多大意义。
另一个原因是这不是非常有用-这是我从来没有错过的功能。有了今天的IDE和它们强大的重构工具,使用类名不是很成问题,即使类后来被重命名。即使在生成源代码时,替换类名也相对简单。

3df52oht

3df52oht3#

重新审视这个问题,我添加一行代码来实现相同的结果。实用程序的MethodHandlesclass在单行中返回Class<?>,性能相对较好。这是更容易记忆,阅读和复制粘贴周围。这些属性在创建记录器之类的情况下很有用。

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

有关性能基准比较,请参阅hereArtyom Krivolapov的答案

相关问题