Closed20

Java基礎(気になったところだけ)

クラスとオブジェクトが別な理由

オブジェクトを直接定義できた方がシンプルに見えるが、作成するオブジェクトが多いほど一つずつ作成するのは大変になる。
クラスを定義しておけば、値を変えるだけでオブジェクトを生み出すことができる。
よってクラスを定義することによって、オブジェクトを作成することにもメリットはある。

クラスとオブジェクトは別物であり、プログラムの動作時に仮想世界の中で活躍するのはオブジェクトだけである。クラスが仮想世界で活動することは基本的にはない。

※オブジェクト ≒ インスタンス

thisの省略

同じクラス内のフィールドにアクセスするときは、thisを省略することが可能。
しかし、ローカル変数や引数にも同じ名前があると、そちらが優先されてしまうなどのバグの原因になりかねない。よってフィールドを用いるときはthisを明示的につけよう。

同一インスタンスを指す変数

以下のコードは「200」が出力される。

public class Main {
 public static void main(String[] args) {
  Hero h1;
  h1 = new Hero();
  h1.hp = 100;
  Hero h2;
  h2 = h1;
  h2.hp = 200;
  System.out.println(h1.hp);
 }
}

これは値参照ではなく参照渡しをしているためである。
具体的にはインスタンスをコピーし、コピー1・コピー2を作成しているのではなく、
h1の場所を示す番地をh2にコピーしている。よってh1, h2どちらもh1を示している。
✨ newが一つしかないのがポイント

コンストラクタ

コンストラクタは開発者が直接呼び出すものではない。(=直接呼び出すことはできない)
インスタンス生成後に、JVMが実行する。

多重継承

Javaは許可していないため、使用不可。

オーバーロードとオーバーライド

二つは似て非なるもの。

  • オーバーロード(多重定義)
    通常は同じメソッド名が複数あるとJVMはメソッドを特定できないが、仮引数が異なれば複数定義することが許されている。
public static int add(int x, int y) {
 return x + y;
}

public static int add(int x, int y, int z) {
 return x + y + z;
}

public static void main(String[] args) {
 System.out.println("10+20=" + add(10, 20));  // 1つ目のメソッドが呼び出される
}
  • オーバーライド
    親クラスを継承して子クラスを宣言する際に、親クラスのメンバを子クラス側で上書きすること。
    尚、finalがついたメソッドはオーバーライドできない。
Parent
public class Parent {
 String name = "Zenn";

 public viud hello() {
  System.out.println(this.name + "さん、おはようございます";
 }
}
Child
public class Child extend Parent {
 public viud hello() {
  System.out.println(this.name + "さん、こんにちは";
 }
}
GrandChild
public class GrandChild {
 public static void main(String[] args) {
  Parent p = new Parent();
  p.hello();   // Zennさん、おはようございます
  Child c = new Child();
  c.hello();   // Zennさん、こんにちは
 }
}

super()とsuper.メンバ変数

  • super()
    親クラスのコンストラクタの呼び出し。
  • super.メンバ変数
    親インスタンス部分のメンバ変数を利用する。

抽象クラスにするのはどんなクラス?

  • 詳細未定のフィールドやメソッドが存在する
    例) 中身が空のattackメソッド
  • オーバーライドでなんとかしたいけど、バグの原因になる→ 抽象メソッドはオーバーライドを強制できる
  • インスタンス化してはだめ→抽象クラスはnewによるインスタンス化が禁止される
public abstract class Character {
    String name;
    int hp;

    public void run() {
        System.out.println(this.name);
    }

    public abstract void attack(Enemy e);
}

インタフェースはつまりどういう時に使うのか

上のようなCharacterクラスは実装が進むにつれ、どんどん抽象化が進んでいく。。。
このような抽象クラスの抽象クラスを特別扱いするのが、インタフェース。

特徴

  • 全てのメソッドは抽象クラス
  • 基本的にフィールドを1つも持たない
    例外) static finalがついたフィールド(尚、public static finalは省略可。自動的にそうなるため)
  • 多重継承可能
