What I Learned at Home this Week: Bit Fields

Mike Diaz
5 min readMar 17, 2024

--

Photo by Pixabay: https://www.pexels.com/photo/turned-off-vintage-white-and-black-computer-257881/

Most of the lessons I’ve learned at work recently have been workplace-specific terraform protocols, so they wouldn’t be terribly fascinating for this blog. That will likely change in the near future, however, as I’m expecting to join a new team and work with Senior and Staff-level engineers for the first time in my career. Since they might have the expectation that I have a strong grasp on core programming concepts, I got the advice that it would be a good time to return to my copy of Effective Java (Third Edition).

I probably bought this book about a year ago, but haven’t touched it in a few months because it’s so dense that I have to read each chapter over and over before I understand anything. That’s frustrating, but for me, there’s no better way to ensure that I understand a concept than to write a blog post about it. So I sat down and spent 30 minutes reading two pages and now I’m going to spend another hour writing about those two pages. This post will cover Item 36 of Effective Java (Third Edition): Use EnumSet instead of bit fields.

Use enums instead of int constants

Item 36 in Effective Java is part of Chapter 6: Enums and Annotations. The first item in this chapter, Item 34, explains the concept of an enumerated type. The enum class allows us to create a group of distinct constants that are associated with each other under an enum, like Planet or Fruit . For someone like me, who only started studying engineering in 2020, the concept of an enum is native. Of course I would use an enum instead of constructing some complicated series of properties. Who would want to write something manual and brittle when there’s a built-in solution?

Reading books like this reminds me of how different my education is than older developers, or people with degrees in Computer Science. In boot camp, I didn’t have the luxury or the ability to learn core concepts of engineering — there simply wasn’t enough time and I didn’t have the background or the brain to study bits and bytes and data types. So if someone gives me a method or a class that just…does something like find or filter, I’m not going to question whether I should write my own version. But in reading this book, it seems that developers sometimes do need convincing to put down an old, flawed method and admit that the authors of Java made a reliable tool for what they want. Add that to the list of things I’ll never understand.

Enums, however, I do understand. Apparently, before enums, it was common to use int constants, which can look like this:

public static final int APPLE_FUJI = 0;
public static final int APPLE_PIPPIN = 1;
public static final int APPLE_GRANNY_SMITH = 2;

public static final int ORANGE_NAVEL = 0;
public static final int ORANGE_TEMPLE = 1;
public static final int ORANGE_BLOOD = 2;

The idea here is to associate each const with a number to help keep them organized. Honestly I’m not sure why this is especially useful and the book is looking to dissuade us from using this pattern, so it doesn’t provide much support either. I don’t blame it, after all there’s no way to get a string from these ints and they are in no way associated with each other. Compare that to an enum:

public enum Apple { FUJI, PIPPIN, GRANNY_SMITH }
public enum Orange { NAVEL, TEMPLE, BLOOD }

We can reference the elements with Apple.FUJI, Orange.TEMPLE, etc, and it’s easy to add or remove elements from the enum. We can even add methods to our enum classes to produce custom logic. They’re great! So long, int constants!

Use EnumSet instead of bit fields

In the book’s first example of an int enum pattern, they showed numbers being assigned sequentially. Apparently, it’s more traditional to assign a different power of 2 to each constant, like this:

public class Text {
public static final int STYLE_BOLD = 1 << 0; // 1
public static final int STYLE_ITALIC = 1 << 1; // 2
public static final int STYLE_UNDERLINE = 1 << 2; // 4
public static final int STYLE_STRIKETHROUGH = 1 << 3; // 8
}

The first question I had to ask myself was “what is <<?” This symbol is a bit operator that shifts the numbers in a bit to the left. The number to the left of the symbol is the original value and the number to the right is how many places to shift the bit. So in the first instance, the result is 1 because we’re shifting 0 places.

In the second example, we shift 1 to the left, so 1 becomes 10, which is 2 in binary code. Shifting to the left again results in 100, which is 4. Each time we shift to the left, the result doubles, hence the reference to “power of 2.”

This is confusing, so why would anyone ever do it? Based on a little bit of research, the main advantage seems to be that bit fields are space-efficient. And if we happen to have a collection that is follows the power of two, we can create a set using the bitwise OR operation:

text.applyStyles(STYLE_BOLD | STYLE_ITALIC);

Believe it or not, there is actually a better way to do this using the built-in java.util package. Rather than try to maximize efficiency with our own clever hacks, we can use the EnumSet class to build sets of enums. And don’t worry, it still uses a bit vector behind the scenes so it’s still efficient! In case you want to see it:

text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC));

If aren’t convinced, the text points out the following disadvantages to bit fields:

  • If one of the int values is changed, the client will have to recompile (or it’ll break).
  • If we’re debugging, we’ll just see numbers to represent our enums instead of any useful string.
  • There is no easy way to iterate over this non-sequential collection (1, 2,4, 8…)
  • To choose a type for the bit field, we have to estimate the maximum number of bits we’ll need (32 or 64) and we exceed that, we’ll have to change the API.

The evolution of programming

I graduated from college in 2011. Sometimes, I think back and I regret not studying computer science in school. After all, if I had gotten a ten-year head start, I would probably have a fabulous career right now and there’s a fair chance that I’d be exceedingly wealthy.

It’s easy to look back and think that, but seeing these concepts and reading 12-year-old StackOverflow questions helps me understand how far this field has come since I was a student. Of course, it would be advantageous to understand my work at such a core, basic level, but it’s incredibly challenging. Trying to learn those concept as a teenager might have dissuaded me from ever becoming a software engineer. I consider myself lucky that I never needed a book to tell me that the complex method I had developed to simply store a collection was obsolete. Instead, I was born into a world where there’s usually a method or a library for that. No one will ever have to extoll the virtues of that world to me — I am happy with that world.

Sources

--

--