1前書き

この記事では、面接中にポップアップする可能性があるJDK8関連の質問をいくつか探ります。

Java 8は、新しい言語機能とライブラリクラスが満載のプラットフォームリリースです。これらの新機能の大部分は、よりクリーンでよりコンパクトなコードを実現することを目的としており、一部の機能はJavaでサポートされたことのない新機能を追加します。


2 Java 8に関する一般的な知識

** Q1. Java 8で追加された新機能

Java 8にはいくつかの新機能が同梱されていますが、最も重要なものは以下のとおりです。


  • Lambda Expressions

    – 治療を可能にする新しい言語機能

オブジェクトとしてのアクション


メソッド参照** – 参照することでラムダ式を定義することを可能にします

名前を直接使ってメソッドに




オプション** – 選択性を表現するために使用される特別なラッパークラス


  • 機能的インターフェース

    – 最大1つの要約を持つインターフェース

方法、実装は、ラムダ式を使用して提供することができる。


デフォルトメソッド** – 完全な実装を追加する機能を私たちに与えてください。

抽象メソッド以外のインタフェース


Nashorn、JavaScriptエンジン** – 実行および実行用のJavaベースのエンジン

JavaScriptコードを評価する



Stream

API ** – 処理を可能にする特別なイテレータクラス

機能的な方法でオブジェクトの集合


Date API ** – 改良された不変のJodaTime風のDate API

これらの新機能に加えて、コンパイラレベルとJVMレベルの両方で、多くの機能強化が内部で行われています。

** 3メソッド参照

** Q1. メソッド参照とは

メソッド参照は、メソッドを呼び出さずにメソッドを参照するために使用できるJava 8構造です。メソッドをラムダ式として扱うために使用されます。それらはいくつかのラムダの冗長性を減らすために構文糖として働くだけです。このように、次のコード:

(o) -> o.toString();

になることができる:

Object::toString();

メソッド参照は、クラス名またはオブジェクト名とメソッド名を区切る二重コロンで識別できます。コンストラクタの参照など、さまざまなバリエーションがあります。

String::new;

静的メソッド参照

String::valueOf;

バウンドインスタンスメソッドのリファレンス:

str::toString;

非バインドインスタンスメソッドの参照

String::toString;


このリンク

とリンク:/java-8-doubleを使用すると、完全な例を使用してメソッド参照の詳細な説明を読むことができます。 -colon-operator[これ]。


Q2. String :: valueOf式の意味は何ですか?

これは、

String

クラスの

valueOf

メソッドへの静的メソッド参照です。


4オプション


Q1.

Optional

とは何ですか?どうやって使えますか?


Optional

は、Java 8の新しいクラスで、オプションの値、つまり存在しないか存在しない値をカプセル化します。それはオブジェクトを包むラッパーであり、あなたはそれを0個または1個の要素のコンテナとして考えることができます。


Optional

には、ラップされた

null

ではなく、特別な

Optional.empty()

値があります。そのため、null許容値の代わりにそれを使用して、多くの場合

NullPointerException

を取り除くことができます。

あなたは

Optional

linkに関する専用の記事を読むことができます:/java-optional[ここ]。

作成者によって設計された、

Optional

の主な目的は、以前は

null

を返すメソッドの戻り型になることでした。このような方法では、戻り値をチェックするための定型コードを記述する必要があり、場合によっては防御的なチェックを忘れる可能性があります。 Java 8では、

Optional

戻り型では、明示的にnullまたはnull以外のラップ値を異なる方法で処理する必要があります。

たとえば、

Stream.min()

メソッドは、一連の値から最小値を計算します。しかし、ストリームが空の場合はどうなりますか?それが

Optional

用ではない場合、メソッドは

null

を返すか、例外をスローします。

しかしそれは

Optional.empty()

かもしれない

Optional

値を返します(2番目のケース)。これにより、このような場合に簡単に対処できます。

int min1 = Arrays.stream(new int[]{1, 2, 3, 4, 5})
  .min()
  .orElse(0);
