12
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

わたしがJavaの嫌なところ5選

Last updated at Posted at 2016-03-07

Java

昨年、20周年を迎えたJava。
最近は関数型言語が流行ってきたり、Script系言語でサッとつくることが多くなってきたので、使ってる人は、昔に比べると減ったのかなと思いますが、それでも、多いですよね。
20周年のイベントもたくさんあったりしました。
そんなJavaですが、まだまだ発展中です。「嫌い」という声も聞いたりします。
私が個人的に「嫌なところ」を書いてみたいと思います。

プリミティブ型が中途半端

プリミティブ型(int,long等)とそれを表現するクラス(java.lang.Integer, java.lang.Long等)の両方があるため、どちらを使おうか迷ったりします。また、その影響で混乱することがあります。
例えば、

  • int型
  • Integerクラス

がありますね。
IntegerクラスはImmutableなので、単純にIntegerクラスだけでいいとかいうわけではありませんが、いろいろ混乱します。
代表的なのはこんな例

java
public class IntegerSample {
  static public void main(String[] args){
    System. out.println("new Integer(100)" );
    Integer new100_1 = new Integer(100);
    Integer new100_2 = new Integer(100);
    System. out.println("  ==  :" + (new100_1 == new100_2 ));
    System. out.println("equals:" + new100_1 .equals(new100_2 ));
  }
}

これを実行すると

new Integer(100)
== :false
equals:true

ふむふむ。オブジェクトを==で比較してるので、こっちはfalseになるね。
じゃあ、少し変えて、こんなふうに。

java
public class IntegerSample {
  static public void main(String[] args){
    System. out.println("Integer.valueOf(100)" );
    Integer valueOf100_1 = Integer.valueOf(100);
    Integer valueOf100_2 = Integer.valueOf(100);
    System. out.println("  ==  :" + (valueOf100_1 == valueOf100_2 ));
    System. out.println("equals:" + valueOf100_1 .equals(valueOf100_2 ));
  }
}

Integerのオブジェクトをnewじゃなくて、Integer.valueOf()で取得するように変えました。
これを実行すると、

Integer.valueOf(100)
== :true
equals:true

あれ?trueだ。
ふーん、valueOfで取得すると、同じインスタンスになるのかー。ほんとかなー。確かめてみよう。
今度は、

java
public class IntegerSample {
  static public void main(String[] args){
    System. out.println("Integer.valueOf(1000)" );
    Integer valueOf1000_1 = Integer.valueOf(1000);
    Integer valueOf1000_2 = Integer.valueOf(1000);
    System. out.println("  ==  :" + (valueOf1000_1 == valueOf1000_2 ));
    System. out.println("equals:" + valueOf1000_1 .equals(valueOf1000_2 ));
  }
}

数字を100じゃなくて、1000にしてみた。
実行すると、

Integer.valueOf(1000)
== :false
equals:true

おー、今度はfalseだ。なんだこれ??
となったので、ソースコードを確認してみました。
すると、Integerクラスの中には、IntegerCacheという内部クラスがあり、-128~127までのIntegerクラスのオブジェクトがキャッシュされているではありませんか!
Integer.valueOf()で取得したときに、-128~127は同じインスタンスが返されて、それ以外の場合は別のインスタンスが返されています。
実は、Byteクラス、Shortクラス、Longクラスも同じように-128~127はXxxCacheという名前の内部クラスがあり、キャッシュされているのです!
もちろん、==じゃなくて、euqals()で比較するんだってはなしですが。このような実装になっていると、バグを発見しづらいことがあります。
※ただ、これは、「Javaの嫌なところ」じゃなくて、「Oracle Javaの嫌な実装」なんですけどね。
※この前、このバグを発見できなくて、悔しかったです。
※operatorのオーバーライドがあればなーと久しぶりに思いました。

日時のクラス群がカオス

最初からある、java.util.Dateクラス、JDK1.1で追加されたjava.util.Calendarクラス、そして、Java8で新たに導入されたjava.timeパッケージの仲間たち。
なかなかカオスです。
java.timeパッケージは新しい日時表現のクラス群として、登場してきました。java.util.Dateクラス、java.util.Calendarクラスの良くないところを改善して、導入されました(joda-timeという、日時を扱うライブラリをベースに導入されたようです)。
なので、こちらを使うことを推奨されていくと思います。
ただし、まだ導入するメリットはなかなか味わえないかなと感じています。
単純に時間を扱うだけであれば、java.timeパッケージを使った実装をすればよいですが、既存のライブラリやフレームワークを使う際には、java.timeパッケージに対応していなければ、せっかくjava.timeパッケージを使って実装していても、ライブラリやフレームワークとのやり取りの部分で変換しなければ使えません。
例えば、DBと日時のデータをやり取りする場合は、java.util.Data(たぶん、java.sql.Dateだったりしますが)と変換してあげなければなりません。めんどくさいですね。そして、せっかくjava.timeパッケージで処理してるのに、、、と思ってしまいます。
もう少し時間が経過して、java.timeパッケージが少し広まったとき、このライブラリはjava.timeパッケージで実装できるけど、こっちはjava.util.Dateだから、、、うーーん。。。ってなりそうです。

Stop The World

時間が止まります。
FullGCのときに。
まあ、それ自体は諦めてます。仕方ないと思ってます。
つらいのはStop The Worldが原因の問題が出るとき。対処方法が難しいのです。
Heapサイズを変えるとか、EdenとOldとサイズをチューニングするとか。GCのアルゴリズムを変えてみるとか。いろいろいろいろ。
これ!って対応方法を見つけるのがすごく難しいんですよね。

getter/setterをそろそろなんとかしてほしい

ずーーっと言われてますね。
最近はlombokがよく使われますが、それでもアノテーションを付けなければならないです。
このあたりの話をするとpublicでいいじゃないかとか論争がはじまることがよくあって、もーってなります。
※フレームワークがgetter/setterを要求することがおおいので、「publicでいいじゃないか論」はちょっと違うんじゃないかと思ってます。
そろそろ、アクセス修飾子の代わりにpropertyつければgetter/setterができるようになってほしいなぁと思うわけです。もちろん、getterだけ/setterだけができる修飾子もほしいです!

「JAVA」って書かれる

いや、別に、いいんですけど。
なんか、気持ち悪くて。
でも、公式も「あなたとJAVA」( https://www.java.com/ja/ )なんだよなぁ。
※公式はここ以外"JAVA"という表記見たことがない気がしますが、あるのかな?

まとめ

Java大好きです!
最初から「嫌い」なんて言ってないですよ。「嫌なところ」です。
今後とも、よろしくお願いします。Javaさん! :smile:

12
10
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?