If you are trying to avoid a template like this, I just stole:
if (access_flag & ACC_PUBLIC != 0) { public++; } if (access_flag & ACC_FINAL != 0) { final++; } ...
This is a great instinct. I make this rule to never write code that looks redundant. It is not only error prone, but also more code in your class, but copying and pasting code is very boring to write.
Thus, the big trick is to make this access “general” and understandable from the calling class - pull out all the repeating crap and just leave the “meat”, push the complexity to the general procedure.
Thus, a simple way to call a method would be something like this, giving an array of bit fields that contain many bit combinations that you need to consider, and a list of fields that interest you (so that you do not spend time testing fields that you do not need) :
int[] counts = sumUpBits(arrayOfFlagBitfields, ACC_PUBLIC | ACC_FINAL | ACC_...);
It's really clean, but how do you access the return fields? I initially thought of something like this:
System.out.println("Number of public classes="+counts[findBitPosition(ACC_PUBLIC])); System.out.println("Number of final classes="+counts[findBitPosition(ACC_FINAL)]);
Most of the template has disappeared here, except for the need to change the bitpods to their place. I think two changes can do it better - encapsulate it in a class and use a hash to track positions, so you don't need to constantly convert the bit position (if you prefer not to use a hash, findBitPosition is at the end).
Try a full class. What should this look like from the perspective of the caller?
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));
It's pretty clean and easy - I really love OO! Now you just use bitSums to store your values until you need them (this is less than templates than storing them in class variables and more understandable than using an array or collection)
So, now for class coding. Note that the constructor now uses variable arguments - less unexpected / more common and makes more sense to implement a hash.
By the way, I know that it looks like it will be slow and inefficient, but it is probably bad for most applications - if so, it can be improved, but it should be much shorter and less redundant than the switch (which really the same as this one, it just unfolds - however, in this case, hash and autoboxing is used, which will entail additional punishment).
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); } }
I have not tested this, but I think it is pretty close. I would not use it to process video packets in real time or something else, but for most purposes it should be fast enough.
As for maintaining the code, it may look “long” compared to the original example, but if you have more than 5 or 6 fields to check, this will actually be a shorter solution than the chained if statements and significantly less errors / addiction and more supported - it’s also more interesting to write.
If you really feel the need to eliminate the hash table, you can easily replace it with a sparse array with the flag position as an index (for example, the flag score 00001000 / 0x08 will be stored in the fourth array position). To do this, you need such a function to calculate the bit position for accessing the array (both for storage in the array and for extraction)
private int findBitPosition(int flag) { int ret; while( ( flag << 1 ) != 0 ) ret++; return ret; }
It was fun.