I read the source of Short

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.

Short class

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;
    }

ShortCache class

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);
    }

Compare with the comparison operator ==

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.

But I'm using the comparison operator ==

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?

Once upon a time there was something called JDK 1.4

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.

compare method

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.

toUnsignedInt method, toUnsignedLong method

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.

Finally

Well, normally I don't use Short, I use Integer.

Recommended Posts

I read the source of Short
I read the source of ArrayList I read
I read the source of Integer
I read the source of Long
I read the source of Byte
I read the source of String
I read the Kotlin startbook
Is drainTo of LinkedBlockingQueue safe? I followed the source
05. I tried to stub the source of Spring Boot
I investigated the internal processing of Retrofit
[day: 5] I summarized the basics of Java
Read the Perelman treatise of Poincare conjecture
I want to output the day of the week
I checked the place of concern of java.net.URL # getPath
I understood the very basics of character input
I compared the characteristics of Java and .NET
I want to var_dump the contents of the intent
I touched on the new features of Java 15
I tried using the profiler of IntelliJ IDEA
I checked the number of taxis with Ruby
Try the free version of Progate [Java I]
[Java] How to get the URL of the transition source
I examined the life cycle of the extension of JUnit Jupiter
The world of clara-rules (2)
I tried using the Server Push function of Servlet 4.0
I read the readable code, so make a note
I was addicted to the record of the associated model
I tried to summarize the state transition of docker
I saw the list view of Android development collectively
I tried to reduce the capacity of Spring Boot
Judgment of the calendar
I tried the new feature profiler of IntelliJ IDEA 2019.2.
I want to know the answer of the rock-paper-scissors app
Image processing: The basic structure of the image read by the program
I want to display the name of the poster of the comment
I summarized the display format of the JSON response of Rails
The world of clara-rules (1)
The world of clara-rules (3)
Source of cellular objects
Read the Rails Guide (Overview of Action Controller) again
[Java] When writing the source ... A memorandum of understanding ①
I wrote a sequence diagram of the j.u.c.Flow sample
I summarized the types and basics of Java exceptions
The idea of quicksort
[WIP] I tried the configuration of Docker + Streama + NFS
I am keenly aware of the convenience of graphql-code-generator, part 2
I can't get out of the Rails dbconsole screen
I learned about the existence of a gemspec file
I want to be aware of the contents of variables!
I want to return the scroll position of UITableView!
The idea of jQuery
I didn't understand the behavior of Java Scanner and .nextLine ().
I took a peek at the contents of Java's HashMap
I tried to summarize the basics of kotlin and java
Now, I understand the coordinate transformation method of UIView (Swift)
I want to expand the clickable part of the link_to method
I want to change the log output settings of UtilLoggingJdbcLogger
[Swift] I tried to implement the function of the vending machine
After all, how should I attach the Constraint of ScrollView?
I tried JAX-RS and made a note of the procedure
Specify the character code of the source when building with Maven