1. 構文糖

プログラマーは、複雑なコードやロジックを数行で記述でき、コードがコンパクトで読みやすくなることを歓迎します。そして、プログラミング言語の作成者がこれを支援することがあります。

ショートカットを実行できる (コードの記述量を減らす) ことができる洗練された言語機能は、構文シュガーと呼ばれます。しかし、正直に言うと、Java にはそのような機能はほとんどありません。

Java の作成者は、Java の冗長性を排除するためにあらゆる手を尽くしました。C++ で 20 の方法で何かを実行できる場合、Java では 1 つの方法でのみ実行できます。

しかし、Java プログラマーも Java の作成者も、自由がないことを好みませんでした。そして時々、砂糖はあなたや私のような普通の人々の生活を楽にしてくれます。

ところで、すでにオートボックス化アンボックス化という糖衣構文に遭遇しました。比較してみましょう:

ロングコード コンパクトなコード
Integer a = new Integer(5);
int b = a.intValue();
Integer a = 5;
int b = a;
int b = 5;
Integer c = new Integer(b);
int b = 5;
Integer c = b;
Integer a = new Integer(1);
int b = 1;
if (a.intValue() == b)
{
   ...
}
Integer a = 1;
int b = 1;
if (a == b)
{
   ...
}

左側のような長いコードの代わりに、右側のよりコンパクトなコードを作成できます。また、インテリジェントなJava コンパイラは、コードの短縮バージョンに基づいてコードの詳細バージョンを生成します。これはまさに糖衣構文です。


2. 変数の型の推論:varキーワード

Java 11 では、コンパイラがさらに賢くなり、宣言された変数の型を、それに割り当てられた値の型に基づいて判断できるようになりました。コードでは次のようになります。

var name = value;

ここでname、 は新しい変数の名前、valueはその初期値、そして はvar変数を宣言するために使用されるキーワードです。name変数の型は、それに割り当てられた値の型と同じになります。

例:

コードの見方 コンパイラが認識するもの
var i = 1;
int i = 1;
var s = "Hello";
String s = "Hello";
var console = new Scanner(System.in);
Scanner console = new Scanner(System.in);
var list = new ArrayList<String>();
ArrayList<String> list = new ArrayList<String>();
var data = new int[]{1, 2, 3};
int[] data = new int[]{1, 2, 3};

コンパイラ自体は、変数に割り当てられた値に基づいて変数の型を決定または推論します。

プログラマーたちは、そのような機能を言語に追加するかどうかについて激しく議論しました。多くの人は、これがvar悪用され、結果としてコードの可読性が低下するのではないかと懸念していました。

varこれには一面の真実があるため、コードの可読性を高める場合に使用するのが最善です。たとえば、次の 2 つの場合があります。

ケース 1: 変数に割り当てられた値を見ると、変数の型がすぐにわかります

コード 説明
var stream = url.getInputStream();
変数はInputStream
var name = person.getFullName();
変数はString

このような場合、を使用すべきではありませんvar。さて、変数の型は何でしょうか?

コード 説明
var result = task.execute();
変数の型を判断するのが難しい
var status = person.getStatus();
変数の型を判断するのが難しい

ケース 2: コードを理解する上で変数の型は重要ではありません

変数が単に何かを一時的に格納するために使用される場合など、コードでは変数のメソッドを呼び出す必要がないことがよくあります。この場合、var確実に使用してもコードの可読性は低下しません。

ロングコード コンパクトなコード
var data = stream.getMetaData();
storage.save(data)
ストリームからメタデータを取得しstream、リポジトリに保存しましたstorage。変数dataの特定の型は重要ではありません。

黄金の平均

ここで、同じコードを記述する 3 つの方法を紹介します。を使用するのvarが最良の選択肢でしょう。

コード ノート
dest.writeHeaderInfo(src.getFileMetaInfo());
コンパクトすぎる
var headerInfo = src.getFileMetaInfo();
dest.writeHeaderInfo(headerInfo);
ちょうどいい
FileMetaInfo headerInfo = src.getFileMetaInfo();
dest.writeHeaderInfo(headerInfo);
詳細すぎる

headerInfo1行バージョンから2行バージョンに移行し、変数名( )を使用することでコードを少し読みやすくしました。これで、このメソッドがメタ情報だけでなくヘッダー情報も返すことがわかりました。

3 番目のバージョンは冗長すぎます。headerInfoであるという事実は、メソッドFileMetaInfoからすでにかなり明らかですgetFileMetaInfo()。メタ情報の目的はさらに興味深いものです。



3. ダイヤモンド演算子を使用して型を省略します。<>

演算子が登場する前からvar、コレクション型を推論する方法をコンパイラーに教えようという試みがありました。この表記が少し冗長に見えることに同意されるでしょう。

ArrayList<String> list = new ArrayList<String>();

Java の第 7 バージョン以降、コレクション型を記述するときに、変数の宣言時にコレクション要素の型が指定されている場合は、その型を省略できるようになりました。言い換えれば、上記のコードは少し省略した形式で書くことができます。

ArrayList<String> list = new ArrayList<>();

ご覧のとおり、String を再度記述する必要はなくなりました。var 演算子ほどクールではありませんが、当時は進歩しているように思えました。

コレクション型の空の山括弧は、2 つの山括弧がなんとなくダイヤモンドに似ているため、ダイヤモンド演算子と呼ばれました。

varキーワードとダイヤモンド演算子を 同時に使用することは望ましくありません。

var list = new ArrayList<>();

コレクションに格納される要素の型に関する情報はまったくなく、コレクションの型はArrayList < Object > になります。



4. 二重中括弧

配列のクイック初期化を覚えていますか?

次のように、中括弧内に値をリストしました。

int[] data = new int[] {1, 2, 3, 4, 5, 6, 7};
int[] data = {1, 2, 3, 4, 5, 6, 7};

Java の作成者は、中括弧を使用して配列の要素の記述を簡略化するというアイデアを気に入りました。しかし、コレクションについてはどうでしょうか?

Java の作成者はコレクションに対しても十分な創造的思考を持っていたため、二重中括弧を使用したトリックを使用することができました。

砂糖と一緒に ノンシュガーで
var list = new ArrayList<String>()
{{
   add("Hello");
   add("How's");
   add("Life?");
}};
var list = new ArrayList<String>();

list.add("Hello");
list.add("How's");
list.add("Life?");

コンパイラーは、左側の例のようなコードを検出すると、それを右側のコードに変換します。

コードはそれほどコンパクトにはなりません。listここでの節約効果は非常にわずかです。毎回書き込む必要はありません。これは、変数名が非常に長い場合に役立ちます。

ただし、プロジェクト内でこのようなコードに出会っても、驚かないでください :