code: @Override
  	public String toBinaryString() {
  		String result;
  		if(hasNoStringCache() || (result = getStringCache().binaryString) == null) {
  			IPStringCache stringCache = getStringCache();
  			stringCache.binaryString = result = toBinaryString(null);
  		}
  		return result;
  	}
docs: /*
  There are two approaches when going beyond the usual segment by segment approach to producing strings for IPv6 and IPv4.
  We can use the inet_aton approach, creating new segments as desired (one, two or three segments instead of the usual 4).
  Then each such segment must simply know it's own sizes, whether bits, bytes, or characters, as IPAddressJoinedSegments and its subclasses show.
  The limitations to this are the fact that arithmetic is done with Java longs, limiting the possible sizes.  Also, we must define new classes to accommodate the new segments.
  A disadvantage to this approach is that the new segments may be short lived, so any caching is not helpful.
  
  The second approach is to print with no separator chars (no '.' or ':') and with leading zeros, but otherwise print in the same manner.
  So 1:2 would become 00010002.
  This works in cases where the string character boundaries line up with the segment boundaries.
  This works for hexadecimal, where each segment is exactly two characters for IPv4, and each segment is exactly 4 characters for IPv6.
  For other radices, this is not so simple.
  
  A hybrid approach would use both approaches.  For instance, for octal we could simply divide into segments where each segment has 6 bits,
  corresponding to exactly two octal characters, or any combination where each segment has some multiple of 3 bits.  It helps if the segment bit length
  divides the total bit length, so the first segment does not end up with too many leading zeros.
  In the cases where the above approaches do not work, this approach works.