JavaRush /Java Blog /Random-JA /8 から 13: Java バージョンの完全な概要。パート1
Константин
レベル 36

8 から 13: Java バージョンの完全な概要。パート1

Random-JA グループに公開済み
子猫たち、みなさん、こんにちは)) さて、今日から 2020 年になり、Java 14 のリリースまで残りわずかになりました。完成版は 3 月 17 日に公開されると思います。何が新鮮で興味深いのかは事後的に分析しますが、今日は Java の以前のバージョンについての記憶を新たにしたいと思います。彼らは私たちにどんな新しいものをもたらしてくれたのでしょうか?見てみましょう。Java 8 は依然として関連性が高く、ほとんどのプロジェクトで使用されているため、Java 8 からレビューを始めましょう。 8 から 13: Java バージョンの完全な概要。 パート 1 - 1以前は、新しいバージョンは 3 ~ 5 年ごとにリリースされていましたが、最近 Oracle は、「新しい Java を 6 か月ごとにリリースする」という異なるアプローチを採用しています。そのため、6 か月ごとに機能がリリースされます。良くても悪くても、人それぞれ捉え方が違います。たとえば、新しいバージョンには新しい機能があまりないため、これはあまり好きではありませんが、同時に雨後のキノコのようにバージョンが成長しています。Java 8 のプロジェクトで何度かまばたきしたのですが、Java 16 はすでにリリースされていました (しかし、まれにリリースされると、新しい機能が蓄積され、最終的にはこのイベントが休日のように待ち望まれます。誰もが、新しいグッズがあり、そこを通り過ぎることはできません)。それでは始めましょう!

Java 8

機能インターフェイス

これは何ですか?関数型インターフェイスは、1 つの未実装 (抽象) メソッドを含むインターフェイスです。 @FunctionalInterface は、そのようなインターフェイスの上に配置されるオプションのアノテーションです。関数インターフェイス (抽象メソッドが 1 つだけある) の要件を満たしているかどうかを確認する必要があります。ただし、いつものように、いくつかの注意点があります。デフォルト メソッドと静的メソッドはこれらの要件に該当しません。したがって、そのようなメソッドが複数存在し、抽象メソッドが 1 つ存在する可能性があり、インターフェイスは機能します。また、インターフェイスの機能定義に影響を与えない Object クラスのメソッドが含まれる場合もあります。デフォルトメソッドと静的メソッドについて少し追加します。
  1. デフォルト修飾子を備えたメソッドを使用すると、既存の実装を壊さずに新しいメソッドをインターフェイスに追加できます。

    public interface Something {
      default void someMethod {
          System.out.println("Some text......");
      }
    }

    はい、はい、実装されたメソッドをインターフェイスに追加します。このメソッドを実装するとき、それをオーバーライドすることはできませんが、継承されたメソッドとして使用します。しかし、クラスが特定のメソッドで 2 つのインターフェイスを実装している場合は、コンパイル エラーが発生します。また、クラスがインターフェイスを実装し、特定の同一のメソッドでクラスを継承している場合は、親クラスのメソッドがインターフェイス メソッドと重複して例外が機能しません。

  2. インターフェイス内の静的メソッドは、クラス内の静的メソッドと同じように機能します。子孫クラスから静的メソッドを呼び出すことができないのと同様に、静的メソッドを継承することもできないことを忘れないでください。

それでは、関数インターフェースについてもう少し説明して、次に進みましょう。以下に FI の主なリストを示します (残りはその種類です)。

    述語 - 値 T を引数として受け取り、ブール値を返します。

    例:boolean someMethod(T t);

  • Consumer - 型 T の引数を受け取り、何も返しません (void)。

    例:void someMethod(T t);

  • サプライヤー - 入力として何も受け取りませんが、値 T を返します。

    例:T someMethod();

  • 関数 - T 型のパラメータを入力として受け取り、R 型の値を返します。

    例:R someMethod(T t);

  • UnaryOperator - T 引数を受け取り、型 T の値を返します。

    例:T someMethod(T t);

ストリーム

ストリームは、関数型スタイルでデータ構造を処理する方法です。通常、これらはコレクションです (ただし、あまり一般的ではない他の状況でも使用できます)。よりわかりやすい言葉で言えば、Stream は、for-each のような総当たり的な方法ではなく、すべてのデータを同時に処理するかのように処理するデータ ストリームです。小さな例を見てみましょう。フィルタリングする一連の数値 (50 未満) があり、5 ずつ増やし、残りの数値から最初の 4 つの数値をコンソールに出力するとします。これをもっと早くに行うにはどうすればよいでしょうか:
List<Integer> list = Arrays.asList(46, 34, 24, 93, 91, 1, 34, 94);

