如果我有字段本身,是否可以通过Java反射获取Field?这是一个原始的浮动(公共,没问题)。我不想将其名称用作String。
示例:
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
...
效果类似于通过引用传递float,但不将其包装到包装类中。
我需要在不同的电视机上测量不同的电压,只需更改线路:
Voltmeter meter = new Voltmeter(tv1.voltageB);
以其他方式,例如:
Voltmeter meter = new Voltmeter(tv2.voltageA);
可以用反射来做吗?
THX
答案 0 :(得分:2)
要使用反射,您必须使用String。而不是使用浮点数,你可以使用一个对象来包装可变浮点数或一个简单的浮点数[1];
顺便说一句,除非你有一个很好的理由,否则我不会使用浮点数,双重遭受更少的舍入错误。
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);
编辑:使用抽象访问器。这是执行此操作的最快方法。 AFAIK,差异小于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 :(得分:2)
为了完整起见,我已经包含了解决此问题的代表方式。我也不建议你的花车可以公开访问。
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());
}
}
答案 2 :(得分:0)
如果您控制TVSet但由于某种原因需要使用反射,避免错误的一个好方法是在TVSet类中编写您需要的方法/字段名称作为字符串常量。
但是,如果您关心的是性能,那么反射就不是一种可行的方法,因为通过反射访问字段或方法比通过getter访问或直接访问要慢得多。
答案 3 :(得分:0)
这是一个变体,您可以在其中提供float
值而不是字符串。
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);
}
}
然后这样称呼:
Voltmeter meter = new Voltmeter(tv1, tv1.voltageB);
仅当电压表创建时刻的电压不同(而不是NaN)时,它才有效,因为第一个字段具有正确的值。我认为它并没有真正提高效率。
我不会真的推荐这个。