public interface Character {
    public abstract void run();
}

or

public interface Character {
     void run();  // public abstractは省略可能
}

効果

  • 同じインタフェースをimplementsする複数の子クラスに、共通のメソッド群を実装するように強制できる
  • あるクラスがインタフェースを実装していれば、少なくともそのインタフェースが定めたメソッドは持っていることが保証される

多様性 = ポリモーフィズム

カプセル化

フィールドへの読み書きやメソッドの呼び出しを制限する機能

  1. private
    自分自身のクラスのみアクセス可
  2. pakcage private(何も書かない)
    自分と同じパッケージに属するクラス
  3. protected
    自分と同じパッケージに属するか、自分を継承した子クラス
  4. public
    すべてのクラス

アクセス修飾の定石

  • フィールドはすべてprivate
  • メソッドはすべてpublic

クラスに対するアクセス制限

  1. package private(何も書かない)
    自分と同じパッケージに属するクラス
  2. public
    すべてのクラス

非publicクラスの特徴

  • クラスの名前はソースファイル名と異なっても良い
  • 1つのソースファイルにクラスを複数宣言しても良い

等値と等価

  • 等値
    同一の存在であること
  • 等価
    同じ内容であること

static

同じクラスから生成されたインスタンスでフィールドを共有したい場合に使用する

3つの特殊な効果

  1. フィールド変数の実態がクラスに準備される
  2. 全インスタンスに、箱の分身が準備される
  3. インスタンスを1つも生み出さなくても共有の箱が利用可能になる

public static final

多くの場合、staticはfinalやpublicと一緒に指定され、変化しない変数を各インスタンスで共有するために利用される。

StringBuilder > +演算子

多くの文字列を連結する場合、StringBuilderを使うと+演算子よりもずっと早く処理することができる。
これはStringインスタンスの不変性が関係している。

インスタンスの不変性

+演算子のイメージは、あるフィールドに何かの文字を加えるようなものだが、
実際は元々のフィールドは破棄され、新しく連結した文字列のフィールドが生成・格納されている。(newされている)
一方StringBuilderは可変であるため、高速に処理できる。

配列のように順序をつけて並べて格納するデータ構造を特に、リストと呼ばれる

コレクションクラス

どんな方のインスタンスでも格納できるように作られている。
しかしインスタンスでないもの(データ型)は格納できない。

ラッパークラス

基本データ型の情報を中身に保持することを責務とする8つのクラスの総称

  • java.lang.Byte
  • java.lang.Short
  • java.lang.Integer
  • java.lang.Long
  • java.lang.Float
  • java.lang.Double
  • java.lang.Character
  • java.lang.Boolean

いちいちこれに変換してからListに格納するのが面倒なときは、オートボクシングオートアンボクシングを使用できる。
しかし、内部で保持できるのはあくまでラッパークラスであるため、コレクションクラスを型に指定することはできない。

イテレーター

リストの中身を1つずつ取り出す方法の1つ。コレクションクラスの中身を順に取り出すためのもの。
リストに含まれる1つの箱をココ!と指している矢印のようなもののイメージ。

イテレータの取得

Iterator<リスト要素の型> it = リスト変数.iterator();

Iterator<hoge>が使えるメソッドは2つだめ

戻り値 メソッド 機能
boolean hasNext() 次の要素を指せるかを判定
- next() 次の要素を指し、その内容(〜型)を返す


イテレータを用いたリスト要素の取り出し

Iterator<リスト要素の型> it = リスト変数.iterator();
while (it.hasNext()) {
    リスト要素の型 e = it.next();
    /* 要素eを用いた処理 */
}

ArrayList vs LinkedList

ArrayList 比較項目 LinkedList
配列(隙間なく並んでいる) 内部構造 連結リスト(数珠つなぎ
遅い 要素の挿入・削除 速い
速い 指定位置の要素の取得 遅い
このスクラップは1ヶ月前にクローズされました
ログインするとコメントできます