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がついたメソッドはオーバーライドできない。
public class Parent {
String name = "Zenn";
public viud hello() {
System.out.println(this.name + "さん、おはようございます";
}
}
public class Child extend Parent {
public viud hello() {
System.out.println(this.name + "さん、こんにちは";
}
}
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する複数の子クラスに、共通のメソッド群を実装するように強制できる
- あるクラスがインタフェースを実装していれば、少なくともそのインタフェースが定めたメソッドは持っていることが保証される
多様性 = ポリモーフィズム
カプセル化
フィールドへの読み書きやメソッドの呼び出しを制限する機能
- private
自分自身のクラスのみアクセス可 - pakcage private(何も書かない)
自分と同じパッケージに属するクラス - protected
自分と同じパッケージに属するか、自分を継承した子クラス - public
すべてのクラス
アクセス修飾の定石
- フィールドはすべてprivate
- メソッドはすべてpublic
クラスに対するアクセス制限
- package private(何も書かない)
自分と同じパッケージに属するクラス - public
すべてのクラス
非publicクラスの特徴
- クラスの名前はソースファイル名と異なっても良い
- 1つのソースファイルにクラスを複数宣言しても良い
等値と等価
- 等値
同一の存在であること - 等価
同じ内容であること
static
同じクラスから生成されたインスタンスでフィールドを共有したい場合に使用する
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 |
---|---|---|
配列(隙間なく並んでいる) | 内部構造 | 連結リスト(数珠つなぎ |
遅い | 要素の挿入・削除 | 速い |
速い | 指定位置の要素の取得 | 遅い |
jarファイル
META-INF ディレクトリ
META-INFディレクトリ内の次のファイル/ディレクトリは、Java 2プラットフォームによって認識および解釈され、アプリケーション、拡張機能、クラスローダー、およびサービスを構成します。
ふむ?つまりどういうことだってばよ。
管理情報を格納するディレクトリです。jarコマンドによって自動的に作成されます。
管理情報とは。。。
エンタープライズアプリケーションデプロイメントディスクリプタである application.xml は、<JRun のルートディレクトリ>/servers/<JRun サーバ>/<Web アプリケーション>/META-INF ディレクトリに置かれます。
あ、なるほど設定ファイルのことかな。application.xml
やpomファイルが入ると。
WEB-INF
ではこっちは?
JSP、HTML ページ、カスケーディングスタイルシート、イメージ、Javascript ファイルなど、クライアントのリクエストからすべてのファイルおよび WEB-INF ディレクトリを格納します。これらのファイルは、Web アプリケーションのルートディレクトリ、または予約名 WEB-INF を使用しないサブディレクトリに直接置くことができます。(省略)このディレクトリ、またはそのサブディレクトリに含まれたファイルはクライアントに直接参照させることはできません。
なるほど。
デプロイメントディスクリプタ (web.xml)
Web アプリケーションは、WEB-INF/web.xml ファイルのコンテンツによって定義されます。
デプロイメントディスクリプタは、アプリケーションサーバ上で実行するためにアプリケーションが使用する設定情報が格納された XML ファイルです。
あれ、META-INFに入ってるのもXMLファイルでなかったっけ。
web.xml ファイルを使用して、Web アプリケーションの次のような設定情報とデプロイ情報を定義します。
サーブレット初期化パラメータ
セッション設定
サーブレットと JSP の定義
サーブレットと JSP URL のマッピング
MIME タイプのマッピング
welcome-file-list
エラーページ
フィルタ
イベントハンドラ
タグライブラリ
セキュリティ情報
データソースや JMS 接続ファクトリなどのリソース
うげ。META-INFとの違いがますますわからん。
ちゃんとMETA-INFについて読もう。
Java 2プラットフォームでは、アプリケーション、拡張機能、クラス・ローダー、およびサービスが構成されるときに、META-INFディレクトリから次のファイルとディレクトリの認識および解釈が行われます。
「アプリケーション、拡張機能、クラス・ローダー、およびサービス」これはWEB-INFの中身の話をしてそう。つまりWEB-INFに入っているサービス情報が構成されるときに、読まれるファイル群ってことかな。
拡張機能やパッケージ関係のデータ定義ファイル、パッケージの位置情報ファイル、署名ファイル、署名ファイルに関連付けられた署名ブロック・ファイル、サービスプロバイダ構成ファイルが入っている。
うん、なるほどなるほど。よく読んでなかった。
【参考】