assertEquals(1, min1);

int min2 = Arrays.stream(new int[]{})
  .min()
  .orElse(0);
assertEquals(0, min2);


Optional

がScalaの

Option

のような汎用クラスではないことは注目に値します。エンティティクラスでフィールド値として使用することはお勧めできません。これは、

Serializable

インタフェースを実装していないことによって明確に示されています。


5機能インターフェース

** Q1. 標準ライブラリにいくつかの機能的なインタフェースを記述してください.


java.util.function

パッケージには多くの機能的なインターフェースがありますが、より一般的なものには以下が含まれますが、これらに限定されません。


  • Function

    – 引数を一つ取り、結果を返す


  • Consumer

    – 引数を1つ取り、結果を返しません(

副作用)
**

Supplier

– 引数を取らず結果を返す


  • Predicate

    – 引数を1つ取り、ブール値を返します


  • BiFunction

    – 2つの引数を取り、結果を返します


  • BinaryOperator

    – これは

    BiFunction

    に似ていますが、2つ取ります。

引数と結果を返します。 2つの引数と結果は
同じ種類のすべて
**

UnaryOperator

– これは

Function

に似ていますが、単一の

引数と同じ型の結果を返す

機能インターフェースの詳細については、記事リンク/java-8-functional-interfaces[“ Java 8の機能インターフェース”]を参照してください。


Q2. 機能的なインターフェースとは何ですか?機能インターフェースを定義するための規則は何ですか?

機能的なインターフェースとは、抽象メソッドが1つだけで、それ以上、決して少なくないインターフェースです(

default

メソッドはカウントされません)。

そのようなインターフェースのインスタンスが必要な場合は、代わりにラムダ式を使用できます。より正式な言い方をすると、

関数型インタフェース

は、ラムダ式とメソッド参照のターゲット型を提供します。

そのような式の引数と戻り値の型は、単一の抽象メソッドのものと直接一致します。

たとえば、

Runnable

インタフェースは機能的なインタフェースです。

Thread thread = new Thread(new Runnable() {
    public void run() {
        System.out.println("Hello World!");
    }
});

あなたは単にすることができます:

Thread thread = new Thread(() -> System.out.println("Hello World!"));

機能インターフェースは通常

@ FunctionalInterface

アノテーションが付けられています。


6. デフォルトの方法

** Q1. デフォルトのメソッドとは何ですか?またいつ使用しますか?

デフォルトメソッドは、実装を持つメソッドです。これは、インタフェースにあります。

デフォルトのメソッドを使用して、すでにインタフェースを実装しているクラスとの下位互換性を維持しながら、インタフェースに新しい機能を追加できます。

public interface Vehicle {
    public void move();
    default void hoot() {
        System.out.println("peep!");
    }
}

通常、新しい抽象メソッドがインタフェースに追加されると、すべての実装クラスは新しい抽象メソッドを実装するまで中断します。 Java 8では、この問題はデフォルトのメソッドを使用することで解決されています。

たとえば、

Collection

インターフェースには

forEach

メソッド宣言はありません。したがって、そのようなメソッドを追加すると、単にコレクションAPI全体が壊れることになります。

Java 8ではdefaultメソッドが導入されているので、

Collection

インタフェースはこのインタフェースを実装するクラスに同じ実装を要求することなく

forEach

メソッドのデフォルト実装を持つことができます。


Q2. 次のコードはコンパイルされますか?

@FunctionalInterface
public interface Function2<T, U, V> {
    public V apply(T t, U u);

    default void count() {
       //increment counter
    }
}

はい。このコードは、単一の抽象メソッドのみを定義するという機能インターフェース仕様に準拠しているため、コンパイルされます。 2番目のメソッド

count

は、抽象メソッドの数を増やさないデフォルトのメソッドです。


7. ラムダ式


Q1. ラムダ式とは何ですか?またそれは

に使用されます.

非常に簡単に言うと、ラムダ式はオブジェクトとして参照したり渡したりできる関数です。