int count = 0;

for (int x : list) {

  if (x >= 50) continue;

  x += 5;

  count++;

  if (count > 4) break;

  System.out.print(x);

}
コードがあまり多くないようで、ロジックがすでに少し複雑になっています。ストリームを使用してどのように見えるかを見てみましょう。
Stream.of(46, 34, 24, 93, 91, 1, 34, 94)

      .filter(x -> x < 50)

      .map(x -> x + 5)

      .limit(4)

      .forEach(System.out::print);
ストリームはコードの量を減らし、コードを読みやすくすることで作業を大幅に簡素化します。このトピックについてさらに詳しく知りたい方のために、このトピックに関する優れた (優れているとさえ言える) 記事をここに示します。

ラムダ

おそらく最も重要で待望されている機能は、ラムダの登場です。 ラムダとは何ですか? これは、さまざまな場所に渡すことができるコードのブロックなので、後で必要に応じて何度でも実行できます。かなりややこしいですね。簡単に言えば、ラムダを使用すると、関数型インターフェイスのメソッド (匿名クラスの実装の一種) を実装できます。
Runnable runnable = () -> { System.out.println("I'm running !");};

new Thread(runnable).start();
run() メソッドを不必要な煩雑な手続きなしで迅速に実装しました。そしてその通りです。Runnable は機能的なインターフェイスです。また、ストリームを操作するときにもラムダを使用します (上記のストリームの例のように)。かなり深く掘り下げることはできるので、あまり深くは説明しません。まだ根っからの探求者がさらに深く掘り下げることができるように、リンクをいくつか残しておきます。

フォーリーチ

Java 8 には、ストリームのようにデータ ストリームを操作する新しい foreach があります。以下に例を示します。
List<Integer> someList = Arrays.asList(1, 3, 5, 7, 9);

someList.forEach(x -> System.out.println(x));
(someList.stream().foreach(…) に似ています)

メソッドリファレンス

参照メソッドは、Java クラスまたはオブジェクトの既存のメソッドまたはコンストラクターを :: 経由で参照するように設計された、新しく便利な構文です。メソッド参照には 4 つのタイプがあります。
  1. デザイナーへのリンク:

    SomeObject obj = SomeObject::new

  2. 静的メソッドのリファレンス:

    SomeObject::someStaticMethod

  3. 特定の型のオブジェクトの非静的メソッドへの参照:

    SomeObject::someMethod

  4. 特定のオブジェクトの通常の (非静的) メソッドへの参照

    obj::someMethod

多くの場合、メソッド参照はラムダの代わりにストリームで使用されます (参照メソッドはラムダよりも高速ですが、可読性が劣ります)。
someList.stream()

        .map(String::toUpperCase)

      .forEach(System.out::println);
参照方法についてさらに詳しく知りたい方は:

API時間

日付と時刻を操作するための新しいライブラリ java.time が追加されました。 8 から 13: Java バージョンの完全な概要。 パート 1 ~ 2新しい API は他の Joda-Time と似ています。この API の最も重要なセクションは次のとおりです。
  • LocalDateは特定の日付 (例: 2010-01-09) です。
  • LocalTime - タイムゾーンを考慮した時間 - 19:45:55 (LocalDate に類似)。
  • LocalDateTime - LocalDate + LocalTime の組み合わせ - 2020-01-04 15:37:47;
  • ZoneId - タイムゾーンを表します。
  • 時計- このタイプを使用すると、現在の時刻と日付にアクセスできます。
このトピックに関する非常に興味深い記事をいくつか紹介します。

オプション

これはjava.utilパッケージの新しいクラスで、安全にnullを含めることができるという値ラッパーです。オプションの受信: Optional.ofOptional<String> someOptional = Optional.of("Something");nullを渡すと、お気に入りのNullPointerExceptionが発生します。そのような場合には、次のものが使用されます。 - このメソッドでは、null を恐れる必要はありません。次に、最初は空のオブジェクトを作成します。 オプション: 空かどうかを確認するには、次を使用します。 true または false が返されます。値がある場合は特定のアクションを実行し、値がない場合は何も実行しません: Optional が空の場合に渡された値を返すリバース メソッド (バックアップ プランのようなもの): 非常に長い間継続できます (幸いなことに、Optional は惜しみなくメソッドを追加しました) が、これについては詳しく説明しません。手始めに、いくつかのリンクを残しておくとよいでしょう。 Optional<String> someOptional = Optional.ofNullable("Something");Optional<String> someOptional = Optional.empty();someOptional.isPresent();someOptional.ifPresent(System.out::println);System.out.println(someOptional.orElse("Some default content")); Java 8 の最も有名なイノベーションについて説明しましたが、それだけではありません。さらに詳しく知りたい場合は、次のことを残しておきます。

