2014-05-02 33 views
-1

公共变量我有一些变量:改变从一个方法

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。

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

+4

这听起来含糊地反映相关,这意味着不,你不能。 (更具体地说,你可以,但不应该没有很好的理由) – awksp

+0

为什么你不想使用getters和setter? – Oyeme

+0

你尝试过使用Map 吗? –

回答

0

可能这样做使用反射,但它会创建将难以维护的代码。例如,更改变量名称会破坏反射代码:直到运行时才会注意到这一点。你也可以绕过封装(可能是因为你注意到成员数据是公开的)。

我建议你以正常的方式做,并设置和获取方法。

1

使用setProperty从apache的共同PropertyUtils

PropertyUtils.setProperty(this,"firstFloatSize", 3.0); 
+0

这仍然在内部使用反射,这可能是令人反感的... – awksp

+1

user3580294:对不舒服反射的人的其他简单方法之一。 – suren

+0

只要字段名称发生更改,这仍会自动打破。 – hiergiltdiestfu

0

如果这些字段的主要歧视性点是“第一”,“第二”等,则可以使用一个数组来存储值,UND设置根据该阵列中的索引而改变的值的方法:

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

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

当然本实施例缺少一些常见警卫的参数(如确保指数是有效的),并且可以通过使用能够提高标准类型(如en嗯)而不是原始的int来切换你想改变的值。然后

更改“firstFloatSize”将通过调用changeValueAtPosition(0, 3);

重申其他答案点是可能的:如果有其他的,更简单的方法不使用反思。基于反射的代码是任何大于100 LOC的项目的维护梦魇。

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替换为所需对象的引用。

请注意,这两种方式都不是很好,因为其他评论已经说明。两者都不是很好维护,例如,如果您希望将来重命名其中一个浮点数,则必须手动检查所有出现的字符串,因为在这些情况下,编译器无法确定正确性。另外(尽管这很明显),如果你有多个你想要访问的相似的浮点数,你也可以创建一个数组并使用一个索引(可能由一个枚举支持)而不是一个字符串解决它们。但是这与原来的问题相去甚远,所以我在此不再详述...

+1

从Java 7开始,if-cascade也可以通过切换字符串字面值来完成,其中 - 恕我直言 - 看起来更优雅,更少混乱。 – hiergiltdiestfu

+0

好点。我修改了我的答案。 –

+0

'getField(fieldName)'不会返回专用字段,您最终将使用'java.lang.NoSuchFieldException'使用'.getDeclaredField(name)'代替。 –

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()); 
    } 
} 
0

作为一个良好的编码习惯。

  1. 你不应该在你的类中有公共变量。
  2. 变量应该是私有的,并具有适当的get和set方法。这是基本的面向对象原则之一。封装。

但是回到你的代码。
首先,您如何定义浮点变量存在一个小问题。这些应该是

float firstFloatSize = 0.0f; 

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

  1. 编写自己的基于反射的代码。
  2. 使用如下所示的条件代码。
  3. 使用Apache PropertyUtils。其中使用反射设置您的财产。

仍然最后你的调用代码应该调用一个适当的设置方法。希望能帮助到你。

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; } }

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; 
    } 
} 

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