オブジェクト・インスタンス・クラスとは?
オブジェクト(インスタンス)とは?
複数の変数・メソッド(後述)を一つのまとまりとして扱うことができるようにまとめたもの。
これの中にある変数のことをメンバ変数と呼び、中にあるメソッドをメンバメソッドと呼ぶ。
クラスとは?
オブジェクト(インスタンス)の設計図。
あらかじめ宣言しておき(設計図を作っておくような感覚)、使用する場面で設計図をもとに実際に使うことができるもの(オブジェクト・インスタンス)を作る(インスタンス化)
クラスの宣言の仕方
class TestClass {
int data1;
int data2;
}
- class [クラス名] { //クラスに含むメンバ すべて }
宣言したクラスを使うには?(クラスのインスタンス化)
例)main (String args[]) { // のなかで
TestClass t = new TestClass();
- [クラス名(型宣言)] [オブジェクト名(代入したいオブジェクトの名前)] = new [クラス名]();
※最後のクラス名の後の"()"の中に変数や初期値を与えることもでき、これを使うことでオブジェクトごとに別の初期値を与えることもできる。(後述)
インスタンス化したオブジェクトのメンバ変数を使うには?
t.data1 = 100;
//TestClassをインスタンス化した,tの中のdata1を呼び出している
System.out.println(t.data1); // =>100
クラスの継承とは?
すでに作成されたクラスをもとに、拡張版(変数の追加や変数の上書きを行われたもの)のクラスを作るための機能のこと。
どうやって継承するの?
class TestClassPlus extends TestClass {
double data3; //メンバ変数の追加
long data4;
data1 = 2; //値の上書き
}
- class [継承先のクラス名] extends [継承元のクラス名] { //継承後クラスに 追加したいもの・上書きしたいもの }
※extendsの意味…延長する。→クラスに必要なメモリ容量の付け足しと思えば理解しやすい。
親クラスのオブジェクトと子クラスのオブジェクトの関係性
(あまり使うことはないが、)子クラスのオブジェクトを親クラスのオブジェクトに代入した場合の挙動は、親クラスに存在するメンバなら呼び出すことはできるが、継承時に追加・変更されたオブジェクトは参照・使用することはできない。
→親クラスで確保されたサイズのメモリしか保有しないため。
例)上記のTestClassとTestClassPlusを使用する
TestClass t;
TestClassPlus tp = new TestClassPlus();
tp.data1 = 123;
tp.data2 = 456;
tp.data3 = 789.0;
t = tp;
System.out.println(t.data1); //=>123
System.out.println(t.data2); //=>456
System.out.println(t.data3); //=>コンパイルエラーになる(実行不可)
メソッド・コンストラクタとは?
メソッドとは?
クラスの中に定義する関数のこと。クラス内で定義されている変数に対する処理や、そのクラスに関する処理をまとめて記述する。一度作ってしまえば、面倒な処理を肩代わりしてくれるものである。
例)宣言の仕方(TestClass内で)
int data1 = 0;
int data2 = 1;
void show(){
System.out.println(data1);
System.out.println(data2);
}
例)呼び出し方
t1.show(); //o(改行)1
コンストラクタとは?
メソッドのうち、クラスがインスタンス化されたときに必ず実行されるメソッド。多くの場合ここでメンバ変数の初期化を行う。
また、インスタンス化の際に使う、new [クラス名]();
の括弧内に引数を与えると、コンストラクタ内で使うことができる。
メソッドの定義とコンストラクタの定義の例
例)上記のTestClassにメソッドとコンストラクタを追加する
class TestClass {
int data1 = 0;
int data2 = 1;
//コンストラクタ
TestClass(int input1, int input2){
data1 = input1; //=>引数input1に指定された値をdata1に代入している
data2 = input2; // →インスタンス化の時に引数で初期値を指定すればそのたびに自動で代入してくれる
}
//メンバ変数を表示するメソッド
void printData() {
System.out.println(data1); //=>同じクラスの中なので、"t.data1"のようなオブジェクト内の変数を指定する
System.out.println(data2); // 形ではなく、単純に"data1"のようにメンバ変数名だけでよい。
}
※コンストラクタはクラス名と同じ名前のメソッドを定義する。
定義されたクラスを使うには
例)上記のメソッドとコンストラクタが追加されたTestClassを使用する
TestClass t = new TestClass(100, 200); //コンストラクタを使った初期化が起きている
t.printData(); //=>100(改行)200
//↑ではSystem.out.println(data1)とSystem.out.println(data2)が実行されている
オーバーライドって?
親クラスを子クラスに継承する際に親クラスのメンバメソッドを上書きすること。
パッケージとは?
複数のクラスをまとめることで、関連するクラスを分類しやすくする考え方。
名前空間にもなり、別のパッケージであれば、同じクラス名をつけても衝突が起きない。
また、別ファイルから読み込む際も、パッケージ単位でまとめて読み込むことができ、便利である。
例)TestClassとTestClassPlusを一つのtestパッケージにまとめる
package test.testClass;
//testClassの定義
package test.TestClassPlus;
//TestClassPlusの定義
例)二つを別のファイルにまとめて読み込む時
import test.*; //testパッケージ以下にあるすべてのクラスを読み込む
アクセス制御(private・public・protected・指定なし)
メソッド・変数にアクセス(読み書き)できる対象を制限すること。
なぜ制限する必要があるのか?
誰でもどこからでも変数・メソッドにアクセスが可能であると、変数の中身を意図せず書き換えたり、予期しないタイミングでメソッドを実行させることができたりしてしまい、思わぬ挙動が現れる可能性を高めてしまう。
→これを防ぐために、アクセスの制限をかけて想定通りの挙動になるように管理する必要がある。
publicとは?
どこから・誰でもアクセスできるメンバ。これはどのクラスでも、どのパッケージからでもアクセスできる状態である。
多くの場合、メソッドをpublic指定してメソッド内で引数などを検査してからprivate要素にアクセスさせる、門番のような役割に使われる。
protectedとは?
同じパッケージ・子クラスからのみアクセスできるメンバ。継承されるクラスで指定される。
指定なしのアクセス権限とは?
同じパッケージからのみアクセスできるメンバ。publicにはならないので注意。
privateとは?
同じクラス・同じクラスから作られたオブジェクトからのみアクセスできるメンバ。もっとも強いアクセス制限で、アクセス権限がないものがアクセスしようとすると、コンパイル時にエラーを出力する。
多くの場合、メンバ変数は簡単に変更されてはならないので、private指定されている。
private指定された変数にアクセスするメソッド(Getter・Setter)
private指定された変数にアクセスする門番のようなメソッドは特にGetter・Setterと呼ばれる。
多くのJavaライブラリではこれを自動生成する機能もついている。
Getter
変数を表示する・他のメソッド内で使用する場合に読みだすために使われるメソッド。
Setter
変数の内容を変更する・他のメソッドの結果を代入する場合に書き込むために使われるメソッド。基本的にここに代入値の検査(バリデーションをかける)を記述する。
Javaの中の変数の型
プリミティブ型(基本データ型)
メモリの中に書き込まれた情報のことを指す。数値を扱うデータ型では基本的にこれを使用する。これの初期化されていない値は基本的に0であって、NULL判定・代入はできない。
型名 | 初期値 | 種別 |
---|---|---|
byte | 0 | 1バイト整数型 |
short | 0 | 2バイト整数型 |
int | 0 | 4バイト整数型 |
long | 0 | 8バイト整数型 |
float | 0.0 | 4バイト実数型 |
double | 0.0 | 8バイト実数型 |
boolean | false | 真偽型 |
char | 文字コードの"¥u0000" | 2バイト文字型 |
参照型
メモリのアドレス情報のことを指す。クラス・文字列を扱うデータ型ではこれを使用する
参照型の代入
同じクラスからインスタンス化された複数のオブジェクトを使って、代入を行うとどのような挙動をするか
例)上記のTestClass が宣言されている。
TestClass t1 = new TestClass();
TestClass t2 = new TestClass();
t1.data1 = 123;
t2.data1 = 456;
t2 = t1;
System.out.println(t2.data1); // =>123
System.out.println(t2.data2); // =>456
これは、Javaのクラスが参照型であり、メモリのアドレスを保持しているため、代入を行うことでアドレスが上書きされる。
アドレスが上書きされることによって、オブジェクト内すべてのデータが書き換えられたように見える。
Javaにおける配列とオブジェクト
Javaの配列の宣言は二通り存在する。
//Java正式な宣言
int[] array;
//C/C++風の宣言
int array[];
空配列の宣言にはnew演算子を使用する
int[] array = new int[5];
[型名] [ ] [配列名] = new [型名][要素数]
初期値が決まっている場合はC言語の配列宣言のように初期化を同時に行うことができる
int[] array = {1, 2, 3, 4, 5}; //=>5つの要素が宣言される
[型名][ ] [配列名] = {初期値}
オブジェクトの配列
インスタンス化されたオブジェクトを配列の中に代入することも可能である。
例)「メソッドの定義とコンストラクタの定義の例」のTestClass を使用する
TestClass[] TestClassArr = new TestClass[3]; //TestClassの配列の宣言
TestClassArr[0] = new TestClass(100, 200); //TestClass一つ一つのインスタンス化
TestClassArr[1] = new TestClass(300, 400);
TestClassArr[2] = new TestClass(500, 600);
System.out.println(TestClassArr[0].data1); //=>100
System.out.println(TestClassArr[1].data2); //=>400
オブジェクトを代入する配列の宣言→配列一つ一つにオブジェクトを作成していく
※配列内へのインスタンス化を繰り返し文でおこなうことが多い
Java内のString型の実装
Javaでも文字列をchar型の配列として保持し、そこに様々なメソッドを追加しているので下記のような記述も可能である。
System.out.println("TESTMOJI".length); //=>8
thisとsuper
thisとは?
クラス内でそのクラスのオブジェクトを使う場合に使用する特別な変数。
例)TestClass内で別のメソッドからprintDataメソッドを呼び出す場合
this.printData();
※Javaではthisの指定をしない場合、暗黙でthis指定(インスタンスのメンバ指定)となる
superとは?
継承したクラスの親クラスのメンバを指定するときに使える。子クラスでオーバーライドしたメソッドの元のメソッドを呼び出すときなどに使うことができる。
System.out.println(super.data1); //=>オーバーライドする前の"0"が表示される
finalとstatic
finalとは?
クラスにつけた場合、継承できなくなる修飾子。
変数につけた場合、変更できなくなる(定数にする)修飾子。
final data5 = 100;
staticとは?
メソッドにつけた場合、インスタンス化なしで使うことができるようにする修飾子。
変数につけた場合、クラス(クラスオブジェクト)に変数を持たせることができる(インスタンス共通の変数を作ることができる)修飾子
class TestClass{
static data1 = 0;
}
System.out.println(TestClass.data1); //TestClassの中に存在するdata1変数
static指定することで、すべてのインスタンスで共有するメンバを一箇所に定義することができる。
→メモリ領域を削減することができる
※インスタンス内からstaticメソッドを変更することができるため、注意が必要である。
例外処理とは?
コンパイル時に発見できる文法エラー以外の実行中のエラー(例外)を検知し、対処するための処理。try句とcatch句を使う
tryとは?
try句の中に処理を記述することで、実行中のエラーを例外として検知することができる。
BufferedReader br = new BufferdReader(InputStreamReader(System.in));
try{
int inputAns = Integer.parseInt(br.readLine()); //キーボードからの数値の読み込み
int ans = 10 / inputAns; //これでは、10÷0というプログラミングの禁忌(結果が無限大になってしまうため)が起きる可能性がある。
}
//以降のcatch文などは次項から解説するので省略。(catch・finalyがない場合はSyntaxエラーとなるので注意)
※これで実行時のエラーを取得までは可能である。
しかし、エラーの種類ごとに対処(例外処理)をすることができない。
catchとは?
tryで取得したエラーの種類をもとに、対処(例外処理)を記述するための文。
try{
//(上記の)通常処理文
}catch (ArithmeticException e){ //ArithmeticExceptionはゼロが入力された時に起きるエラー。
System.out.println("0が入力されました。処理を中断します。");
}catch (IOException e){ //文字列が入力できなかった時に起きるエラー
System.out.println("入力が読み込めませんでした。処理を中断します。");
}
※このように、一つ一つのエラーの種類ごとに例外処理を書くことができる。
すべての例外処理をまとめて処理したい場合
try{
//通常処理文
}catch (Exception e){ //Exception とは 例外という意味
//例外処理分
}
finallyとは?
通常処理終了後も例外処理終了後もどちらの処理の後でも実行しなければならない処理を記述する部分
try {
//通常処理
}catch (Exception e){
//例外処理
}finally {
//最終処理
}
※try・catch文の最後に書く必要がある。
throw・throwsとは?
throwとは?
tryの中で宣言することで例外処理に処理を移すことができる。
throw new testException();
throwsとは?
メソッドの中で例外処理が起きる可能性を示しておくためにメソッド宣言時に記述する語句。
void show() throws testException{
// 例外の可能性がある処理
if (data1 < 0 || data2 > 10000){
throw new testException();
}
}
抽象クラスとインターフェイス
抽象クラスとは?
クラス宣言時にabstractを指定することで作成される、そのままインスタンス化できないクラス。継承するために定義する。
複数のクラスで共通する部分をここで定義する。
class abstract TestClass {
//クラスの宣言
}
インターフェイスとは?
abstractでの宣言と同様に、抽象クラスの宣言を行うための語句。
interface TestClass {
//抽象化するクラスの宣言
}
インターフェイスを使う意味
これを使うことで、インターフェイスの継承ができる。