Java - 我可以将变量修改从一个类转换为另一个类吗?

时间:2016-10-13 06:49:05

标签: java

说我在班级A

int a = 1, b = 2, c = 3;

现在,在班级B中说我有一个功能:

public int void reset(String intName, A classA) {
...
}

reset()如果我reset('c', classA),那么我希望重置c中的classA。如果我执行了reset('b', classA),那么我希望重置b中的classA,依此类推。我不确定这是否可行,但是我需要这个来消灭游戏中不同类别的单位。

5 个答案:

答案 0 :(得分:1)

这可以通过反思来实现。但由于反思很慢,我建议你不要立即尝试反思。先尝试别的。你为什么不能这样做:

someObjectOfA.a = some value;
someObjectOfA.b = some value;
someObjectOfA.c = some value;

无论如何,这是使用反射的解决方案:

public static void reset(String name, A a) throws NoSuchFieldException, IllegalAccessException {
    Class<A> clazz = A.class;
    Field f = clazz.getField(name);
    f.set(a, 0);
}

请注意,abc必须声明为public,否则会引发NoSuchFieldException

如果您不想公开字段,可以添加如下字母:

public void setA(Integer value) {
    a = value;
}

然后reset方法将是:

public static void reset(String name, A a) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
    Class<A> clazz = A.class;
    Method m = clazz.getMethod("set" + name.toUpperCase(), Integer.class);
    m.invoke(a, 0);
}

答案 1 :(得分:1)

这里有很多选项,即使不使用反射(即通过运行时指定的名称动态修改对象的任意属性)。最简单的是让A负责从指定的密钥转换为相应的变量:

public class A {
    private static int a = 1, b = 2, c = 3;

    public void reset(String key) {
        switch(key) {
        case "a": a = 0;
                  break;
        case "b": b = 0;
                  break;
        case "c": c = 0;
                  break;
        default:
                  break;
        }
    }
}

public class B {
    public int void reset(String intName, A obj) {
        obj.reset(intName);
    }
}

这会导致重复的代码,并且很容易出错,尤其是当您向A添加新字段时。

更好的选项将使用Map动态地将属性名称映射到其值:

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class A {
    private static Map<String, Integer> map = new HashMap<>();
    static {
        map.put("A", 1);
        map.put("B", 2);
        map.put("C", 3);
    }

    public Map<String, Integer> getGameProperties() {
        return Collections.unmodifiableMap(map);
    }

    public void reset(String key) {
        map.put(key, 0);
    }
}

public class B {
    public int void reset(String intName, A obj) {
        obj.reset(intName);
    }
}

它在一个步骤中处理属性声明和键映射,从而修复了重复的,容易出错的代码的问题。它现在可能会影响类的外部接口,因为您删除了各个字段并将其替换为Map。这当然是保留字段private并使用getter / setter的一个很好的理由,因为可以更新getter以查看Map而无需更改类{{1}的外部API }}

答案 2 :(得分:1)

我会像这样设计我的A级:

class A
{
   public enum UnitType { TANK, TRIKE, COMMANDO };

   public void reset (UnitType type); 

   //or even:
   public void reset (Set<UnitType> types); 

}

所以B级可以打电话:

a.reset(UnitType.TANK);

Set案例

a.reset(EnumSet.of(UnitType.TANK, UnitType.COMMANDO));

a.reset(EnumSet.allOf(UnitType.class));

您仍然可以选择class A如何跟踪计数,而不会影响class B

的界面

例如,A类可以在内部使用Map来跟踪计数(这似乎是一个好主意),但也可以使用字段或任何其他方法。

答案 3 :(得分:0)

如果你真的想从其他类重置它,为什么不在A类中设置类似setter的东西呢?

我在A班说:

int a = 1, b = 2, c = 3;

public void resetA()
{
    this.a = 0;
}
public void resetB()
{
    this.b = 0;
}
public void resetC()
{
    this.c = 0;
}

int a = 1, b = 2, c = 3;

public void resetAll()
{
    this.c = 0;
    this.a = 0;
    this.b = 0;
}

我现在想不出如何为它的灵活性做出良好的编码,但如果你愿意,它可以重置你的价值,如果你喜欢的话

答案 4 :(得分:0)

试试这个。无需为每个字段编写setter方法。

        try
        {
            Field field = classA.getClass().getDeclaredField(intName);    
            field.setAccessible(true);
            Object value = field.get(classA);
            System.out.println(" val "+ value);
            field.set(classA, 0);//Reset to zero
            value = field.get(classA);
            System.out.println(" val "+ value);
        } catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }