如何从 Java 中的字符串获取变量值?
How do I get a variable value from a String in Java?
所以我正在为 Minecraft bukkit 编写调试器插件,我想知道如何从字符串中获取 public 静态变量值。这是一些示例代码:
package example.package;
public class Ex {
public static String foo = "bar";
}
如果我给它字符串“example.package.Ex.foo”,它应该return“bar”,我该怎么做?
如您所述,example.package.Ex.foo
将 return bar
。静态变量由 class 而不是实例拥有,因此只有一个变量副本存在,您不需要创建实例。
如果你想在同一个 class 中访问变量,如果你想在另一个 class 中使用它,只需通过变量的名称使用它,你可以使用多种方法。
- 通过变量的完全限定名称。
package another.pack;
public class AnotherClass {
public void testVar(){
String tempStr = example.package.Ex.foo;
}
}
- 导入 class 并使用 class.variable。
package another.pack;
import example.package.Ex;
public class AnotherClass {
public void testVar(){
String tempStr = Ex.foo;
}
}
- 静态导入。
package another.pack;
import static example.package.Ex.foo;
public class AnotherClass {
public void testVar(){
String tempStr = foo;
}
}
在上述所有示例中,tempStr
的值将是 "bar"
由于变量只有一个副本退出,所以你必须小心,如果变量在一个地方被改变,它会影响到所有地方。
如果你想要一个常量,在声明变量时使用 final
关键字
package example.package;
public class Ex {
public static final String FOO = "bar";
}
Note: the convention is to use upper case for constants.
使用 java 11(反射 API)- 您也可以在旧 java 版本中执行此操作
public class Main {
public static void main(String[] args) {
var _this = new Main();
_this.doJob();
}
void doJob() {
var classLoader = this.getClass().getClassLoader();
try {
var loaded = classLoader.loadClass("example.package.Ex");
var obj = new Object();
var field = loaded.getField("foo");
System.out.println(field.get(obj));
} catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
编辑
通用方法是这样的:
<T> T getFieldValueAtRuntime(String field) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
var classLoader = this.getClass().getClassLoader();
final var endIndex = field.lastIndexOf('.');
final var fullClassName = field.substring(0, endIndex);
final var fieldName = field.substring(endIndex + 1);
var loadedClass = classLoader.loadClass(fullClassName);
var obj = new Object();
var fieldOfLoadedClass = loadedClass.getField(fieldName);
return (T) fieldOfLoadedClass.get(obj);
}
-------------------------
try {
String fieldValue = _this.getFieldValueAtRuntime("example.package.Ex.foo");
System.out.println(fieldValue);
} catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
所以我正在为 Minecraft bukkit 编写调试器插件,我想知道如何从字符串中获取 public 静态变量值。这是一些示例代码:
package example.package;
public class Ex {
public static String foo = "bar";
}
如果我给它字符串“example.package.Ex.foo”,它应该return“bar”,我该怎么做?
example.package.Ex.foo
将 return bar
。静态变量由 class 而不是实例拥有,因此只有一个变量副本存在,您不需要创建实例。
如果你想在同一个 class 中访问变量,如果你想在另一个 class 中使用它,只需通过变量的名称使用它,你可以使用多种方法。
- 通过变量的完全限定名称。
package another.pack; public class AnotherClass { public void testVar(){ String tempStr = example.package.Ex.foo; } }
- 导入 class 并使用 class.variable。
package another.pack; import example.package.Ex; public class AnotherClass { public void testVar(){ String tempStr = Ex.foo; } }
- 静态导入。
package another.pack; import static example.package.Ex.foo; public class AnotherClass { public void testVar(){ String tempStr = foo; } }
在上述所有示例中,tempStr
的值将是 "bar"
由于变量只有一个副本退出,所以你必须小心,如果变量在一个地方被改变,它会影响到所有地方。
如果你想要一个常量,在声明变量时使用 final
关键字
package example.package;
public class Ex {
public static final String FOO = "bar";
}
Note: the convention is to use upper case for constants.
使用 java 11(反射 API)- 您也可以在旧 java 版本中执行此操作
public class Main {
public static void main(String[] args) {
var _this = new Main();
_this.doJob();
}
void doJob() {
var classLoader = this.getClass().getClassLoader();
try {
var loaded = classLoader.loadClass("example.package.Ex");
var obj = new Object();
var field = loaded.getField("foo");
System.out.println(field.get(obj));
} catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
编辑 通用方法是这样的:
<T> T getFieldValueAtRuntime(String field) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
var classLoader = this.getClass().getClassLoader();
final var endIndex = field.lastIndexOf('.');
final var fullClassName = field.substring(0, endIndex);
final var fieldName = field.substring(endIndex + 1);
var loadedClass = classLoader.loadClass(fullClassName);
var obj = new Object();
var fieldOfLoadedClass = loadedClass.getField(fieldName);
return (T) fieldOfLoadedClass.get(obj);
}
-------------------------
try {
String fieldValue = _this.getFieldValueAtRuntime("example.package.Ex.foo");
System.out.println(fieldValue);
} catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}