Programatically calculate the size of a value type
-
22-07-2019 - |
Question
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.
Solution
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);
}
OTHER TIPS
if this is a real concern and performance isn't that important you could always use a bitset
In Java byte has fixed size (8 bits), so no need for sizeof.
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.
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?
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);