Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #32972

Re: Java primitive variable objects

From Eric Sosman <esosman@comcast-dot-net.invalid>
Newsgroups comp.lang.java.programmer
Subject Re: Java primitive variable objects
Date 2015-11-02 14:15 -0500
Organization A noiseless patient Spider
Message-ID <n18clb$k3o$1@dont-email.me> (permalink)
References <33c95894-2638-4484-af5d-545701d34372@googlegroups.com>

Show all headers | View raw


On 11/2/2015 1:11 PM, Eric Douglas wrote:
> I just discovered something which created a minor problem in my class.  What would be the best way to solve it?
>
> I have some constant values defined such as this
> public static final int AVALUE = 1;
>
> some methods in the class have conditions defined such as this
> if (myValue == MyClass.AVALUE) {
>
> I'm passing in myValue as Integer with a possibility it could be null.
> I hadn't tested these methods with the null value so I didn't realize it actually gets an error.

     ... as it should.  "Unboxing" an Integer to extract its int
value cannot proceed if the Integer reference is null, that is,
if there's no Integer to be unboxed.

> This code
>            Integer x = 1;
>            Integer o = 1;
>            if (x == o) {
>                 System.out.println("equal");
>            } else {
>                 System.out.println("not");
>            }
> prints "equal".

     Right, but perhaps not for the reason you may imagine.
The comparison is not made between the unboxed values of the
Integer references, but is the traditional "reference identity"
comparison.  That is, the comparison checks whether the two
references x and o refer to the same Integer instance.

     Java happens to guarantee that the Integer instances produced
by "boxing" small int values are identical: It caches a bunch of
small-valued Integer objects and uses them over and over.  So if
you box the int value 1 twice, you get two references to the same
cached 1-valued Integer, and == pronounces them identical.

     If you box some int values whose corresponding Integers are
*not* cached, you get two brand-new Integer instances that == will
declare to be different.  I forget what the mandatory range of cached
values is (and individual implementations are allowed to cache more
than are required), but if you experiment with changing the 1's in
your example to -192837465's or some such, you may well get a different
outcome.

> This code
>            Integer x = new Integer(1);
>            Integer o = 1;
>            if (x == o) {
>                 System.out.println("equal");
>            } else {
>                 System.out.println("not");
>            }
> prints "not".

     Right.  The x reference is to a brand-new 1-valued Integer, while
the o reference is to a 1-valued Integer in the JVM's cache.  The ==
sees that these two are different objects, and says so.

> This code
>            Integer x = new Integer(1);
>            int o = 1;
>            if (x == o) {
>                 System.out.println("equal");
>            } else {
>                 System.out.println("not");
>            }
> prints "equal".

     Right, because comparison between an Integer and an int works
by "unboxing" the Integer and comparing the two int values.  The
comparison is shorthand for `x.intValue() == o'.

> This code
>            Integer x = null;
>            int o = 1;
>            if (x == o) {
>                 System.out.println("equal");
>            } else {
>                 System.out.println("not");
>            }
> gets a NullPointerException on the if.

     As above, the comparison is `x.intValue() == o', and when x is
null you can't call instance methods on it.

> Of course Eclipse at this point knows x is null and shows a warning on the if, but if you break it out as the real code would be, it compiles without error and just crashes when you run.
>
>       public static void main(String[] args) {
>            Integer x = null;
>            checkThis(x);
>       }
>       public static void checkThis(final Integer checkMe) {
>            int o = 1;
>            if (checkMe == o) {
>                 System.out.println("equal");
>            } else {
>                 System.out.println("not");
>            }
>       }
>
> Solutions?

     It's not clear to me just what problem you think needs solving.
Boxing and unboxing conversions can be confusing, agreed, but once
Sun decided to add them to Java there was no going back: You simply
need to know what the rules are, or know how to stay away from the
situations where the confusing bits arise.

> 1) Change all the constants to objects
> public static final Integer AVALUE = 1;

     Still plenty of room for surprises:

	if (new Integer(1) == AVALUE) ...

... and similarly for any other 1-valued Integer of unknown provenance.

