[JAVA] I didn't understand the difference between Collections.emptyMap and Collections.EMPTY_MAP and my colleague got angry so I'll write it down here for self-discipline.

This article is a reprint of a blog post. https://munchkins-diary.hatenablog.com/entry/2018/11/14/034818

Good evening, I'm a Java / Scala developer who became a JVM lover after learning how the C1C2 compiler works. (My name is not stable) Today (or yesterday), my colleague pointed out, and for the first time I realized the difference in the empty map of Collections properly, so I will post it here with the meaning of the next time. It's been a long time since I first wrote Java, but it was a good study because I didn't know it at all even though it was very rudimentary.

First from the conclusion

The main subject and the explanation after that are long, so I will write from the conclusion first. Collections.emptyMap: Unless row type is used for the type of variable or return value, it is cast to the type specified in the method and is type safe. `` **Collections.EMPTY_MAP:** Since it is a row type canonical object, there is no type specification in the generics and it is not type safe. ``

It is also properly described in Oracle's official JavaDoc. https://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#emptyMap%28%29

Unlike this method, the field does not provide type safety. (Unlike this method, the field (EMPTY_MAP) is not type safe.)

(See later for a discussion of the question why both methods and constants have the same purpose.)

Gudaguda and a long subject and how he got angry

After lunch, I was skimming through O'Reilly's microservices architecture at my desk, and I received a somewhat disturbing Slack message from a foreign colleague working in Japan (let's call it Linus).

Linus: My profile says on Vacation, but are you still on vacation? Me: My heart is on vacation endlessly ... (I'm lying back) What's wrong? La: No, your code is so terrible that you want to cry ... Me: Hey ... La: Don't you think it's garbage when you see it for yourself? Me: I don't think it's a problem for Repository ... La: Repository Hey ...

It is a swordsman in the middle. (In his honor, he uses this wording only technically, especially for silly mistakes and dirty code, but it's usually the most gentle and humorous nice ~~ Geek ~~ Guy)

To make an excuse, I knew that there were some problems because it was the class I wrote when I was driving in the previous term, but I didn't think it was such a terrible design. He is the leader of the back-end team and is quite busy, so I asked him to give me feedback in his spare time and he broke up. In the evening, when the work had settled down to some extent, he sent me another message.

Linus: Did you notice any problems in that class?

I raised design issues as much as I could think of and waited for his reaction. But what came back from him was a simpler answer.

No, you know, do the basics first before saying such a big deal.

  1. ʻImmutableMap.Builder retvalBuilder = ImmutableMap. <String, T> builder (); `This is raw type
  2. Do you know the difference between return Collections.EMPTY_MAP; and return Collections.emptyMap ();?
  3. return this.getXXXByIds (Arrays.asList (id)). getOrDefault (id, null); You're mentioning NPE in JavaDoc, but you're not handling nulls properly. Why don't you return Optional? In the first place, getOrDefault (x, null) and get (x) are the same.

As for 1 and 3, the moment I saw them, I was ashamed to blush. I want to enter if there is a hole. I have no choice but to be honest. I will expose it here with the meaning of reflection. After all, the basic thing to say is that I myself repeatedly teach juniors working in other countries in reviews. However, I didn't think that 2 was a problem at all. After all, Collections.EMPTY_MAP is canonical and immutable. I thought it would be better to use a canonical object (although it's an error) because it's more memory friendly if it doesn't change anyway.

However, when I read JavaDoc, the meaning became clear. It's written properly, there is a danger of using EMPTY_MAP for the return value.

Unlike this method, the field does not provide type safety. (Unlike this method, the field (EMPTY_MAP) is not type safe.)

Yes, it's not type-safe, EMPTY_MAP. We Java programmers live protected by the powerful typing function of Java. Programmers who write atypically secure code are as immature as junior high school students in the rebellious period, who live under the protection of their parents and despise their parents.

(I'm sorry I said too much)

Well, why are there two constants and methods even though it's not Singlton in the first place?

Collections.EMPTY_MAP should be an unnecessary constant by the current standards, but I found out why by looking at the released version.

** Collections.EMPTY_MAP was released in Java3, and Collections.emptyMap was released in Java5. ** **

Generics sits down with the face that it's been around for a long time now, but this feature was introduced into Java quite recently in Java5. (When I started Java, I couldn't specify the type, so I cast it one by one.)

In other words, Collections.EMPTY_MAP was created as a canonical object with no type specification because it was created in an era without generics, but since generics were lifted in Java 5, a more type-safe Collections.emptyMap method was created. I would say that. Of course, the standard library must be backwards compatible, so Collections.EMPTY_MAP is still running around the field energetically.

…… But honestly, I wonder if this can be used. The fact that it is not specified as Deprecated probably has a intended use, but I personally don't know how to use it correctly in Java today. If anyone knows, please let me know in the comments.

Summary

The constants of the Collections class, EMPTY_MAP, are non-type safe and the emptyMap method is type safe. So basically it is safer to create an empty Map with the emptyMap method for Java 5 and above.

It's a small thing, but I and Linus have the utmost respect for Java and the JVM (and all languages, infrastructure, and OS developers), so these small mistakes should be angry enough. I recognize that. It's been quite a while since I started writing Java, but there are still many things I don't know, and I feel that it's a really rewarding language to study.

By the way, regarding the microservice architecture mentioned at the beginning, I will write another article on my blog and Qiita, so I will publish it at a later date.

It's a summary that has nothing to do with the main subject, well. Then!

Recommended Posts

I didn't understand the difference between Collections.emptyMap and Collections.EMPTY_MAP and my colleague got angry so I'll write it down here for self-discipline.
I don't understand the devise_parameter_sanitizer method, so I'll output it here.
I don't really understand the difference between swift Error and NSError, so I tried to summarize it myself.
Understand the difference between each_with_index and each.with_index
[iOS] Understand the difference between frame and bounds
Understand the difference between abstract classes and interfaces!
I didn't understand the topological sort, so I looked it up and implemented it in BFS, and then tried to solve the AtCoder problem.
[Rails] I learned about the difference between resources and resources
[Rails] I investigated the difference between redirect_to and render.