如何在不使用静态上下文中的 class 名称的情况下访问 java 中的 .class 对象
How to access the .class object in java without using the class name from a static context
在 java 中可以访问 class 而无需使用(换句话说键入)class 的名称。一个例子
public class Example {
/**
* Non static context, can only be called from an instance.
*/
public void accessClass() {
System.out.println(this.getClass());
}
}
但是在静态上下文中没有类似的方法,只有 .class 静态字段。这个问题的重点是从 java class 本身访问 .class ,而不是从其他 classes.
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 的静态上下文中访问 class 的 .class
对象而不引用 class 名称(既不直接也不引用间接)?
另一个限制是答案不允许实例化class或使用.getClass()
实例方法。
我在上面创建了一些示例,试图证明我的发现。
我很惊讶地发现,如果不在同一个 class.
中键入 class 名称,我就无法找到访问 .class
字段的方法
这只是某些设计决策的副作用,还是有任何根本原因导致没有 class 名称就无法访问 .class
?
我发现的一种方法是先获取当前堆栈跟踪:
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
StackTraceElement current = stackTrace[1];
然后,调用 getClassName
并将其传递给 Class.forName
:
Class<?> clazz = Class.forName(current.getClassName());
A Java 9 方法使用 StackWalker
API
Class<?> currentClass = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE)
.walk(s -> s.map(StackFrame::getDeclaringClass).findFirst().orElseThrow());
这种方法完全避免使用 class 名称。
至于 whis 不是核心语言功能的原因,我只能猜测,但我想到的一件事是嵌套 classes 的一些复杂性,这会使通过某些方式实现这样的功能变得复杂关键词。如果没有从嵌套 class 等中引用可能的多个外部 classes 的方法,添加它就没有多大意义
另一个原因是这不是非常有用 - 这不是我曾经错过的功能。使用当今的 IDE 及其强大的重构工具,使用 class 名称不是很成问题,即使 class 后来被重命名。即使在生成源代码时,替换 class 名称也相对简单。
在 java 中可以访问 class 而无需使用(换句话说键入)class 的名称。一个例子
public class Example {
/**
* Non static context, can only be called from an instance.
*/
public void accessClass() {
System.out.println(this.getClass());
}
}
但是在静态上下文中没有类似的方法,只有 .class 静态字段。这个问题的重点是从 java class 本身访问 .class ,而不是从其他 classes.
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 的静态上下文中访问 class 的 .class
对象而不引用 class 名称(既不直接也不引用间接)?
另一个限制是答案不允许实例化class或使用.getClass()
实例方法。
我在上面创建了一些示例,试图证明我的发现。 我很惊讶地发现,如果不在同一个 class.
中键入 class 名称,我就无法找到访问.class
字段的方法
这只是某些设计决策的副作用,还是有任何根本原因导致没有 class 名称就无法访问 .class
?
我发现的一种方法是先获取当前堆栈跟踪:
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
StackTraceElement current = stackTrace[1];
然后,调用 getClassName
并将其传递给 Class.forName
:
Class<?> clazz = Class.forName(current.getClassName());
A Java 9 方法使用 StackWalker
API
Class<?> currentClass = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE)
.walk(s -> s.map(StackFrame::getDeclaringClass).findFirst().orElseThrow());
这种方法完全避免使用 class 名称。
至于 whis 不是核心语言功能的原因,我只能猜测,但我想到的一件事是嵌套 classes 的一些复杂性,这会使通过某些方式实现这样的功能变得复杂关键词。如果没有从嵌套 class 等中引用可能的多个外部 classes 的方法,添加它就没有多大意义
另一个原因是这不是非常有用 - 这不是我曾经错过的功能。使用当今的 IDE 及其强大的重构工具,使用 class 名称不是很成问题,即使 class 后来被重命名。即使在生成源代码时,替换 class 名称也相对简单。