> 2) Add null checks to all conditions
> if (checkMe != null && checkMe == o) {

     This avoids the NullPointerException, but as with (1) it can
still yield surprises.  (Also, although it reliably detects "present
and equal" it fails to distinguish between "absent" and "present but
unequal."  In a real program, you'd probably want to treat the three
cases differently.)

> Is there a third option? [...]

     I'd recommend not comparing Integers (or Bytes, etc.) with the ==
and != operators.  Comparing them with int (byte, ...) values is okay
if the references are non-null, because unboxing occurs and you get a
value-based comparison.  It's also okay to compare non-null references
with <, <=, >=, and >, because these also cause unboxing.

     To avoid nulls, try to use Integer (etc.) only when forced to and
prefer to use int (etc.) wherever you can.  When you must use an
Integer -- for example, when you're storing values in a Collection --
be careful to null-check when you need to:

	Map<Thing, Integer> occurrences = ...;
	for (Thing thing : collectionOfThings) {
	    Integer count = occurrences.get(thing);
	    occurrences.put(thing, count == null ? 1 : count + 1);
	}

> [...] Is there a difference in declaring static int constants versus Integers for memory use, performance?

     There's certainly a difference in memory use.  An int value takes
four bytes, period.  Using an Integer requires the Integer object itself
plus a reference variable that points to it.  On my system (yours may be
different) that's sixteen bytes for the Integer and four more for the
reference.  As mentioned above, though, some smallish Integers are
cached and re-used, so part of the twenty-byte total may be "free" or
at the least "amortized;" it's hard to come up with an exact measurement
of the int-to-Integer penalty.

     Performance?  Dunno, but I suspect the difference is fairly small,
probably too small to be measured without a Real Whole Lot of work.
You could take it on as a research project, I guess.

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

Back to comp.lang.java.programmer | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

Java primitive variable objects Eric Douglas <e.d.programmer@gmail.com> - 2015-11-02 10:11 -0800
  Re: Java primitive variable objects Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-11-02 14:15 -0500
    Re: Java primitive variable objects Eric Douglas <e.d.programmer@gmail.com> - 2015-11-02 13:03 -0800
      Re: Java primitive variable objects Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-11-02 16:29 -0500
  Re: Java primitive variable objects Jan Burse <janburse@fastmail.fm> - 2015-11-02 22:46 +0100
    Re: Java primitive variable objects Jan Burse <janburse@fastmail.fm> - 2015-11-02 22:52 +0100
    Re: Java primitive variable objects Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-11-02 17:47 -0500
  Re: Java primitive variable objects Joerg Meier <joergmmeier@arcor.de> - 2015-11-05 22:19 +0100
    Re: Java primitive variable objects Eric Douglas <e.d.programmer@gmail.com> - 2015-11-05 13:31 -0800
      Re: Java primitive variable objects Arne Vajhøj <arne@vajhoej.dk> - 2015-11-07 22:21 -0500
        Re: Java primitive variable objects Eric Douglas <e.d.programmer@gmail.com> - 2015-11-09 04:52 -0800
          Re: Java primitive variable objects Jerry Stuckle <jstucklex@attglobal.net> - 2015-11-09 08:54 -0500
            Re: Java primitive variable objects Eric Douglas <e.d.programmer@gmail.com> - 2015-11-09 07:27 -0800
              Re: Java primitive variable objects Jerry Stuckle <jstucklex@attglobal.net> - 2015-11-09 10:51 -0500
                Re: Java primitive variable objects Eric Douglas <e.d.programmer@gmail.com> - 2015-11-09 08:28 -0800
                Re: Java primitive variable objects Jerry Stuckle <jstucklex@attglobal.net> - 2015-11-09 11:57 -0500
                Re: Java primitive variable objects Eric Douglas <e.d.programmer@gmail.com> - 2015-11-09 10:13 -0800
                Re: Java primitive variable objects Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-11-09 13:28 -0500
                Re: Java primitive variable objects Jerry Stuckle <jstucklex@attglobal.net> - 2015-11-09 14:53 -0500
                Re: Java primitive variable objects Nigel Wade <nmw@ion.le.ac.uk> - 2015-11-10 09:27 +0000
                Re: Java primitive variable objects "Jeffrey H. Coffield" <jeffrey@digitalsynergyinc.com> - 2015-11-09 10:44 -0800
                Re: Java primitive variable objects Martin Gregorie <martin@address-in-sig.invalid> - 2015-11-09 18:59 +0000
                Re: Java primitive variable objects Jerry Stuckle <jstucklex@attglobal.net> - 2015-11-09 15:02 -0500
                Re: Java primitive variable objects Martin Gregorie <martin@address-in-sig.invalid> - 2015-11-09 22:57 +0000
                Re: Java primitive variable objects Jerry Stuckle <jstucklex@attglobal.net> - 2015-11-09 19:16 -0500
                Re: Java primitive variable objects Arne Vajhøj <arne@vajhoej.dk> - 2015-11-09 20:55 -0500
                Re: Java primitive variable objects Jerry Stuckle <jstucklex@attglobal.net> - 2015-11-09 22:13 -0500
                Re: Java primitive variable objects Arne Vajhøj <arne@vajhoej.dk> - 2015-11-09 20:40 -0500
                Re: Java primitive variable objects Jerry Stuckle <jstucklex@attglobal.net> - 2015-11-09 22:23 -0500
          Re: Java primitive variable objects Martin Gregorie <martin@address-in-sig.invalid> - 2015-11-09 14:00 +0000
            Re: Java primitive variable objects Eric Douglas <e.d.programmer@gmail.com> - 2015-11-09 07:18 -0800
              Re: Java primitive variable objects Arne Vajhøj <arne@vajhoej.dk> - 2015-11-09 20:43 -0500
          Re: Java primitive variable objects Arne Vajhøj <arne@vajhoej.dk> - 2015-11-09 19:38 -0500
            Re: Java primitive variable objects Jerry Stuckle <jstucklex@attglobal.net> - 2015-11-09 20:26 -0500
              Re: Java primitive variable objects Martin Gregorie <martin@address-in-sig.invalid> - 2015-11-10 02:10 +0000
                Re: Java primitive variable objects Jerry Stuckle <jstucklex@attglobal.net> - 2015-11-09 22:12 -0500
                Re: Java primitive variable objects Martin Gregorie <martin@address-in-sig.invalid> - 2015-11-10 13:01 +0000
                Re: Java primitive variable objects Jerry Stuckle <jstucklex@attglobal.net> - 2015-11-10 12:23 -0500
                Re: Java primitive variable objects Eric Douglas <e.d.programmer@gmail.com> - 2015-11-10 10:10 -0800
                Re: Java primitive variable objects Arne Vajhøj <arne@vajhoej.dk> - 2015-11-10 22:08 -0500
                Re: Java primitive variable objects Martin Gregorie <martin@address-in-sig.invalid> - 2015-11-10 20:05 +0000
                Re: Java primitive variable objects Eric Douglas <e.d.programmer@gmail.com> - 2015-11-10 13:21 -0800
                Re: Java primitive variable objects Martin Gregorie <martin@address-in-sig.invalid> - 2015-11-10 23:30 +0000
                Re: Java primitive variable objects Jerry Stuckle <jstucklex@attglobal.net> - 2015-11-10 20:58 -0500
                Re: Java primitive variable objects Gene Wirchenko <genew@telus.net> - 2015-11-10 22:30 -0800
                Re: Java primitive variable objects Arne Vajhøj <arne@vajhoej.dk> - 2015-11-10 21:58 -0500
              Re: Java primitive variable objects Arne Vajhøj <arne@vajhoej.dk> - 2015-11-10 21:56 -0500
                Re: Java primitive variable objects Jerry Stuckle <jstucklex@attglobal.net> - 2015-11-10 22:19 -0500
                Re: Java primitive variable objects Arne Vajhøj <arne@vajhoej.dk> - 2015-11-10 22:42 -0500
                Re: Java primitive variable objects Jerry Stuckle <jstucklex@attglobal.net> - 2015-11-10 23:07 -0500
            Re: Java primitive variable objects Eric Douglas <e.d.programmer@gmail.com> - 2015-11-10 06:06 -0800
  Re: Java primitive variable objects Lew <lewbloch@gmail.com> - 2015-11-16 14:47 -0800

csiph-web