Javaがクソなのは今に始まった話ではないのだが、Java 7でさらにクソミソになるようだ。
New language features in Java 7 « JoeJag :: Tech
Java 7にはDiamond Operatorなるものがある。
アイディアとしてはこうだ。いままでは、こんな風に書かなければならなかった。
Map<String, List<String>> anagrams = new HashMap<String, List<String>>();
これは、どう見ても冗長で無駄だ。モダンな言語をみるに、C++0xのautoといい、C#のvarといい、これらの冗長なコードを回避できる方法を提供している。時代遅れで池沼のJavaも、なんとかC++やC#のマネごとをしたかったものとみえる。連中の解決方法は以下の通り。
Map<String, List<String>> anagrams = new HashMap<>();
わー、ボク、よくできまちたねー。ナデナデ。
連中は何考えているんだろう。C++もC#も、型を右側に記述し、代入する変数に、わざわざ型を記述しなくてもすむようにしているのだ。なぜなら、式の結果の型を、コンパイラは決定できるからなのだ。しかし、Java 7は、依然として変数の型を指定しなければならないことに変わりない。何も変わっていないのである。
どっかの掲示板でC♯に似たような構文を要望してる人たちがいましたよ。
ReplyDeleteこんな感じ
List<string> = new();
左側に型を書きたがる人種は一定量いるようです。
そういう人たちにはウケるんじゃないでしょうか。
>どっかの掲示板でC♯に似たような構文を要望してる人たちがいましたよ。
ReplyDelete似た話を読んだことがあります.以前少しまとめたものがこの辺に.
http://d.hatena.ne.jp/NyaRuRu/20090906/p1
http://d.hatena.ne.jp/NyaRuRu/20080730/p1
なお,この書き方を推論ルールとして導入すると,自然と Foo(new(), new(), new()) という構文も許されることになるわけですが,そこまで考えて List<string> = new(); の導入を主張している人はほとんど居ない,というのが個人的な印象です.
C#もC++もどういう仕
ReplyDelete組みなのか知らないのですが...
静的な型付けを行う言語で型を明示する、というJavaの書き方には特に違和感がありません。
以降の処理では、オブジェクトはanagramsの型であるMap<String,
List<String>>として振舞うので、これを省略できない、というのはもっともだと考えます。
一方で、右辺の new HashMap<>() については、Map<String,
List<String>>に代入可能なオブジェクトを生成しようとしていることが推論できる(代入できない
ことをしようとしているのならコンパイルエラー)ので、略記できるようにするのも妥当なところだと思います。
「変数の型を指定しなければならない」のではなくて、変数の型を指定することこそが重要なのだと思います。
逆にJavaしか知らない者からすると、むしろ「代入する変数に、わざわざ型を記述しなくてもすむ」ことにどんなメリットがあるのか
わからないです。
型推論というより、簡単な変数宣言と同時に代入する際のマクロみたいなかんじなんですしょうか。
ReplyDeletevar map = new HashMap<String, String>()
ReplyDeleteと
Map<String, String> map = new HashMap<>();
はそもそも意味が違う。
上は左辺も右辺も同じ型だが、下は右辺値が左辺に代入可能な型を持っている
だけで、map自身はあくまでMapインターフェース型として解釈される。
ローカル変数ならvarで問題ないけど、フィールド(インスタンス変数)や静的
フィールド(クラス変数)だと、varでは不味いことが起き得る。
class Hoge {
private var map = new HashMap<String, String>();
void replaceMap(Map<String, String> newMap) {
map = newMap; // ← mapがHashMapなので代入できない。
// 実体がHashMapならキャストすればいいけど、TreeMapだったら?
}
}
class Hoge {
private Map<String, String> map = new HashMap<>();
void replaceMap(Map<String, String> newMap) {
map = newMap; // ← これならOK。
}
}
https://sourceforge.jp/users/egtra/
ReplyDeleteC++とC#ではメンバ変数・フィールドにautoやvarを認めていません。その点で、フィールドでも使えるJavaの提案は1つの利点だと思っています(C++/C#の制限によるもののため本質的な利点ではありませんが)。そもそも、自分は必要とあらば、var t = (IAbstractHoge)CreateHogeImpl();などと型推論+キャストを書く人間ですが。
さて、それはともかく私はMap<String, List<String>> anagrams = new HashMap<>();と右側を省略することに、左側を省略するC++/C#のauto/varほど魅力を感じません。var/autoはvar x = obj.GetHoge();のように関数・メソッドの戻り値を受けるときに型名を省略できますが、Javaの方式ではそれは叶わないからです。Javaだと代わりにNyaRuRuさんのおっしゃるようにFoo(new(), new(), new())とこっちで省略できるようになるのですが、戻り値ほど魅力を感じません、たいていは変数やnewだけでない式を渡すのですから。
ただ、Java方式もauto/varほど魅力的ではないというだけで、C++のmake_pair/make_tuple/make_sharedなど、C#でも.NET 4のTuple.Createなどの一般化と考えれば(推論元が変化していますが)、言語に組み込むことを考える価値はあると思います、auto/varと比べるような機能ではないというだけで。
ごめんなさい。make_sharedは関係ありませんでした。あと、sourceforge.jpのURLも本文とは無関係です(OpenIDの欄と間違えました)。
ReplyDeleteそういえば
ReplyDeletehttp://www.infoq.com/jp/news/2016/04/java-inference
JavaでもC++みたいな推論をやろうみたいな話が最近出てましたね、その後どうなったかしらんけど