如何在不使用静态上下文中的类名的情况下访问 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。 utilities的MethodHandles

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

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

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

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