通过反射获取Java字段,而不是从其字符串名称获取
如果我有字段本身,是否可以通过Java反射获得字段?这是一个原始的浮动(公共的,没问题)。我不想将其名称用作字符串 例如:通过反射获取Java字段,而不是从其字符串名称获取,java,reflection,floating-point,field,primitive,Java,Reflection,Floating Point,Field,Primitive,如果我有字段本身,是否可以通过Java反射获得字段?这是一个原始的浮动(公共的,没问题)。我不想将其名称用作字符串 例如: public class TVset { public float voltageA; public float voltageB; public float voltageC; public TVset(...) {...} // constructor public void function() {...} // it changes voltag
public class TVset {
public float voltageA;
public float voltageB;
public float voltageC;
public TVset(...) {...} // constructor
public void function() {...} // it changes voltages
}
class Voltmeter{
Object theObject;
Field theField;
Voltmeter(Object obj) {
theObject = obj;
Class theFieldClass = obj.getClass();
Class theContainerClass = theFieldClass.getDeclaringClass();
Field theField = ??? // <-- here I don't want to use a String
}
float getVoltage() {
return theField.getFloat(theObject);
}
}
TVset tv1 = new TVset(...);
TVset tv2 = new TVset(...);
Voltmeter meter = new Voltmeter(tv1.voltageB);
meter.getVoltage();
tv1.function();
meter.getVoltage(); <- should reflect the changed voltage
tv1.function();
meter.getVoltage(); <- should reflect the changed voltage
...
去做其他事情,比如:
Voltmeter meter = new Voltmeter(tv2.voltageA);
有可能通过反射来实现吗
Thx要使用反射,必须使用字符串。您可以使用对象包装可变浮点或简单浮点[1],而不是使用浮点 顺便说一句,除非你们有很好的理由,否则我不会使用float,double的舍入误差要小得多
public class TVset {
public double[] voltageA = { 0.0 };
public double[] voltageB = { 0.0 };
public double[] voltageC = { 0.0 };
}
class Voltmeter{
final double[] theField;
Voltmeter(double[] theField) {
this.theField = theField;
}
double getVoltage() {
return theField[0];
}
}
// works just fine.
Voltmeter meter = new Voltmeter(tv1.voltageB);
编辑:使用抽象访问器。这是最快的方法。好吧,相差不到10纳秒
public abstract class Voltmeter{ // or use an interface
public abstract double get();
public abstract void set(double voltage);
}
public class TVset {
private double _voltageA = 0.0;
private double _voltageB = 0.0;
private double _voltageC = 0.0;
public final Voltmeter voltageA = new Voltmeter() {
public double get() { return _voltageA; }
public void set(double voltage) { _voltageA = voltage; }
}
public final Voltmeter voltageB = new Voltmeter() {
public double get() { return _voltageB; }
public void set(double voltage) { _voltageB = voltage; }
}
public final Voltmeter voltageC = new Voltmeter() {
public double get() { return _voltageC; }
public void set(double voltage) { _voltageC = voltage; }
}
}
就个人而言,如果速度很关键,我会直接按名称使用字段。没有比这更简单或更快的了。要使用反射,必须使用字符串。您可以使用对象包装可变浮点或简单浮点[1],而不是使用浮点 顺便说一句,除非你们有很好的理由,否则我不会使用float,double的舍入误差要小得多
public class TVset {
public double[] voltageA = { 0.0 };
public double[] voltageB = { 0.0 };
public double[] voltageC = { 0.0 };
}
class Voltmeter{
final double[] theField;
Voltmeter(double[] theField) {
this.theField = theField;
}
double getVoltage() {
return theField[0];
}
}
// works just fine.
Voltmeter meter = new Voltmeter(tv1.voltageB);
编辑:使用抽象访问器。这是最快的方法。好吧,相差不到10纳秒
public abstract class Voltmeter{ // or use an interface
public abstract double get();
public abstract void set(double voltage);
}
public class TVset {
private double _voltageA = 0.0;
private double _voltageB = 0.0;
private double _voltageC = 0.0;
public final Voltmeter voltageA = new Voltmeter() {
public double get() { return _voltageA; }
public void set(double voltage) { _voltageA = voltage; }
}
public final Voltmeter voltageB = new Voltmeter() {
public double get() { return _voltageB; }
public void set(double voltage) { _voltageB = voltage; }
}
public final Voltmeter voltageC = new Voltmeter() {
public double get() { return _voltageC; }
public void set(double voltage) { _voltageC = voltage; }
}
}
就个人而言,如果速度很关键,我会直接按名称使用字段。没有比这更简单或更快的了。如果您控制TVSet,但出于某种原因需要使用反射,避免错误的一个好方法是将所需的方法/字段名作为字符串常量写入TVSet类中
但是,如果您关心的是性能,那么反射就不是一条出路,因为通过反射访问字段或方法可能比通过getter或直接访问要慢得多。如果您控制电视机,但出于某种原因需要使用反射,避免错误的一个好方法是将所需的方法/字段名作为字符串常量写入TVSet类
但是,如果您关心的是性能,那么反射就不是解决问题的方法,因为通过反射访问字段或方法可能比通过getter或直接访问要慢得多。为了完整起见,我已经包含了解决此问题的委托方法。我也不建议让你的花车公开
public class stackoverflow_5383947 {
public static class Tvset {
public float voltageA;
public float voltageB;
public float voltageC;
public Tvset() {
}
public void function() {
voltageA++;
}
};
public static class Voltmeter {
private VoltageDelegate _delegate;
public Voltmeter(VoltageDelegate delegate) {
_delegate = delegate;
}
float getVoltage() {
return _delegate.getVoltage();
}
};
public static interface VoltageDelegate {
public float getVoltage();
}
public static void main(String[] args) {
final Tvset tv1 = new Tvset();
Voltmeter meter = new Voltmeter(new VoltageDelegate() {
public float getVoltage() {
return tv1.voltageA;
}
});
System.out.println(meter.getVoltage());
tv1.function();
System.out.println(meter.getVoltage());
tv1.function();
System.out.println(meter.getVoltage());
}
}
为了完整起见,我加入了解决这个问题的代理方法。我也不建议让你的花车公开
public class stackoverflow_5383947 {
public static class Tvset {
public float voltageA;
public float voltageB;
public float voltageC;
public Tvset() {
}
public void function() {
voltageA++;
}
};
public static class Voltmeter {
private VoltageDelegate _delegate;
public Voltmeter(VoltageDelegate delegate) {
_delegate = delegate;
}
float getVoltage() {
return _delegate.getVoltage();
}
};
public static interface VoltageDelegate {
public float getVoltage();
}
public static void main(String[] args) {
final Tvset tv1 = new Tvset();
Voltmeter meter = new Voltmeter(new VoltageDelegate() {
public float getVoltage() {
return tv1.voltageA;
}
});
System.out.println(meter.getVoltage());
tv1.function();
System.out.println(meter.getVoltage());
tv1.function();
System.out.println(meter.getVoltage());
}
}
这里是一个变体,您可以使用
浮点值而不是字符串
class Voltmeter{
Object container;
Field theField;
Voltmeter(Object obj, float currentValue) {
container = obj;
Class<?> containerClass = obj.getClass();
Field[] fields = containerClass.getFields();
for(Field f : fields) {
if (f.getType() == float.class &&
f.getFloat(container) == currentValue) {
this.theField = f;
break;
}
}
}
float getVoltage() {
return theField.getFloat(container);
}
}
只有当电压表创建瞬间的电压不同(而不是NaN)时,它才起作用,因为它使用正确值的第一个字段。我认为这并不是真的更有效
我真的不建议这样做。这里有一个变体,您可以给您的浮点值而不是字符串
class Voltmeter{
Object container;
Field theField;
Voltmeter(Object obj, float currentValue) {
container = obj;
Class<?> containerClass = obj.getClass();
Field[] fields = containerClass.getFields();
for(Field f : fields) {
if (f.getType() == float.class &&
f.getFloat(container) == currentValue) {
this.theField = f;
break;
}
}
}
float getVoltage() {
return theField.getFloat(container);
}
}
只有当电压表创建瞬间的电压不同(而不是NaN)时,它才起作用,因为它使用正确值的第一个字段。我认为这并不是真的更有效
我真的不建议这样做。你能详细说明一下“我不想使用字符串”吗?我只是觉得写新的电压表(tv2,“voltageA”)很难看,因为我确切地知道TVset中的字段是什么,我可以写新的(tv2.voltageA)。另外,如果我无意中写了新的(tv2.vltageA),编译器会在运行前对我大喊大叫。你能详细解释一下“我不想使用字符串”吗?我只是觉得写新的伏特计(tv2,voltageA)很难看,因为我确切地知道TVset中的字段是什么,我可以写新的(tv2.voltageA)。另外,如果我无意中编写了新代码(tv2.vltageA),编译器会在运行前对我大喊大叫。但这不会带来性能损失吗?TVset对象每秒需要进行数百万次电压更新。这就是我使用基本浮点的原因(精度不是问题)。它比使用反射要小得多。如果需要,每秒可以执行1亿次更新。如果希望避免使用数组,可以使用抽象访问器类。这个抽象访问器类是如何工作的?请举个例子好吗?谢谢你的耐心。(顺便说一句,我意识到最初的问题非常愚蠢,因为当tv1.voltageA作为一个参数传递时,它已经被解析为一个普通浮点,因此接收方类无法知道它来自何处。)啊哈。谢谢你的例子。本质上,它的工作原理类似于Andrew Finnell的委托解决方案,但不是将访问器作为伏特计构造函数的参数当场构建,而是建议在TVset本身内部预构建所有这些访问器。很好。唯一(绝对次要)的缺点是,对于我决定添加到电视机中的每个新voltageX,我需要记住构建相应的访问器。但那绝对没问题。太多了!但这不会带来性能惩罚吗?TVset对象每秒需要进行数百万次电压更新。这就是我使用基本浮点的原因(精度不是问题)。它比使用反射要小得多。如果需要,每秒可以执行1亿次更新。如果希望避免使用数组,可以使用抽象访问器类。这个抽象访问器类是如何工作的?请举个例子好吗?谢谢你的耐心。(顺便说一句,我意识到最初的问题非常愚蠢,因为当tv1.voltageA作为一个参数传递时,它已经被解析为一个普通浮点,因此接收方类无法知道它来自何处。)啊哈。谢谢你的例子。本质上,它的工作原理类似于Andrew Finnell的委托解决方案,但不是将访问器作为伏特计构造函数的参数当场构建,而是建议在TVset本身内部预构建所有这些访问器。很好。唯一(绝对次要)的缺点是,对于每一个新的电压X,我决定添加到电视机中