[JAVA] Autoboxing that I learned as NullPointerException in Short comparison

Use ʻequals` when comparing values in wrapper classes

It is often said in the comparison of String. If you use == in comparison For ** reference types such as wrappers, compare the referenced **, and for ** primitive types, compare the value **.

String hoge = "hoge";
String fuga = "hogehoge";
fuga = fuga.substring(4); // << "hoge"become

//Since the reference destination is compared, it becomes "false"
boolean isEqual1 = hoge == fuga;

//Since the values are compared, it becomes "true".
boolean isEqual2 = hoge.equals(fuga);
System.out.print(isEqual2);

Even if you use == to compare Shorts, the range of "-128 to 127" will compare the values.

I inadvertently compared Short (short wrapper) with ==, but I didn't notice it halfway, I noticed when the value reached about 200. I didn't know ... but you should use ʻequals`.

Boolean isEquala = null;
// 「-128~Since it is out of the range of "127", it becomes "false".
Short a1 = -129;
Short a2 = -129;
isEqual = a1 == a2;
// 「-128~Since it is within the range of "127", it becomes "true".
Short b1 = -128;
Short b2 = -128;
isEqual = b1 == b2;
// 「-128~Since it is within the range of "127", it becomes "true".
Short c1 = 127;
Short c2 = 127;
isEqual = c1 == c2;
// 「-128~Since it is out of the range of "127", it becomes "false".
Short d1 = 128;
Short d2 = 128;
isEqual = d1 == d2;

Probably for the same reason as Integer.

Because "Integer.valueOf ()" is used instead of "new Integer ()" from int to Integer. This (currently) returns a cached Integer in the range -128-127, so it will be the same instance in that range. Therefore, even if they are compared with ==, they are equal. Java type memo (Hishidama's Java type Memo)

I get a NullPointerException even if I use == in the Short comparison

I was surprised ... I don't understand

Short a = null;
Boolean isOne = null;
//NullPointerException as expected
isOne = a.equals(1);
//Become "true" as you can imagine
isOne = a == null;
//Unexpectedly I get a NullPointerException!
isOne = a == 1;
//This will be "false" instead of a NullPointerException
isOne = a == new Short("1");
//This will also be "false"
Integer i = 1;
isOne = a == new Short(i.shortValue());

There is a boxing transform that automatically transforms primitive types and wrapper classes

It seems that it became possible from JDK1.5, and I did not know that there was such a name.

//Ordinary assignment to wrapper class
Short a1 = new Short("1000");
//Autoboxing: Automatically convert primitive types to wrapper classes
Short a2 = 1000; //When I decompile the class file, it looks like this>> Short a2 = Short.valueOf((short)1000);

//Ordinary assignment to primitive type
short b1 = a1.shortValue();
//Unboxing: Automatically convert wrapper classes to primitive types
short b2 = a2; //When I decompile the class file, it looks like this>> short b2 = a2.shortValue();

I tried to decompile the place where == was used in the Short comparison to see if it was boxing converted.

It seems that you can tell if it is boxing converted by decompiling, So I tried decompiling.

When I decompile the compiled version and look at it, it is simply replaced by the conversion method ... Java type memo (Hishidama's Java type Memo)

isOne = a.equals(1);
//↑ If you compile this and decompile it, it will be like this ↓
isOne = Boolean.valueOf(a.equals(Integer.valueOf(1)));

isOne = a == null;
//↑ If you compile this and decompile it, it will be like this ↓
isOne = Boolean.valueOf(a == null);

isOne = a == 1;
//↑ If you compile this and decompile it, it will be like this ↓
isOne = Boolean.valueOf(a.shortValue() == 1);

isOne = a == new Short("1");
//↑ If you compile this and decompile it, it will be like this ↓
isOne = Boolean.valueOf(a == new Short("1"));

Integer i = 1;
isOne = a == new Short(i.shortValue());
//↑ If you compile this and decompile it, it will be like this ↓
Integer i = Integer.valueOf(1);
isOne = Boolean.valueOf(a == new Short(i.shortValue()));

Comparing Short with a primitive type by == will result in a NullPointerException because shortValue () will be executed!

a == 1;
//↑ becomes like this ↓
Boolean.valueOf(a.shortValue() == 1);

I understand why it's a NullPointerException, but why is it shortValue () only when it's a literal number? ʻA == new Short ("1"); will not be Boolean.valueOf (a.shortValue () == new Short (i.shortValue ())); `?

@Swordone told me such a question.

If you compare the wrapper class (reference type) with the primitive type, autoboxing will be done, so If the comparison target is a reference type, .shortValue () is not executed and NullPointerException does not occur.

//For example, this is because the comparison target is a primitive type
boolean isOne = a == (short) 1;
//Auto boxing is performed(↓ Decompiled result)
boolean isOne = a.shortValue() == 1;


Recommended Posts

Autoboxing that I learned as NullPointerException in Short comparison
Methods that I found useful in Ruby
What I learned in Java (Part 2) What are variables?
Summary of what I learned in Spring Batch