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

问题描述 投票:0回答:3

在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

java static programming-languages language-design
3个回答
4
投票

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

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

然后,调用

getClassName
并将其传递给
Class.forName
:

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

2
投票

使用

StackWalker
API 的 Java 9 方法

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

这种方法完全避免使用类名。


至于whis不是核心语言功能的原因,我只能猜测,但我想到的一件事是嵌套类的一些复杂性,这些复杂性会使通过某些关键字实现此类功能变得复杂。如果没有办法从嵌套类等中引用可能的多个外部类,那么添加它就没有多大意义。

另一个原因是这并不是非常有用——这不是我曾经错过的功能。借助当今的 IDE 及其强大的重构工具,使用类名并不是什么大问题,即使该类后来被重命名。即使在生成源代码时,替换类名也相对简单。


1
投票

重新审视这个问题,我添加了一个达到相同结果的oneliner。实用程序的MethodHandles

class
在一行中返回
Class<?>
,性能相对较好。这更容易记忆、阅读和复制粘贴。这些属性在创建记录器等情况下非常有用。

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

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

© www.soinside.com 2019 - 2024. All rights reserved.