views:

354

answers:

6

I'm writing a unit test for a method that packs boolean values into a byte. The various bit locations are determined by the value of an enum, which only has 5 values right now, but it's conceivable (though extremely unlikely) that this number could go to 9.

I'd like a simple test along the lines of:

private byte m_myNum; enum MyEnum {...}

assert(sizeof(m_myNum) <= MyEnum.values().length);

I'm under the impression that there's not a sizeof function in Java. What's the most elegant workaround?

---EDIT

I don't think I was clear. I'm not concerned about normal runtime. My issue is that I can write this code now with a byte that stores all the information, but as the Enum grows in an unrelated part of code, I could reach a point where my bitmasking code breaks. Rather than having this in a deployed application, I'd like to have a unit test that fails when the number of states in the enum exceeds the number of bits in the storage variable, so when a programmer adds that ninth enum, they can adjust the type of the variable to something with more than eight bits.

A: 

In Java byte has fixed size (8 bits), so no need for sizeof.

asalamon74
A: 

First, yes, there's no sizeof operator in Java. But sizeof(byte) is always 1 anyway. Is this really what you meant to say?

Second, how were you intending to fit 9 booleans into one byte? Not with bitmasks, I hope.

If you just want to find the highest bit that's set, you could use Integer.highestOneBit(m_myNum & 0xFF) (see the docs here).


EDIT: You talk about changing the storage to a larger type when there are too many values in the enum. According to this question, there's no memory reason not to use a byte instead of an int unless you have an array. So I'd say use an int at minimum, and upgrade to a long if the size exceeds 32. Simple enough?

Michael Myers
sizeof(byte) is 1, not 8
Arkadiy
Yes, of course, my mistake. I think the point remains, though.
Michael Myers
As for byte vs int, I was under the impression that 1.6 fixed this and is now more compact.The question still remains of when to make that update. It's very unlikely that the developer adding the 33rd item to the enum will realize it breaks my implementation. I need this unit test to alert them.
Parker
@mmyers In this post (http://stackoverflow.com/questions/229886/size-of-a-byte-in-memory-java/229992#229992) it is said that byte and boolean (as a class member) is 4 bytes. Can you provide any reliable proves for your statement, that sizeof(byte) == 1?
dma_k
@dma_k: Neither the JLS nor the JVM spec specifies the size in memory of each data type; they merely state the required value ranges. The JVM is free to use as much memory as it wishes to store any value. I would guess (although I have not researched it) that most JVMs align all variables, even those of smaller types, on 4 or 8 byte boundaries. But in arrays, it is much easier for the JVM to pack the values together. So to sum up, what I meant by `sizeof(byte) == 1` is that it's impossible for the number of available bits in a `byte` to vary from JVM to JVM.
Michael Myers
A: 

I found this question that may help you :-)

Unfortunately, there is no sizeof() in Java, but take a look at the answers of this questions. One I found interesting is this article from JavaWorld.

Paulo Guedes
+2  A: 

I think this test does what you want. It is probably a waste of your time to get more generic than this.

public void testEnumSizeLessThanOneByte() throws Exception 
{ 
    assertTrue("MyEnum must have 8 or less values.", 
                MyEnum.values().length <= 8);
}
Justin Standard
A: 

I know you're trying to come up with a generic solution but,in this case I would take the lazy way out and hard code the size and add some comments.

static final int MAX_BITS_IN_MY_NUM = 8; // Currently set to size of a byte.  
                                         // Update if data type changes from byte to something larger than a byte.
...
assertTrue(MAX_BITS_IN_MY_NUM >= MyEnum.values().length);
rich
Sadly enough, this is what I did. (Using Byte.SIZE instead). The overloaded sizeOf(...) just seemed too heavy-handed. If it comes up more, I'll switch over.If anyone comes up with a more elegant solution, please share!
Parker
+1  A: 

if this is a real concern and performance isn't that important you could always use a bitset

luke