ラムダ式は、Javaで機能スタイル処理を導入し、コンパクトで読みやすいコードの記述を容易にします。

このため、ラムダ式はメソッドの引数として無名クラスの代わりになります。それらの主な用途の1つは、機能的インターフェースのインライン実装を定義することです。


Q2. ラムダ式の構文と特性を説明する

ラムダ式は、2つの部分から構成されます。パラメータ部分と式部分は、下のように前向き矢印で区切られています。

params -> expressions

すべてのラムダ式には、次のような特徴があります。


  • オプションの型宣言

    – でパラメータを宣言するとき

ラムダの左側では、その型を次のように宣言する必要はありません。
コンパイラはそれらの値からそれらを推測できます。だから

int param – > …​

and

param – > …​

はすべて有効です


オプションの括弧** – 単一のパラメータしか宣言されていない場合は、

かっこで囲む必要はありません。これは

param – > …​

そして

(param) – > …​

はすべて有効です。しかし、複数のパラメータが
宣言、括弧は必須


省略可能な中括弧** – 式の部分が1つしかない場合

ステートメント、中括弧は必要ありません。これは

param – >を意味します
statement



param – > \ {statement;}

はすべて有効です。しかし中括弧
複数のステートメントがある場合は必須


オプションのreturn文** – 式が値を返すとき

中括弧で囲まれているので、returnステートメントは必要ありません。つまり、

(a、b) – > \ {return a b;}



(a、b) – > \ {a b;}

はどちらも有効です。

Lambda式の詳細については、https://www.tutorialspoint.com/java8/java8

lambda

expressions.htm[このリンク]および

this one

を参照してください。


8 Nashorn Javascript


Q1. Java 8のNashornとは何ですか?


Nashorn

は、Java 8に同梱されているJavaプラットフォーム用の新しいJavascript処理エンジンです。JDK7まで、Javaプラットフォームは同じ目的でMozilla Rhinoを使用していました。 Javascript処理エンジンとして。

Nashornは、ECMAの正規化されたJavaScript仕様への準拠性が向上し、以前のバージョンよりも優れたランタイムパフォーマンスを提供します。


Q2. jjsとは何ですか?

Java 8では、

jjs

はコンソールでJavascriptコードを実行するために使用される新しい実行可能ファイルまたはコマンドラインツールです。


9ストリーム


Q1. ストリームとはコレクションとはどう違うのですか?

簡単に言うと、ストリームとはイテレータであり、その役割は一連のアクションを受け取ってそれに含まれる各要素に適用することです。


The stream

は、集約操作をサポートするコレクションなどのソースからの一連のオブジェクトを表します。それらは、コレクション処理を単純かつ簡潔にするように設計されています。コレクションとは反対に、繰り返しのロジックはストリーム内に実装されているので、宣言的な処理を実行するために

map



flatMap

などのメソッドを使用できます。

もう1つの違いは、

Stream

APIが流暢でパイプライン化が可能であることです。

int sum = Arrays.stream(new int[]{1, 2, 3})
  .filter(i -> i >= 2)
  .map(i -> i **  3)
  .sum();

また、コレクションとのもう1つの重要な違いは、ストリームは本質的に遅延ロードおよび処理されることです。


Q2. 中間操作と最終操作の違いは何ですか?

ストリーム操作はパイプラインにまとめられてストリームを処理します。すべての操作は中間または端末のいずれかです。

中間操作は

Stream

自体を返す操作で、ストリームに対するそれ以降の操作を可能にします。

これらのオペレーションは常に怠惰です、すなわち、それらはコールサイトでストリームを処理しません、中間オペレーションは端末オペレーションがあるときだけデータを処理することができます。中間操作には、

filter



map

、および

flatMap

があります。

端末操作はパイプラインを終了し、ストリーム処理を開始します。端末操作呼び出し中に、ストリームはすべての中間操作を通過します。端末操作には、

forEach



reduce、Collect

、および

sum

があります。

この問題を解決するために、副作用のある例を見てみましょう。