Java9

そこで、2017 年 9 月 21 日、世界は JDK 9 を目にしました。この Java 9 には豊富な機能セットが付属しています。新しい言語概念はありませんが、新しい API と診断コマンドは開発者にとって間違いなく興味深いものとなるでしょう。 8 から 13: Java バージョンの完全な概要。 パート 1 ~ 4

JShell (REPL - 読み取り-評価-印刷ループ)

これは対話型コンソールの Java 実装であり、機能をテストしたり、インターフェイス、クラス、列挙型、演算子などのコンソール内のさまざまな構成要素を使用したりするために使用されます。JShellを起動するにはターミナルに jshell を記述するだけです。その後、想像力が許す限り何でも記述できます。JShell 8 から 13: Java バージョンの完全な概要。 パート 1 ~ 5を使用すると、トップレベルのメソッドを作成し、同じセッション内でそれらを使用できます。これらのメソッドは、 staticキーワードを省略できることを除いて、静的メソッドと同様に機能します。詳細については、 Java 9. REPL (JShell) マニュアルを参照してください。

プライベート

Java バージョン 9 以降、インターフェイスでプライベート メソッドを使用できるようになりました (アクセスが不十分なために他のメソッドをオーバーライドできないため、デフォルトおよび静的メソッド)。 private static void someMethod(){} try-with-resources Try-With-Resources 例外を処理する機能がアップグレードされました。
BufferedReader reader = new BufferedReader(new FileReader("....."));
  try (reader2) {
  ....
}

モジュール性 (ジグソー)

モジュールは、関連するパッケージおよびリソースと、新しいモジュール記述子ファイルのグループです。このアプローチは、コードの結合を緩和するために使用されます。疎結合は、コードの保守性と拡張性にとって重要な要素です。モジュール性はさまざまなレベルで実装されます。
  1. プログラミング言語。
  2. 仮想マシン。
  3. 標準の Java API。
JDK 9 には 92 個のモジュールが付属しており、それらを使用することも、独自のモジュールを作成することもできます。さらに詳しく見るためのリンクがいくつかあります。

不変のコレクション

Java 9 では、コレクションを不変にしつつ、1 行でコレクションを作成して埋めることができるようになりました (以前は、不変コレクションを作成するには、コレクションを作成し、それにデータを入れて、メソッドを呼び出す必要がありました。たとえば、 Collections.unmodifiableList)。そのような作成の例: List someList = List.of("first","second","third");

その他の革新:

  • Expanded オプション (新しいメソッドが追加されました)。
  • ProcessHandle インターフェイスと ProcessHandle インターフェイスは、オペレーティング システムの動作を制御するように見えました。
  • G1 - デフォルトのガベージ コレクター。
  • HTTP/2 プロトコルと WebSocket の両方をサポートする HTTP クライアント。
  • 拡張されたストリーム。
  • Reactive Streams API フレームワーク (リアクティブ プログラミング用) を追加しました。
Java 9 をより完全に理解するには、以下を読むことをお勧めします。

Java10

そのため、Java 9 のリリースから 6 か月後の 2018 年 3 月 (昨日のことのように覚えています)、Java 10 が登場しました。 8 から 13: Java バージョンの完全な概要。 パート 1 ~ 6

変数

これで、データ型を指定する必要がなくなりました。メッセージを var としてマークすると、コンパイラは右側に存在する初期化子の型によってメッセージの型を決定します。この機能は、初期化子を持つローカル変数でのみ使用できます。型を定義できる初期化子がないため、メソッドの引数、戻り値の型などには使用できません。var の例 (文字列型の場合):
var message = "Some message…..";
System.out.println(message);
var はキーワードではありません。本質的には、 int と同様に予約された型名です。varの利点は大きく、型宣言は何のメリットももたらさずに多くの注目を集めますが、この機能により時間を節約できます。しかし同時に、変数がメソッドの長いチェーンから取得される場合、そこにどのような種類のオブジェクトがあるのか​​すぐに不明瞭になるため、コードは読みにくくなります。この機能をさらに詳しく知りたい人向け:

