0
0

More than 3 years have passed since last update.

気になるとこ

Last updated at Posted at 2019-12-16

1章

■hashCodeメソッド

・hashCodeメソッドとは

①オブジェクトの識別に使用されるint型のハッシュ値を生成して返すメソッド
②Objectクラスにおけるデフォルトの実装では、メモリアドレスを基に値が生成される。

・用途

オブジェクトを検索する際のパフォーマンスを向上させる目的で使用される。(HashMapやHashtable,HashSetなどではオブジェクト検索の際にequalsメソッドとhashCodeメソッド呼び出しに返されるハッシュ値を使用している)

・主なハッシュ生成アルゴリズム

・MD5、SHA
(ハッシュ値には一般的に「不可逆性」や「一方向性」という性質があり、理論上では生成されたhash値からは元データを推測できない。)

・ハッシュの用途

・改ざん検知(誤り検出)
・電子署名
(主にセキュリティー分野で利用される)

・hashCodeの実装ルール

・equalsメソッドのセマンティクスと同期している必要がある。
①equalsメソッドによって等しいとされる2つのオブジェクトは必ず同じ値を返す必要がある。
②equalsメソッドによって等しくないとされる2つのオブジェクトは必ずしも異なる値を返さなくてもいい。(hashCodeメソッドが等しくない場合equalsメソッドもfalseを返す必要がある。)
③equalsメソッドが判定の基準に用いているフィールド値が変更されていない限り、hashCodeメソッドが返す値は常に同じであること。

■不変クラス(Immutable Class)

・不変クラス(Immutable Class)とは

・不変 = Immutable
・Immutable = 状態が変更されないことを保証。
・そのクラスから生成された不変クラスのインスタンスにおいてフィールド値を変更できないように設計されたクラス

・主な不変(Immutable)クラス

・java.lang.String
・jaavx.lang.Integerやプリミティブ型ラッパー・クラス
・java.BigDecimal
・java.awt.Color
・Date and Time APIにおける日時を表すクラス

不変クラスに設計されたクラスのメリット

・意図せず状態が変更されてしまうことによる潜在的なバグを防ぐことができる
・オブジェクトをキャッシュして共有するような場合に値が変更されないことが保証されるため、安全に利用可能
・マルチスレッド・アプリケーションで利用する場合、スレッド・セーフなオブジェクトとして利用できる。

不変クラス(Immutable Class)の設計指針

①クラス・・・継承されないようにfinal宣言する。
②すべてのフィールド・・・外部からアクセス不可とし、設定された値を変更されないように、private final宣言する。
③アクセサメソッド・・・ゲッターメソッドのみ提供し、セッターメソッドやフィールドを設定できるような、いかなるメソッドも提供しないようにする。
④配列やコレクションなどの可変コンテナ・クラス(保持する要素を変更可能なクラス)や可変クラスへの参照を外部に公開しないようにする。
⑤this参照を外部に公開しないようにする。

■多重継承問題

デフォルトメソッドの競合

インターフェースがデフォルトメソッドを実装できるようになったことにより、
多重実装(継承)時にインターフェースのdefaultMethodのシグニチャが同じ場合メソッドの強豪が発生する(コンパイルエラーが発生する)。
※インターフェースの抽象メソッドはシグニチャが同じでも関連性のあるメソッドとされ、競合は発生しない(コンパイルエラーにならない)。
これを回避するには、実装側で競合しているメソッドをオーバーライドすることによってコンパイラにオリジナルのメソッドだと宣言できる。

ダイヤモンド継承問題(菱形継承問題)

型構成がダイヤモンド(菱形)の場合もメソッドの競合によりコンパイルエラーが発生する。
しかし、片側でメソッドがオーバーライドされている場合はそのメソッドが継承される。
つまり、メソッドが競合した際には型階層においてより距離が近いメソッドが優先され適用されるため、コンパイルエラーは発生しない。

■enumクラス(列挙型)の基本

・フィールドやメソッドを宣言した場合はそれよりも前に列挙定数は記述し、最後の列挙定数にセミコロンを記述する。
・列挙定数は暗黙的に「public static final」なメンバーとなるため明示的に修飾子をつけることはできない。
・列挙型では「private」なコンストラクタのみが許容され、それ以外だとコンパイルエラーとなる(暗黙的(明示しても可))。

