假设我有这样一个类:
class ASDF {
int a;
int b;
int c;
}
ASDF[] myArray;
一系列规模的ASDF。有没有办法编写一个接受ASDF成员名称和ASDF数组的函数,并对给定成员名称的所有成员求和?
即,我想要一个像这样工作的函数:
sumMember(myArray, a);
将返回所有' a'的总和。 ASDF中的成员变量。但是,有三个以上的成员变量,因此为每个变量设置一个函数并不现实。
答案 0 :(得分:6)
您可以使用反射或地图或......
或者,如果你可以使用Java 8,你可以传递一个lambda来指向你感兴趣的成员。它不是你想要的那么短,但也不是太糟糕:
public static int sumMembers(ASDF[] array, ToIntFunction<ASDF> member) {
return Arrays.stream(array).mapToInt(member).sum();
}
样品使用:
public static void main(String[] args) {
ASDF[] array = {new ASDF(), new ASDF()};
array[0].a = 1;
array[1].a = 2;
//THIS IS HOW YOU CALL IT
int sum = sumMembers(array, a -> a.a);
}
答案 1 :(得分:1)
如果类和字段为public
,那么您可以使用reflection按名称获取字段值,因此您可以编写sumMember
以便
sumMember(myArray, "a");
作品。
Reflection tends to be overpowered并使用静态分析工具(如重构)进行干扰,因此您可以使用interface Getter
对字段进行抽象,如
public interface Getter<V, O> {
V get(O source);
}
public static <O>
double sumMember(Iterable<? extends O> toSum, Getter<Double, O> getter) {
double runningSum = 0.0;
for (O o : toSum) { runningSum += getter(toSum); }
return runningSum;
}
然后使用它
sumMember(Arrays.asList(yourArray), // Xlate btw array and Iterable
new Getter<Double, ASDF>() { // ASDF x -> x.a
public Double get(ASDF asdf) { return asdf.a; }
});
或使用Java8 lambda创建getter。
答案 2 :(得分:1)
将公共领域放在一个类中通常被认为是糟糕的设计实践。如果该类具有可管理的成员数,全部为int
,那么最好创建字段private
并为每个字段添加getter函数:
class ASDF {
private int a;
private int b;
private int c;
public int getA() {
return a;
}
public int getB() { ... and so on
}
(我假设你会为这些字段提供更好的名称。)如果是这种情况,那么你可以使用Java 8的成员函数语法轻松编写sum
函数,将其中一个函数作为参数:
int sumMember(ASDF[] array, toIntFunction<ASDF> func) {
int sum = 0;
for (ASDF element : array) {
sum += func.applyAsInt(element);
}
return sum;
}
sumA = sumMember(myArray, ASDF::getA);
sumB = sumMember(myArray, ASDF::getB);
等等。 ToIntFunction
位于java.util.function
,其描述为here。 [另外,在assylias中使用lambda'的答案也很有效,写起来很简单;在这种情况下,你可以在没有getter函数的情况下解决它,但我仍然认为以这种方式使用公共字段是一个坏主意。]
但是,如果有大量int
成员,或者您有一个类,其唯一目的是拥有多个int
成员(即除了getter或setter之外没有其他方法)那么你可能不想要个别成员。相反,您需要一个使用数组或某种集合的类来保存成员,这样就可以通过String
名称或其他类型的键或索引来访问成员。
答案 3 :(得分:0)
您可以使用反射按字段名称引用, 但这是一个糟糕的主意。
相反, 创建一个知道所需值的类,并将其返回到sumMember方法。
以下是一些代码:
public int sumMember(
final ASDF[] itIsTerribleToUseArraysLikeThis
final ValueRetriever valueRetriever)
{
int returnValue = 0;
for (ASDF current : itIsTerribleToUseArraysLikeThis)
{
returnValue += valueRetriever.getValue(current);
}
return returnValue;
}
public interface ValueRetriever
{
public int getValue(ASDF structure);
}
public class AValueRetriever implements ValueRetriever
{
public int getValue(final ASDF structure)
{
if (structure != null)
{
return structure.a;
}
else
{
return 0;
}
}
}
sumMember(myArray, new AValueRetriever());
注意: 你的代码在几个方面很糟糕。
ASDF是一种结构。如果您使用C语言或其他非oo语言编写代码,这很好。在Java中,它很糟糕。使用对象。
传递阵列也很糟糕。 Java(和其他oo语言)提供了很好的集合实现。使用这些。查看List