public static void main(String[]args) {
    System.out.println("Stream without terminal operation");

    Arrays.stream(new int[]{ 1, 2, 3 }).map(i -> {
        System.out.println("doubling " + i);
        return i **  2;
    });

    System.out.println("Stream with terminal operation");
        Arrays.stream(new int[]{ 1, 2, 3 }).map(i -> {
            System.out.println("doubling " + i);
            return i **  2;
    }).sum();
}

出力は次のようになります。

Stream without terminal operation
Stream with terminal operation
doubling 1
doubling 2
doubling 3

ご覧のとおり、中間操作は端末操作が存在するときにのみトリガーされます。


Q3.

map



flatMap

ストリーム操作の違いは何ですか?


map



flatMap

の間には署名に違いがあります。

一般的に言って、

map

操作はその戻り値をその序数型の内側にラップしますが、

flatMap

はしません。

たとえば、

Optional

では、

map

操作は

Optional <String>

typeを返し、

flatMap



String

typeを返します。

そのため、マッピング後に値を取得するには、オブジェクトをラップ解除(「フラット化」)する必要がありますが、フラットマッピング後は、オブジェクトが既にフラット化されているため、そのような必要はありません。

Stream

のマッピングとフラットマッピングにも同じ概念が適用されます。


map



flatMap

はどちらも、関数を受け取り、この関数をストリームのすべての要素に適用する中間ストリーム操作です。

違いは、

map

の場合、この関数は値を返すのに対し、

flatMap

の場合、この関数はストリームを返すことです。

flatMap

操作は、ストリームを1つに「平坦化」します。

これは、ユーザーの名前と電話のリストのマップを作成し、

flatMap

を使用してすべてのユーザーの電話のリストに「平坦化」する例です。

Map<String, List<String>> people = new HashMap<>();
people.put("John", Arrays.asList("555-1123", "555-3389"));
people.put("Mary", Arrays.asList("555-2243", "555-5264"));
people.put("Steve", Arrays.asList("555-6654", "555-3242"));

List<String> phones = people.values().stream()
  .flatMap(Collection::stream)
    .collect(Collectors.toList());


Q4. Java 8のストリームパイプライン化とは何ですか?

ストリームパイプライン化は、操作を連鎖させるという概念です。これは、ストリームで発生する可能性がある操作を2つのカテゴリ(中間操作と端末操作)に分割することによって行われます。

各中間操作は、実行時にStream自体のインスタンスを返すため、処理パイプラインを形成するデータを処理するために任意の数の中間操作を設定できます。

その後、最終値を返してパイプラインを終了させる端末操作が必要です。


10 Java 8 Date and Time API


Q1. Java 8

の新しいDate and Time APIについて教えてください.

Java開発者にとって長年の問題は、通常の開発者が必要とする日付と時刻の操作に対するサポートが不十分であることです。


java.util.Date



SimpleDateFormatter

などの既存のクラスはスレッドセーフではないため、ユーザーに同時実行性の問題が生じる可能性があります。

貧弱なAPI設計は、古いJava Data APIでも現実的です。これは簡単な例です –

java.util.Date

の年は1900年、月は1、日は0から始まります。

これらの問題および他のいくつかの問題により、Joda-Timeなどのサードパーティ製の日付と時刻のライブラリの人気が高まっています。

これらの問題に対処し、JDKでより良いサポートを提供するために、これらの問題がない新しい日時APIがパッケージ

java.time

の下でJava SE 8用に設計されました。

** 11結論+

**

この記事では、Java 8に偏りがある技術面接の質問について、いくつかの非常に重要な質問を取り上げました。 8。

あなたがたった今立ち上がったばかりであっても、Java 8を知らないことは、特にJavaがあなたの履歴書に強く現れているときには、インタビューに参加するのに良い方法ではありません。したがって、これらの質問に対する答えを理解し、さらに研究を進めるために時間をかけることが重要です。

あなたのインタビューで頑張ってください。




  • «** 前へ