说我在班级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
,依此类推。我不确定这是否可行,但是我需要这个来消灭游戏中不同类别的单位。
答案 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);
}
请注意,a
,b
和c
必须声明为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();
}