■enumクラス(列挙型)の基本的なメソッド

・列挙定数名を文字列として取得
①name() ・・・ finalされているためオーバーライド不可
②toString() ・・・ オーバーライド可能(カスタム可)

・文字列から列挙型定数を取得
①valueOf(//ここにString型で指定)

2章

■ジェネリクスの注意点

・匿名クラスの実装時にジェネリクスを使用する場合はインスタンス生成のコードにおける型引数は常に省略してはならない。

インスタンス生成時における型引数の省略
Foo<String> foo = new Foo<String>();
// ↓ 省略可能
Foo<String> foo = new Foo<>();
ジェネリクスを用いた匿名クラスの実装
//型引数は省略できない
Foo<String> foo = new Foo<Strig>() { //匿名クラスによる実装 };

・ジェネリック・クラス実装時のコード記述ルール

以下に示すコード記述は不可能
※クラス宣言時の共通
class Test<T>{// ここに記述できないコードを以下に列挙}

static修飾子付きの型変数
static T type; //コンパイルエラー
型変数によるインスタンス生成
T obj = new T(); //コンパイルエラー
型変数を要素に指定する配列の生成
T[] array = new T[5]; //コンパイルエラー
instatnceOf演算子による型の判定
//引数に指定するのはOK
void doIt(T t){
    if(t instanceOf T) { //コンパイルエラー
        /* some code here */
    }
}
型変数に対する「.class」の参照
void doIt(){
    Class<T> klass = T.class;
}

■Arraysクラスの注意点

・メソッド

asList()・・・配列または数字の列挙からコレクションList型のオブジェクトを生成。
asList()メソッドの引数に渡された配列から生成されるListオブジェクトの要素は元の配列オブジェクトの要素を参照しているため、いずれかのオブジェクトに加えた変更はもう片方のオブジェクトにも反映される。
※但し、asListメソッドより生成されたListオブジェクトは要素の追加(add())や削除(remove())はサポートしていないため例外UnsupportedOperationExcepitonがスローされる。要素の置換(set())のみ対応している。

オブジェクトに独立性をもたせる(要素の参照を共有させたくない)場合には、ArrayListやLinkedListのコンストラクタに指定する。


ArrayList<?> list = new ArrayList<>(Arrays.asList(array));
LinkedList<?> list = new LinkedList<>(Arrays.asList(array));

■Deque(ArrayDeque)について

ArrayDequeの特徴

・FIFOデータ構造ではLinkedListクラスよりも高速
・FILOデータ構造ではjava.util.Stackよりも高速
・null要素は許容しない
・スレッド・セーフでない(Stackクラスはマルチスレッドのアプリケーションに使える。)

■TreeSetに格納するオブジェクトの注意点

TreeSetでは内部で要素を並べ替えるために、要素をComparable型にCast処理をおこなっている。そのため、TreeSetに格納される要素がComparable型ではない(Comparableをimplementsしていない)場合にはキャストが失敗し、ClassCastExceptionが発生する。
※コンパイルエラーではない。

3章

4章

■Streamの終端操作の注意点

・終端操作は同一ストリームに対して二回以上呼び出すことはできない。呼び出した場合、例外「IllegalStateException」がスローされる。

■MapインターフェースのforEachメソッド

仕様
・IterableインターフェースのforEachメソッドはConsumerを引数に受け取る。
・CollectionインターフェースはIterableインターフェースを継承している。
・MapインターフェースはCollectionインターフェースを継承していない。
・Mapインターフェースは独自でdefaultメソッドとしてforEachメソッドを定義している。
・MapインターフェースのforEachメソッドはBiConsumerを引数に受け取る。

結論
MapインターフェースのforEachメソッドの引数の条件からMapのサブタイプでforEachを利用するときは引数をふたつ受け取る実装を適用させる必要がある。

Map#forEach
//ラムダ式で実装する場合
Map<Integer, String> map = new TreeMap<>(){{put(1, "A"); put(2, "B");}}
map.forEach((k, v) -> System.out.println(k + " = " + v));

■テキストファイルの文字列をStreamオブジェクトとして扱うには

・java.io.BufferedReader#lines()
・java.nio.file.Files#lines(Path path):static
※BufferdReaderのlinesは引数を受け取らず、FilesのlinesはPathオブジェクトを引数に受け取る。

BufferedReader#lines
try(BufferedReader br = new BufferdReader(new FileReader("xxx.txt"))){
    Stream<String> line =  br.lines();
    line.forEach(System.out::println);
}catch(IOException e){
    e.printStackTrace();
}
Files#lines
Path path = Paths.get("xxx.txt");
Steram<String> line = Files.lines(path);
line.forEach(System.out::println);

■StreamのallMatch,anyMatch,noneMatch

・それぞれのメソッドは&&や||のように短絡評価されるため注意

■Mapインターフェースのmergeメソッド

【メソッド定義】
default V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)

【説明】
・基本的には第二引数(V value)に指定された値を使用し指定されたキーに設定する。
・キーが存在し且つ値も設定されている場合は、BiFunctionオブジェクトを用いて指定されたキーの値と指定された第二引数の値をBiFunctionオブジェクトの実装に則った返り値を戻す。
・キーが存在しないか、値がnullの場合には第三引数のBiFunctionは使用されない。

■reduce/collect メソッド

リダクションとは
データの集合を1つに要約すること

リダクションの実現
reduceメソッド

可変リダクション操作
何らかの可変コンテナに要素を収集する操作のこと
※可変コンテナ?
要素を格納できるだけでなく格納した要素を変更できるオブジェクトのこと。
主にListやMapなどのCollectionオブジェクト、StringBuilderがそれにあたる。

可変リダクション操作の実現
collectメソッド

5章

■try-with-resources

処理順序

try文の実行➡︎close文の実行➡︎catch文の実行

AutoCloseableを実装しなかった時

例外処理ではなく、コンパイルエラーが発生する。

■日時を表現するクラスが実装しているインターフェース

・TemporalAccessor

・Temporalインターフェースのスーパーインターフェース
・読み取り専用のメソッドが定義されている

・Temporal

・TemporalAccessorのサブインターフェース
・読み取りおよび書き込み用のメソッドが宣言されている。

■日時を表すクラスのfromメソッド

・staticなfromメソッドはTemporalAccessorオブジェクトを受け取る
・日付オブジェクト(LoclaDate)や時間オブジェクト(LocalTime)から日時オブジェクト(LocalDateTime)は生成できず生成を試みると例外「DateTimeException」が発生する。(データが足りないオブジェクトを生成することはできない)
・逆にLocalDateTimeオブジェクトからLocalDate、LocalTimeのオブジェクトは生成可能だが日付情報や日時情報が失われる。
・また、OffsetDateTimeやZonedDateTimeオブジェクトからLoclaDateTimeオブジェクトは生成できるが、時差情報・タイムゾーンの情報が失われる。

■日付や時間の単位を表すインターフェースとそれを実装した列挙型

・日付・時間の単位を表すインターフェース

java.time.temporal.TemporalUnit

・インターフェースを実装した列挙型

java.time.temporal.ChronoUnit

ChronoUnitの主な列挙定数
列挙定数 説明
DAYS 1日の概念を表す単位
HOURS 1時間の概念を表す単位
MINUTES 1分の概念を表す単位
MONTHS 1ヵ月の概念を表す単位
SECONDS 1秒の概念を表す単位
WEEKS 1週間の概念を表す単位
YEARS 1年の概念を表す単位
ChronoUnitの列挙定数を引数にとる主なLocalDateTimeのメソッド
メソッド 説明
LocalDateTime minus(long amountToSubtract, TemporalUnit unit) 指定された時間量を減算した、この日付・時間のコピーを返す
LoclaDateTime plus(long amountToAdd, TemporalUnit unit) 指定された時間量を加算した、この日付・時間のコピーを返す
long until(Temporal endExclusive, TemporalUnit unit) もう一方の日付・時間までの時間量を指定された単位で返す

■TemporalUnitインターフェイスで定義されたメソッドはChronoUnit列挙型も用いて呼び出す

列挙定数で指定した概念の単位を基に以下のメソッドが呼び出せる
●ChronoUuit.DAYS.
・指定された概念単位で日時を足す
addTo(基になる日時, 追加するlong値)
・指定された概念単位で日数間の時間量を計算する
between(start日数, end日数)

0
0
0

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
0
0