Java

Javaにおける文字列と数値と変数とオブジェクトのまとめ

More than 3 years have passed since last update.

パーフェクトJavaを読んだ(第2章 ~ 第3章)ので、

その簡単なまとめを載せる。

(ちなみに全ての内容を記載しているわけではありません)


第2章 文字と文字列


  • Javaの文字列はイミュータブルなオブジェクト

  • 文字列を変更する際は新しくオブジェクトを生成している。

  • Javaの文字列は配列のように見えない工夫が施されていて、ひとつのオブジェクトとして扱う。

  • Stringオブジェクトは読み込み専用なので、文字操作の度にインスタンスを作成して、無駄が生じる。


StringBuilder


  • オブジェクトの破壊的なメソッドはメソッドの定義だけでは判別がつかないので、イミュータブルなStringメソッドからコピーした方が安全である。(生成のコストはかかる)

  • Stringオブジェクトのように文字列が変更不能であるような性質のオブジェクトを不変オブジェクトという。不変オブジェクトは予期しづらい非効率なコードになる可能性がある。


    • 文字結合を +演算子 で行う場合




文字比較


  • Stringオブジェクトの文字列比較には == を使用するのはNG


    • == はオブジェクトの参照先が等しいか(同一性)を判別するので、値が等しいか(同値性)は判別しない。

    • 同値性を判別するには、equalsメソッドを使用する。



  • 文字リテラルを == で比較する際、文字列リテラルから暗黙に生まれるStringオブジェクトは、文字列の内容が一致している場合は同一のStringオブジェクトであるので、trueになる。文字結合後の内容が一致している場合も、同一のStringオブジェクトになるので、trueになる。


    • しかし、これはたまたまtrueになるとかんがえるべきで、通常はequalsを使用する。



  • 文字列リテラルとStringオブジェクトの文字比較


    • "012".equals(str)にすると安全。(str.equals("012")はstrがnullの場合、エラーになるため)



  • StringBuilderの同値比較


    • StringオブジェクトとStringBuilderオブジェクトの比較は"012".contentEquals(new StringBuilder("012"))を使用する。

    • StringBuilder同士の比較はtoStringを使う。



  • ObjectクラスにtoStringメソッドが定義されている


    • toStringメソッドは継承先のオーバーライドを前提にしている。

    • 独自クラスにtoStringはデフォルトでは「クラス名+内部ID(HashCode)」が出力される。

    • toStringにフィールド値等を出力させる実装を独自にオーバーライドしてやると、デバックで役立つ。




文字


  • 文字列リテラルはダブルクォートで囲む。

  • 文字リテラルはシングルクォートで囲む。


第3章 数値


整数型をどのように使い分けるべきか。


  • byte型, char型はバイト及び文字として限定して使う。

  • short型, int型, long型


    • 基本的にはint型を使えば良い。

    • どうしても、int型でまかないきれない範囲を扱う場合のみlong型を使用する。

    • short型は正直、使わなくても良い。(ハードウェアリソースの節約で使いたがるかもしれないが、不具合を起こす可能性のほうが高いので止めるべき)




型変換


  • 整数型の変換は拡大変換のみ可能(short → int, int → long)


  • 縮小変換はコンパイルエラーになるが、キャストによる変換が可能


    • int → shortへの変換はビットがあふれる可能性があるために注意する。
      java
      int i = 32768;
      short s = (short) i; // -32768


    • キャストはバグを生む原因になりやすいので、なるべく使用を避ける。
      キャストを使うケースが多い場合は、型定義を間違えている可能性を疑う。



  • char と byte と shortでの変換は必ずキャストが必要。


  • int型のリテラルで定義した整数が代入先の型の範囲に収まっていれば、キャストなしで代入可能。(longは代入不可能)


  • メソッドに引数にリテラル値を渡すときは代入先の型の範囲に収まっていても、キャストが必ず必要になる。



第4章 変数とオブジェクト


参照型変数とは


  • 参照型変数のまとめ


    • 「参照」とはオブジェクトの位置情報を示す何かである。

    • 参照型変数は値として、「参照」を持つ

    • 「参照」は、その直接の値を意識することはない。

    • 結果として、参照型変数には「オブジェクトを指し示す役割」だけが残る。



  • 参照型変数の型(暫定的な理解)


    • 参照型変数自体にも型が存在する。オブジェクト自身の型とは別に存在する。

    • 変数の型とは参照できるオブジェクトの種類を限定するもの




オブジェクト生成と代入


  • 参照型変数を他の変数に代入すると、代入元と代入先の変数は同じオブジェクトへの参照を持つ。

  • nullは「何も参照していない」という状態を作る。


    • 未初期化状態

    • オブジェクトが存在しないことを明示

    • オブジェクトの参照を明示的になくす



  • nullに対してのメソッドやフィールド呼び出しは、NullPointerExceptionを引き起こす。


変数の種類


  • シャドーイング


    • 宣言した変数はその後でのブロック内にも有効になる。ブロック内に同名変数を定義すると、スコープが重なってしまう。(これをシャドーイングという)

    • Javaではこういったシャドーイングはコンパイルエラーになる。



  • final変数


    • 普通は定数定義として使う。

    • final変数が参照型変数の場合は、final修飾子は変数自体の値の変更(参照先の変更)を禁止させるが、参照先のオブジェクト自体の変更は可能である。



  • 堅牢なプログラミングのための工夫


    • 変数は宣言と同時に初期化する(無理の無い範囲で)

    • 変数を使いまわさない(再代入は避ける)

    • 変数のスコープは小さくする

    • オブジェクトの寿命を意識する

    • 不変オブジェクトを活用する