I decided to read the JDK source somehow. That said, I don't have time to read each line carefully, so I read it briefly and found this code. Last time I read the source of Byte, so next is Short.
The Short class is a wrapper class for the primitive type short. First, the fields and the constructor. Well, it's a source that everyone can imagine.
Short.java
private final short value;
public Short(short value) {
this.value = value;
}
Actually, there is a ShortCache class that is not visible in javadoc.
Short.java
private static class ShortCache {
private ShortCache(){}
static final Short cache[] = new Short[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Short((short)(i - 128));
}
}
Isn't it a copy of the explanation of the Byte class so far? !! !! For the time being, the difference with the Byte class is that it caches instances from -128 to 127. It seems that I didn't instantiate from -32768 to 32767 because it's Short.
It is a cache of ShortCache, but it is referenced by valueOf.
Short.java
public static Short valueOf(short s) {
final int offset = 128;
int sAsInt = s;
if (sAsInt >= -128 && sAsInt <= 127) { // must cache
return ShortCache.cache[sAsInt + offset];
}
return new Short(s);
}
For the time being, it is the same as Byte, and if you do new Short (), it will be another instance. Short.valueOf () and autoboxing are probably the same.
Main.java
public static void main(String[] args) {
short s00 = 127;
Short s01 = Short.valueOf(s00);
Short s02 = s00;
System.out.println(s01 == s02);
short s10 = 128;
Short s11 = Short.valueOf(s10);
Short s12 = s10;
System.out.println(s11 == s12);
}
Result is···
true
false
Well, it's natural. In valueOf (), 127 or less uses the cache, but 128 or more is new Short (). For the time being, the same instance will be in the range of -127 to 128, but it is better to avoid comparing reference values too much.
However, it seems that there are occasions when the comparison operator == is used.
Main.java
public static void main(String[] args) {
short s11 = 128;
short s12 = 128;
Short s21 = s11;
Short s22 = s12;
System.out.println(s11 == s12);
System.out.println(s11 == s22);
System.out.println(s21 == s12);
System.out.println(s21 == s22);
}
The first is a primitive, the second is a primitive and a wrapper, and the fourth is a wrapper comparison. Actually, the second and third are casually auto-unboxing. Therefore, the result is ...
true
true
true
false
This is pretty tough. Personally, it's a crazy level to change the result depending on whether the s in the model name is lowercase or uppercase. Furthermore, as I wrote earlier, -127 to 128 will be true for all the 4th wrappers. How can I explain this to someone who is like Java for the first time in a month and understand it 100% correctly?
There is a version called JDK 1.4, and for the time being, you can compile at this 1.4 level even with the current JDK 1.8.
$ javac -source 1.4 -target 1.4 Main.java
warning: [options]Bootstrap classpath-source 1.Not set with 4
warning: [options]Source value 1.4 is obsolete and will be removed in a future release
warning: [options]Target value 1.4 is obsolete and will be removed in a future release
warning: [options] 廃止されたオプションについてのwarningを表示しないようにするには、-Xlint:Use the option.
Main.java:15:error:Incompatible type:Unable to convert short to Short:
Short s21 = s11;
^
Main.java:16:error:Incompatible type:Unable to convert short to Short:
Short s22 = s12;
^
Main.java:18:error:Binary operator'=='Operand type is invalid
System.out.println(s11 == s22);
^
First type: short
Second type: Short
Main.java:19:error:Binary operator'=='Operand type is invalid
System.out.println(s21 == s12);
^
First type: Short
Second type: short
4 errors
4 warnings
Actually, JDK 1.4 itself is also included,
$ javac Main.java
Main.java:15:Incompatible type
Detected value: short
Expected value: java.lang.Short
Short s21 = s11;
^
Main.java:16:Incompatible type
Detected value: short
Expected value: java.lang.Short
Short s22 = s12;
^
Main.java:18:operator==Is short,java.lang.Not applicable to Short.
System.out.println(s11 == s22);
^
Main.java:19:operator==Is java.lang.Short,Not applicable to short.
System.out.println(s21 == s12);
^
4 errors
The error message is slightly different. The reason for the error is that autoboxing / unboxing has been added since JDK 1.5. So what kind of source did you write before JDK 1.4?
Main.java
public static void main(String[] args) {
short s11 = 128;
short s12 = 128;
Short s21 = Short.valueOf(s11);
Short s22 = Short.valueOf(s12);
System.out.println(s11 == s12);
System.out.println(s11 == s22.shortValue());
System.out.println(s21.shortValue() == s12);
System.out.println(s21 == s22);
}
It seems like, in fact,
Main.java
public static void main(String[] args) {
short s11 = 128;
short s12 = 128;
Short s21 = new Short(s11);
Short s22 = new Short(s12);
System.out.println(s11 == s12);
System.out.println(s11 == s22.shortValue());
System.out.println(s21.shortValue() == s12);
System.out.println(s21 == s22);
}
What is it? Short.valueOf (short) is a method added from JDK 1.5. When I compile with javac -source 1.4 -target 1.4 with JDK 1.8, I can compile.
So, I think it would have been easier to understand if there was no poor auto-unboxing.
There is a method called compare, but let's arrange it as Byte, Short, Integer, Long for easy understanding.
Byte.java
public static int compare(byte x, byte y) {
return x - y;
}
Short.java
public static int compare(short x, short y) {
return x - y;
}
Integer.java
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
Long.java
public static int compare(long x, long y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
Can you see the difference? Even though I was an int in my own class, I skipped it and wrote return x --y ;. It works somehow, but in an extreme case, it overflows at x = 0x7FFFFFFF; y = -1. That's why it's a bug.
So, Byte and Short are return x --y; because the result falls within the range of int.
This is today's highlight. I mean, was there something like this? If you think so, it is added in JDK 1.8.
Short.java
public static int toUnsignedInt(short x) {
return ((int) x) & 0xffff;
}
public static long toUnsignedLong(short x) {
return ((long) x) & 0xffffL;
}
What to do is to convert from signed short to unsigned short, but since it cannot be expressed by short, it is returned as int or long. Since I came to Java from C language, I tend to think that I should write it myself like this, but I feel that it is better to use the prepared macros like C language macros. I will.
Well, normally I don't use Short, I use Integer.
Recommended Posts