title: Java integer flag and bitwise operations for memory reduction
body: <p>Is using an integer flag and bitwise operations an effective way of reducing the memory footprint of high volume Objects?</p>
  
  <ul>
  <li><p><strong>Memory Footprint</strong></p>
  
  <p>It is my understanding that commonly a <code>boolean</code> is stored as an <code>int</code> in a JVM implementation.  Is this correct?  In which case surely the 32 flags represent a large memory footprint reduction.</p>
  
  <p>Although of course the JVM implementations vary, so this may not always be the case.</p></li>
  <li><p><strong>Performance</strong></p>
  
  <p>It is my understanding that CPUs are very number driven and bitwise operations are about as efficient as things come in computing.</p>
  
  <p>Is there a performance penalty - or even gain - to using bitwise operations over boolean operations?</p></li>
  <li><p><strong>Alternatives</strong></p>
  
  <p>Is there a better way of accomplishing the same thing?  Does an Enum allow the combination of flags i.e. <code>FLAGX = FLAG1 | FLAG2</code>?</p></li>
  </ul>
  
  <hr>
  
  <h2>Example Code</h2>
  
  <p>Note the last method <code>propogateMove()</code> is recursive and may be called many hundreds of times per second and has a direct effect on the responsiveness of our application, hence the usage of flags to avoid logic bits and calling other methods.</p>
  
  <pre><code>// FLAGS helper functions
  private final void setclear(int mask, boolean set) { if (set) set(mask); else clear(mask); }
  private final void set(int mask) { flags |= mask; }
  private final void clear(int mask) { flags &amp;= ~mask; }
  private final boolean test(int mask) { return ((flags &amp; mask) == mask); }
  
  
  
  // Flags //////////////////////////////////////////////////////////////////////
  
  private static final boolean HORIZONTAL          = true;
  private static final boolean VERTICAL            = false;
  
  private static final int ORIENT                  = 0x00000001;
  private static final int DISPLAY                 = 0x00000002;
  private static final int HSHRINK                 = 0x00000004;
  private static final int VSHRINK                 = 0x00000008;
  private static final int SHRINK = HSHRINK | VSHRINK;
  
  private static final int TILE_IMAGE              = 0x00000010;
  private static final int CURSOR                  = 0x00000020;
  private static final int MOUSEINSIDE             = 0x00000040;
  private static final int MOUSEINSIDE_BLOCKED     = 0x00000080;
  
  private static final int CONSTRAIN               = 0x00000100;
  private static final int CONSTRAIN_DESCENDENT    = 0x00000200;
  private static final int PLACE                   = 0x00000400;
  private static final int PLACE_DESCENDENT        = 0x00000800;
  private static final int REFLOW = CONSTRAIN | CONSTRAIN_DESCENDENT | PLACE | PLACE_DESCENDENT;
  
  private static final int PACK                    = 0x00001000;
  private static final int CLIP                    = 0x00002000;
  private static final int HAS_WIDTH_SLACK         = 0x00004000;
  private static final int HAS_HEIGHT_SLACK        = 0x00008000;
  
  private static final int ALIGN_TOP               = 0x00010000;
  private static final int ALIGN_BOTTOM            = 0x00020000;
  private static final int ALIGN_LEFT              = 0x00040000;
  private static final int ALIGN_RIGHT             = 0x00080000;
  private static final int ALIGNS = ALIGN_TOP | ALIGN_BOTTOM | ALIGN_LEFT | ALIGN_RIGHT;
  private static final int ALIGN_TOPLEFT = ALIGN_TOP | ALIGN_LEFT;
  private static final int ALIGN_TOPRIGHT = ALIGN_TOP | ALIGN_RIGHT;
  private static final int ALIGN_BOTTOMLEFT = ALIGN_BOTTOM | ALIGN_LEFT;
  private static final int ALIGN_BOTTOMRIGHT = ALIGN_BOTTOM | ALIGN_RIGHT;
  
  private static final int ENTER_TRAP              = 0x00100000;
  private static final int LEAVE_TRAP              = 0x00200000;
  private static final int _MOVE_TRAP              = 0x00400000;
  private static final int MOVE_TRAP               = 0x00800000;
  
  private static final int CHILDREN_READ_TRAP      = 0x01000000;
  private static final int CHILDREN_TRAP           = 0x02000000;
  private static final int PLACE_CLEAN             = 0x03000000;
  
  private static final int SHRINK_TRAP             = 0x04000000;
  private static final int HSHRINK_TRAP            = 0x10000000;
  private static final int VSHRINK_TRAP            = 0x20000000;
  
  //private static final int UNUSED                = 0x40000000;
  //private static final int UNUSED                = 0x80000000;
  
  
  
  
  // Flags in switch ////////////////////////////////////////////////////////////
  
  /** get align value as a string from align flags */
  private JS alignToJS() {
      switch(flags &amp; ALIGNS) {
          case (ALIGN_TOPLEFT):
              return SC_align_topleft;
          case (ALIGN_BOTTOMLEFT):
              return SC_align_bottomleft;
          case (ALIGN_TOPRIGHT):
              return SC_align_topright;
          case (ALIGN_BOTTOMRIGHT):
              return SC_align_bottomright;
          case ALIGN_TOP:
              return SC_align_top;
          case ALIGN_BOTTOM:
              return SC_align_bottom;
          case ALIGN_LEFT:
              return SC_align_left;
          case ALIGN_RIGHT:
              return SC_align_right;
          case 0: // CENTER
              return SC_align_center;
          default:
              throw new Error("This should never happen; invalid alignment flags: " + (flags &amp; ALIGNS));
      }
  }
  
  
  
  
  // Flags in logic /////////////////////////////////////////////////////////////
  
  private final boolean propagateMove(int mousex, int mousey) throws JSExn {
      // start with pre-event _Move which preceeds Enter/Leave
      if (test(_MOVE_TRAP)) {
          if (Interpreter.CASCADE_PREVENTED == justTriggerTraps(SC__Move, JSU.T)) {
              // _Move cascade prevention induces Leave
              propagateLeave();
              // propagate cascade prevention
              return true;
          }
      }
  
      // REMARK: anything from here on in is a partial interruption relative
      // to this box so we can not call propagateLeave() directly upon it
      int i;
      boolean interrupted = false;
  
      if (!test(PACK)) {
          // absolute layout - allows for interruption by overlaying siblings
          for (Box b = getChild(i=treeSize()-1); b != null; b = getChild(--i)) {
              if (!b.test(DISPLAY)) {
                  continue;
              }
              if (interrupted) {
                  b.propagateLeave();
                  continue;
              }
              int b_mx = mousex-getXInParent(b);
              int b_my = mousey-getYInParent(b);
              if (b.inside(b_mx, b_my)) {
                  if (b.propagateMove(b_mx, b_my)) {
                      interrupted = true;
                  }
              } else {
                  b.propagateLeave();
              }
          }
      } else {
          // packed layout - interrupted still applies, plus packedhit shortcut
          boolean packedhit = false;
          for (Box b = getChild(i=treeSize()-1); b != null; b = getChild(--i)) {
              if (!b.test(DISPLAY)) {
                  continue;
              }
              if (packedhit) {
                  b.propagateLeave();
                  continue;
              }
              int b_mx = mousex-getXInParent(b);
              int b_my = mousey-getYInParent(b);
              if (b.inside(b_mx, b_my)) {
                  packedhit = true;
                  if (b.propagateMove(b_mx, b_my)) {
                      interrupted = true;
                  }
              } else {
                  b.propagateLeave();
              }
          }
      }
  
      // child prevented cascade during _Move/Move which blocks
      // Enter on this box - invoking Leave if necessary
      if (interrupted) {
          if (test(MOUSEINSIDE)) {
              if (!test(MOUSEINSIDE_BLOCKED)) {
                  // mouse previously inside, now blocked so invoke Leave
                  set(MOUSEINSIDE_BLOCKED);
                  if (test(LEAVE_TRAP)) {
                      justTriggerTraps(SC_Leave, JSU.T);
                  }
              }
          } else {
              // mouse not previously inside, Enter not yet triggered, so
              // do not invoke Leave
              set(MOUSEINSIDE);
              set(MOUSEINSIDE_BLOCKED);
          }
          // propagate cascade prevention 
          return true;
      }
  
      // set cursor if applicable to this box
      if (test(CURSOR)) {
          Surface s = getSurface();
          if (s!=null &amp;&amp; !s.cursorset) {
              s.cursor = JSU.toString(getAndTriggerTraps(SC_cursor));
              s.cursorset = true;
          }
      }
  
      // fire Enter traps
      if (!test(MOUSEINSIDE)) {
          set(MOUSEINSIDE);
          if (test(ENTER_TRAP)) {
              justTriggerTraps(SC_Enter, JSU.T);
          }
      }
  
      // finish post-event Move which follows Enter/Leave
      if (test(MOVE_TRAP)) {
          if (Interpreter.CASCADE_PREVENTED == justTriggerTraps(SC_Move, JSU.T)) {
              // propagate cascade prevention
              return true;
          }
      }
  
      // propagation uninterrupted
      return false;
  }
  </code></pre>