如果你想避免这样的模式,我只是偷了一个:
if (access_flag & ACC_PUBLIC != 0)
{
public++;
}
if (access_flag & ACC_FINAL != 0)
{
final++;
}
...
这是一种伟大的直觉。我制定了一条规则,永远不要编写看起来像那样多余的代码。它不仅容易出错,而且你的类中的代码更多,而且复制和粘贴代码真的很无聊。
所以最大的技巧是让这个访问“通用”并且易于从调用类中理解——去掉所有重复的废话,只留下“肉”,将复杂性推到通用例程中。
因此,调用方法的一种简单方法是提供一个包含许多需要计数的位组合的位域数组以及您感兴趣的字段列表(这样您就不会浪费时间进行测试)您不关心的字段):
int[] counts = sumUpBits(arrayOfFlagBitfields, ACC_PUBLIC | ACC_FINAL | ACC_...);
这真的很干净,但是您如何访问返回字段?我原本是这么想的:
System.out.println("Number of public classes="+counts[findBitPosition(ACC_PUBLIC]));
System.out.println("Number of final classes="+counts[findBitPosition(ACC_FINAL)]);
除了需要将位域更改为它们的位置之外,这里的大部分样板都已消失。我认为两项更改可能会使其更好-将其封装在一个类中并使用散列来跟踪位置,这样您就不必一直转换 bitPosition (如果您不想使用散列,findBitPosition 在最后)。
让我们尝试一个成熟的课程。从调用者的角度来看,这应该如何看待?
BitSummer bitSums=new BitSummer(arrayOfFlagBitfields, ACC_PUBLIC, ACC_FINAL);
System.out.println("Number of public classes="+bitSums.getCount(ACC_PUBLIC));
System.out.println("Number of final classes="+bitSums.getCount(ACC_FINAL));
这很干净也很简单——我真的很喜欢 OO!现在您只需使用 bitSums 来存储您的值直到需要它们(它比将它们存储在类变量中更少样板,并且比使用数组或集合更清晰)
所以现在对类进行编码。请注意,构造函数现在使用可变参数 - 更少惊喜/更传统,并且对哈希实现更有意义。
顺便说一句,我知道这看起来会很慢而且效率低下,但对于大多数用途来说可能还不错——如果是的话,它可以改进,但这应该比 switch 更短且冗余更少声明(实际上与此相同,只是展开-但是此声明使用哈希和自动装箱,这将导致额外的惩罚)。
public class BitSummer {
// sums will store the "sum" as <flag, count>
private final HashMap<Integer, Integer> sums=new HashMap<Integer, Integer>();
// Constructor does all the work, the rest is just an easy lookup.
public BitSummer(int[] arrayOfFlagBitfields, int ... positionsToCount) {
// Loop over each bitfield we want to count
for(int bitfield : arrayOfFlagBitfields) {
// and over each flag to check
for(int flag : positionsToCount) {
// Test to see if we actually should count this bitfield as having the flag set
if((bitfield & flag) != 0) {
sums.put(flag, sums.get(flag) +1); // Increment value
}
}
}
}
// Return the count for a given bit position
public int getCount(int bit) {
return sums.get(bit);
}
}
我没有对此进行测试,但我认为它相当接近。我不会用它来实时处理视频包或任何东西,但对于大多数用途来说,它应该足够快。
至于与原始示例相比,维护代码可能看起来“长”,但如果要检查的字段超过 5 或 6 个,这实际上将是比链式 if 语句更短的解决方案,并且错误/容易发生的问题明显更少等等可维护——写起来也更有趣。
如果您真的觉得需要消除哈希表,您可以轻松地将其替换为以标志位置为索引的稀疏数组(例如,标志 00001000/0x08 的计数将存储在第四个数组位置)。这将需要一个这样的函数来计算数组访问的位位置(存储在数组中和检索)
private int findBitPosition(int flag) {
int ret;
while( ( flag << 1 ) != 0 )
ret++;
return ret;
}
那很有趣。