从方法更改公共变量

时间:2014-05-02 08:55:40

标签: java

我有一些变数:

float firstFloatSize  = 0.0;
float secondFloatSize = 1.0;
float thirdFloatSize  = 2.0;
float fourthFloatSize = 3.0;

我想从一个方法中更改这些变量,该方法将接收变量的名称和新值作为参数。像这样:

public void changeValue("firstFloatSize", 3.0);

如果我运行它,我会将变量“firstFloatSize”的值更改为3.0。

这会以某种方式成为可能吗?我知道我可以为浮点数创建一个包装类,并在该类中实现了这样的方法,但我只是好奇我是否能以另一种方式实现这一点。

7 个答案:

答案 0 :(得分:1)

使用apache common setProperty

中的PropertyUtils
PropertyUtils.setProperty(this,"firstFloatSize", 3.0);

答案 1 :(得分:0)

可以使用反射来做到这一点,但它会创建难以维护的代码。例如,更改变量名称将破坏反射代码:在运行时之前您不会注意到这一点。你也在规避封装(或许你没有注意到会员数据是公开的)。

我建议您使用set和get方法以正常方式执行此操作。

答案 2 :(得分:0)

如果这些字段的主要歧视点是" first"," second"等等,那么您可以使用数组来存储值,并设置方法它根据数组中的索引更改值:

float[] floatSizes = new float[]{ 0, 1, 2, 3 };

public void changeValueAtPosition(int index, float newValue){
    floatSizes[index] = newValue;
}

这个例子当然缺少参数的一些常见保护(比如确保索引有效),并且可以通过使用标准类型(如枚举)而不是基元int来切换要更改的值来改进

更改" firstFloatSize"然后可以通过调用changeValueAtPosition(0, 3);

来实现

重申其他答案:如果有其他更简单的方法,请不要使用反射。基于反射的代码是任何项目规模的维护噩梦> 100 LOC。

答案 3 :(得分:0)

您基本上有两种选择:

编写自定义调度方法:

public void changeValue(String fieldName, float newValue)
{
     // Java 6 style:
     if("firstFloatSize".equals(fieldName)) {
         targetClass.firstFloatSize = newValue;
     } else if("secondFloatSize".equals(fieldName)) {
         targetClass.secondFloatSize = newValue;
     } else if // ... and so on

     // or, alternatively, Java 7 style:
     switch(fieldName)
     {
         case "firstFloatSize": targetClass.firstFloatSize = newValue; break;
         case "secondFloatSize": targetClass.secondFloatSize = newValue; break;
         // ... and so on
     } 
}

或使用反射:

public void changeValue(String fieldName, float newValue)
{
  try 
  {
    Field field = targetObject.getClass().getField(fieldName);
    field.setFloat(targetObject, newValue);
  }
  catch( ... ) { ... }
}

我不知道你的花车是同一个班级还是另一个班级。如果它是同一个班级,显然你不需要targetObject。否则,当然,您需要将targetObject替换为对所需对象的引用。

请注意,两种方式都不是很好,因为其他评论已经说明了。两者都不是很易于维护,例如,如果你想在将来重命名其中一个浮点数,那么你必须手动检查所有出现的字符串,因为在这些情况下你的编译器无法确定是否正确。

另外(虽然这有点显而易见),如果你想要像这样访问多个类似的浮点数,你也可以创建一个数组并使用索引(可能由枚举备份)而不是字符串解决他们但这与原来的问题相差太远,所以我不会在这里详细说明......

答案 4 :(得分:0)

我建议使用第三方库。

但是如果你想使用Java原始API,下面是一个示例代码..

public class ReflectionSample {

    private float value1 = 1.0f;

    public float getValue1() {
            return this.value1;
    }

    public void changeValue(String fieldName, float value) throws Exception {
            Field field = this.getClass().getDeclaredField(fieldName);
            boolean accessible = field.isAccessible();
            field.setAccessible(true);
            field.set(this, value);
            field.setAccessible(accessible);
    }

    public static void main(String[] args) throws Exception {
            ReflectionSample sample = new ReflectionSample();
            sample.changeValue("value1", 3.0f);
            System.out.println(sample.getValue1());
    }
}

答案 5 :(得分:0)

作为一个良好的编码实践。

  1. 您的班级不应该有公共变量。
  2. 变量应该是私有的,具有正确的get和set方法。这是基本的OOP原则之一。封装。
  3. 但请回到您的代码。
    首先,如何定义浮点变量存在一个小问题。这些应该是

    float firstFloatSize  = 0.0f;
    

    现在有几种方法可以实现这一目标。

    1. 编写自己的基于反射的代码。
    2. 使用类似下面的条件代码。
    3. 使用Apache PropertyUtils。其中使用反射设置您的属性。
    4. 最后,您的调用代码应该调用正确的set方法。希望它有所帮助。

      public void changeValue(String property, float value) { if(property.equals("firstFloatSize")) { firstFloatSize = value; } else if(property.equals("secondFloatSize")) { secondFloatSize = value; } else if(property.equals("thirdFloatSize")) { thirdFloatSize = value; } else { fourthFloatSize = value; } }

答案 6 :(得分:0)

不确定你究竟需要以这种方式设置值,但这就是我没有反思的结果:

public class PropertySetter {

    private float valOne;
    private float valTwo;
    private float valThree;
    private float valFour;

    public void setValue(FIELDS name, float value) {
        switch (name) {
            case valOne:
                valOne = value;
                break;
            case valTwo:
                valTwo = value;
                break;
            case valThree:
                valThree = value;
                break;
            case valFour:
                valFour = value;
                break;
            default:
                throw new AssertionError(name.name());
        }
    }

    public enum FIELDS {

        valOne,
        valTwo,
        valThree,
        valFour;
    }
}

但是如果允许反射,那么我会这样做:

public class ReflectionSetter {

    private float valOne;
    private float valTwo;
    private float valThree;
    private float valFour;

    public boolean setValue(String name, float value) {
        Field[] fields = this.getClass().getDeclaredFields();
        for (Field f : fields) {
            if (f.getName().equals(name)) {
                try {
                    f.setFloat(this, value);
                } catch (IllegalArgumentException | IllegalAccessException ex) {
                    Logger.getLogger(ReflectionSetter.class.getName()).log(Level.SEVERE, null, ex);
                }
                return true;
            }
        }
        return false;
    }
}

第一种方法有点难以维护,因为重构这个类将是一场噩梦。 第二种方式非常好,因为你只需要知道fieldname。