JITコンパイラ(GraalVM)

早速ですが、javac コマンドを実行すると、Java アプリケーションが Java コードから JVM バイトコード (アプリケーションのバイナリ表現) にコンパイルされることを思い出してください。しかし、通常のコンピュータ プロセッサは、JVM バイトコードを単純に実行することはできません。JVM プログラムが動作するには、このバイトコード用の別のコンパイラーが必要です。コンパイラーは、プロセッサーがすでに使用できるマシンコードに変換されます。javac と比較すると、このコンパイラーははるかに複雑ですが、高品質のマシンコードも生成します。現在、OpenJDKには HotSpot 仮想マシンが含まれており、これには 2 つの主要な JIT コンパイラが含まれています。1 つ目の C1 (クライアント コンパイラ) は、より高速な動作を目的として設計されていますが、コードの最適化が困難になります。2 つ目は C2 (サーバー コンパイラ) です。実行速度は低下しますが、コードはより最適化されます。どちらはいつ使用されますか? C1 は、長い JIT 一時停止が望ましくないデスクトップ アプリケーションに最適であり、C2 は、コンパイルにより多くの時間を費やすことがかなり耐えられる、長時間実行されるサーバー プログラムに最適です。 マルチレベル コンパイルでは、コンパイルが最初に C1 を通過し、結果が C2 を通過します (より高度な最適化に使用されます)。 GraalVM は、HotSpot を完全に置き換えるために作成されたプロジェクトです。Graal は、HotSpot 用の新しい JIT コンパイラーと新しい多言語仮想マシンなど、いくつかの関連プロジェクトとして考えることができます。この JIT コンパイラーの特徴は、Java で書かれていることです。Graal コンパイラの利点は安全性です。つまり、クラッシュではなく、メモリ リークではなく例外が発生します。また、優れた IDE サポートも提供され、デバッガー、プロファイラー、その他の便利なツールを使用できるようになります。さらに、コンパイラは HotSpot から独立している可能性があり、それ自体のより高速な JIT コンパイル済みバージョンを作成できるようになります。 採掘者向け:

パラレル G1

G1 ガベージ コレクターが優れていることは間違いありませんが、シングル スレッドのフル GC サイクルを実行するという弱点もあります。未使用のオブジェクトを見つけるためにあらゆるハードウェアの能力が必要なときに、スレッドは 1 つに制限されます。Java 10 ではこの問題が修正され、GC は追加したすべてのリソースで動作するようになりました (つまり、マルチスレッドになります)。これを達成するために、言語開発者は GC からの主要なソースの分離を改善し、GC 用のきれいなインターフェイスを作成しました。この魅力の開発者である OpenJDK は、新しい GC の作成をできるだけ簡素化するだけでなく、アセンブリから不要な GC をすぐに無効にできるようにするために、特にコード内のダンプをクリーンアップする必要がありました。成功の主な基準の 1 つは、これらすべての改善を行った後に動作速度が低下しないことです。 こちらも見てみましょう: その他の革新:
  1. クリーンなガベージ コレクター インターフェイスが導入されました。これにより、さまざまなガベージ コレクターからのソース コードの分離が向上し、代替コレクターを迅速かつ簡単に統合できるようになります。
  2. JDK ソースを 1 つのリポジトリに結合します。
  3. コレクションは、このコレクションの不変のコピーを返す新しいメソッドcopyOf (Collection)を受け取りました。
  4. オプション(およびそのバリアント) には、新しいメソッド.orElseThrow()があります。
  5. 今後、JVM は Docker コンテナ内で実行されていることを認識し、オペレーティング システム自体にクエリを実行するのではなく、コンテナ固有の設定を取得します。
Java 10 をより詳しく説明するためのその他の資料を以下に示します。 私は、Java の一部のバージョンが 1.x と呼ばれているという事実に非常に混乱していました。明確にしておきたいのですが、9 より前の Java バージョンは、単に異なる命名スキームを持っていただけです。たとえば、Java 8 は1.8、Java 5 - 1.5などと呼ばれることもあります。そして、Java 9 からのリリースへの移行に伴い、命名スキームも変更され、Java バージョンの接頭辞が 1.x ではなくなっていることがわかります。 。これで最初の部分は終わりです。Java 8 ~ 10 の興味深い新しい機能について説明しました。次の投稿で最新情報を続けてみましょう。
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION