この記事の目的
Javaを業務で使い始めた駆け出しエンジニアが、学習のアウトプットのために書きました。
勉強している際に、何かを調べても、その調べた際に出てくる用語がわからず、さらに調べていくと結局何を目的としていたのか忘れてしまうということが頻発したり、結局調べてもよくわからないという状況が続いたので、用語集があれば良いなと思い、書きました。
結構間違っている認識もあるかとは思うので、まさかりバンバン募集しているので、コメントで訂正や修正お待ちしております。
私の勉強にもなるので、ためになります。
どんな人が書いたか
Javaを業務で使い始めて3ヶ月くらいの駆け出しエンジニアです。
Java Silverを取得するために現在勉強中。
java用語集
オペランド
a+b=cがあったとして、
この式をオペランドという
+,=を演算子という
リテラル
オペランドの中でも具体的な値5,10とかをリテラルという。
キャスト演算子
むりやり型返還すること(int)
int age = (int)3.2;
//3
パラメーター
パラメータは、関数の定義中に特定の値を定義するために使用される変数です。
要するに引数となる変数のこと
public class Example {
// 変数aとbはパラメーター
public static int myMethod(int a, int b)
{
return a + b;
}
オブジェクト指向
→データと処理をひとまとめにしてプログラムを作る考え方
メンバ変数
クラスの特性として参照可能な変数やメソッドは、そのクラスのメンバーと呼ばれます。
メンバ変数は、オブジェクトの状態を表す属性を保持するためのフィールドです。また、修飾子 static
を指定されていないメンバ変数は、インスタンス毎に確保される変数となり、インスタンス変数とも呼ばれます。
class Account {
// メンバー変数
int balance;
void setBalance(int aBalance) {
// 自分のクラスのメンバー変数へのアクセス
balance = aBalance;
}
int getBalance() {
// 自分のクラスのメンバー変数へのアクセス
return balance;
}
}
class AccountManager {
void transfer(Account account, int ammount) {
// オブジェクトのメンバー変数へのアクセス
account.balance += ammount;
}
}
ローカル変数
メソッド内やメソッド引数で定義される変数の有効範囲(スコープ)は、当該メソッド内にしか及びません。更に、メソッド内のブロック内部で定義された場合は、そのブロック内から制御が外れるとメモリ上からドロップされて永遠に失われます。このような変数を**ローカル変数**
と呼びます。ローカル変数は制御がそのスコープから外れるとメモリ上からドロップされる変数です。
メンバー変数の修飾子
final | 初期化した値以外に変更できない。定数として用いる。 |
---|---|
private | 同じクラスからしかアクセスできない。他のクラスから利用したければ、当該クラスのメソッドを介する。 |
省略 | 同じパッケージ内からしかアクセスできない。 final |
, static | |
宣言とは共存できる。 | |
protected | 同じパッケージ、またはそのサブクラスからしかアクセスできない。 |
public | アクセスに制限がない。 |
static | 静的変数。通常の変数は、インスタンスごとに異なる値を保持し、インスタンス変数と呼ばれる。一方、静的変数はインスタンスによらず共通のメモリ領域を占有する。クラスAをインスタンス化したインスタンス1とインスタンス2があるときに、インスタンス1が静的変数を10にセットしたら、インスタンス2から参照しても10になっている。静的変数の利用にはインスタンス化の必要がない。 |
アクセス修飾子の定石
・フィールドは全てprivate
・メソッドは全てpublic
・クラスは全てpublic
getter,setter
フィールドをすべてprivateにすると、外部から一切読み書きできない。
そこで、メソッドを経由してアクセスする。
public class King {
void talk(Hero h) {
System.out.println(h.name);
}
}
// これではnameはHeroクラスでの定義なので、privateの場合、Kingクラスではアクセスできない
public class Hero {
private String name;
public String getName() {
return this.name;
}
}
public class King {
void talk(Hero h) {
System.out.println(h.getName());
}
}
これをgetterメソッドという
getterメソッドの定石
public フィールドの型 getフィールド名() {
return this.フィールド名;
}
returnで変数を返しているので、メソッドの中身は変数になる。
setterメソッドの定石
public void setフィールド名(フィールドの型 任意の変数名) {
this.フィールド名 = 任意の変数名;
}
カプセル化とは
getter,setterを用いて、フィールド(変数)に間違った値が代入されることを防ぐこと。
インスタンス化
クラス名 インスタンス変数名;
インスタンス変数 = new クラス名();
ここで、二行目では、コンストラクタと呼ばれる特殊なメソッドの呼びだしという意味があります。コンストラクタは、クラスをインスタンス化してオブジェクトを作成するときに、必ず実行されています。オブジェクトの初期化という重要な役割を果たします。コンストラクタは、クラス名と同じ名前を持ち、戻り値を持たない特殊なメソッドです。
従って、上記の基本書式は、正確には次のような意味があります:
クラス名 インスタンス変数名;
インスタンス変数 = new コンストラクタ名();
Javaはインスタンス化しないと、実態にならない。
メモリ領域に値が入らないというイメージ
コンストラクタ
コンストラクタは特殊なメソッドです。クラス名と同じ名前で、 void
キーワードを持たず戻り値宣言もないメソッドです。引数の異なるコンストラクタを同時に定義することも可能です。これをオーバーロードと呼びます。
今までクラスの作成時に、コンストラクタを作ってきませんでした。コンストラクタが全く記述されていないクラスに限り、 Java コンパイラ javac
は、自動的に、引数なしで内容が空のデフォルト・コンストラクタを、生成するバイトコード内に埋め込んでくれます。引数をもつコンストラクタを自分で作ると、 javac
は引数の無いコンストラクタをもう作ってはくれないので、自分で実装する必要があります。
働きとしては、オブジェクトの初期化です。インスタンス化時に必ず呼ばれるので、必要な初期化ロジックを実装できます。メンバ変数の説明のときに、メンバ変数は暗示的に初期値が代入されると言いましたが、普通はコンストラクタを明示的に作成して、インスタンス化のときに、コンストラクタに受け渡す引数を通して初期化します。
- コンストラクタは、クラス名と同じ名前の特殊なメソッドです。
- コンストラクタは、戻り値がなく、
void
キーワードを持たない特殊なメソッドです。 - コンストラクタは、クラスを初期化する特殊なメソッドです。
- コンストラクタは、インスタンス化のときに必ず呼ばれています。
newされた直後に自動的に実行される
public Hero() {
this.hp = 100;
}
public class Main {
public static void main(String[] args) {
Hero h = new Hero(); //100
System.out.println(h.hp); //100
}
}
コンストラクタの条件
・メソッド名がクラス名と完全に等しい
・メソッド宣言に戻り値が記述されていない(voidもだめ)
コンストラクタのメリット
コンストラクタでメンバ変数を初期化することは、インスタンス作成時にインスタンスの変数の値を指定できると言うことです。つまり、インスタンス化するオブジェクトごとに固有の初期値を持たせることが出来るわけです。クラスを利用する他のクラスから見れば、専用の初期化メソッドをわざわざ呼び出す必要がなくなります。
つまり、newした時にすでに値が入っている。
メソッドのオーバーロード
Java では、メソッドを識別するのに、メソッド名と引数リストの組を使います。これをシグネチャ(署名)と呼びます。同じメソッド名でも、引数リストの異なるものは、別のものとして扱われます。同じメソッド名で、引数リストの異なるメソッドを同時に定義することを、メソッドのオーバーロード
と呼びます。
class GetMean {
//メンバ変数
double x;
//メソッド1:引数は一つ
void mean(double a) {
x = a / 10;
}
//メソッド2:引数は二つ
void mean(double a, int b) {
x = a / b;
}
}
class OverLoadTest {
public static void main(String[] args) {
//インスタンス化:オブジェクト obj の作成
GetMean obj = new GetMean();
System.out.println("メソッド1");
//引数は一つ
obj.mean(870.0);
System.out.println("obj.x: " + obj.x);
System.out.println("メソッド2");
//引数は二つ
obj.mean(972.0, 11);
System.out.println("obj.x: " + obj.x);
}
}
→つまりオーバーロードすると、メソッドの引数を色々変えたり増やしたりできる。めっちゃ便利。
オーバーライド
クラスの継承時に子のクラスで、親のクラスのメソッドを同じ名前で上書きすること
class OverrideOya {
public void retMsg() {
System.out.println("親のメッセージ");
}
}
class OverrideKo extends OverrideOya {
public void retMsg() {
System.out.println("子供のメッセージ");
}
}
class OverrideDemo {
public static void main(String[] args) {
OverrideKo objKo = new OverrideKo();
objKo.retMsg();
}
}
// "子供のメッセージ"
メソッドを上書きして、再定義ができる。
シグネチャ
メソッドの呼び出しは、クラスの完全限定名とメソッド名と引数の組で決定します。これをメソッドのシグネチャと呼びます。
super
サブクラスでオーバーライドしたメソッドを呼び出すとき、オーバーライドされたスーパークラスのメソッドの方を呼び出すことも出来ます。このとき、メソッドのプレフィックスはインスタンス名ではなく、 super
になります。
つまり継承しているときでも、親クラスのメソッドを呼び出すやり方
class Oya {
void meth() {
System.out.println("スーパークラスで実装したメソッド");
}
}
class Ko extends Oya {
//オーバーライド
void meth() {
System.out.println("サブクラスでオーバーライドしたメソッド");
}
void methOya() {
// スーパークラスのメソッド呼び出し
super.meth();
}
}
class TestOverride {
public static void main(String[] args) {
Ko obj=new Ko();
obj.meth();
obj.methOya();
}
}
//サブクラスでオーバーライドしたメソッド
//スーパークラスで実装したメソッド
super変数
親クラスの変数を使うこと
class Oya {
int x;
void setVar() {
x = 100;
}
}
class Ko extends Oya {
int x;
int y;
void getVar() {
x = 10;
y = super.x; // スーパークラスのメンバ変数 x を代入
}
}
class SuperVarDemo {
public static void main(String[] args) {
//インスタンス化
Ko obj = new Ko();
//メソッド呼び出し
obj.setVar(); //Oyaクラスで定義
obj.getVar(); //Koクラスで定義
System.out.println("obj.x: " + obj.x);
System.out.println("obj.y: " + obj.y);
}
}
//obj.x: 10
//obj.y: 100
this
とは何か
通常のメンバー変数やメソッドは、どのオブジェクトのものかを識別するために、オブジェクト名を付して呼び出します。しかし、同じクラス内のフィールドやメソッドは、オブジェクト名を付けないで裸で参照できます。オブジェクト名を省略して呼び出すと、自クラス内のメンバーだと解釈されるのです。
field; // オブジェクト自身のメンバー変数呼び出し
method(); // オブジェクト自身のメソッド呼び出し
しかし、メソッド内部で定義したローカル変数名と、当該メソッド自身が含まれるクラスのインスタンス変数名がバッティングしたときにはどうでしょうか?
class ThisTest {
String name = "Sugai"; // Member Variable
void meth() {
String name = "Tochihara"; // Local Variable
System.out.println(name); // 何が出力されますか?
}
}
結果としては、ローカル変数が優先されます。ここで出力されるのは "Tochihara" です。
メンバー変数名とローカル変数名が競合するときに、メンバー変数を参照するためには this
キーワードを使います。
class ThisTest {
String name = "Sugai"; // Member Variable
void meth() {
String name = "Tochihara"; // Local Variable
System.out.println(this.name); // Member Variable
}
}
this
キーワード
オブジェクト変数と this
あるオブジェクトのフィールドやメソッドを参照するときには、そのオブジェクトを参照する変数を接頭辞に付けて、「どのオブジェクトの」インスタンス変数なのか、「どのオブジェクトの」メソッドなのかを識別していました。
obj.name; // obj オブジェクトの name 変数
obj.meth(); // obj オブジェクトの meth() メソッド
自分のクラスのメンバーであるメソッドや変数を指定する為には this
が使えます。当該オブジェクト自身への参照が格納されています。オブジェクトを参照する変数の特殊なものと考えて良いでしょう。
抽象メソッド
抽象メソッドは修飾子 abstract
で宣言します:
abstract [戻り値型] <メソッド名>(シグネチャ);
通常のメソッドならば、実際の処理が {}
の中に記述されているはずですが、抽象メソッドの場合はセミコロン ;
になっています。
抽象メソッドでは、メソッド名とシグネチャ、戻り値の型の宣言だけ行います。
抽象メソッドは、実際の処理を記述せず、その入出力だけ宣言したメソッドとも言えます。インスタンス化するには継承して、抽象クラスをオーバーライドして実装する必要がありますが、そのときシグネチャ(引数とそのデータ型の組)と戻り値型は抽象クラスで宣言されたものに合致している必要があります。
抽象メソッドは実装の無い引数と戻り値の宣言です。従って、これを実装する場合、色々な実装方法が考えられます。同じ引数を与えても、目的に応じて異なる戻り値が返ります。逆に言うと、目的ごとに別のクラスをインスタンス化してメソッド呼び出ししても、入出力の型が同一なので、呼び出す側で変更する必要がなくなるわけです。
抽象クラス
抽象メソッドを持つクラスは抽象クラスであり、修飾子で abstract
宣言しておかなければなりません:
abstract class <クラス名>{
メンバ変数
コンストラクタ
抽象メソッド
普通のメソッド
}
抽象クラスはインスタンス化できません。必ず継承されて、継承したサブクラスがインスタンス化されます。このとき、抽象クラスの抽象メソッドはオーバーライドされて、完全なものになっていることが必要です。
抽象メソッドを持ったクラスは抽象クラスになり、利用するときには抽象メソッドを実装したサブクラスをインスタンス化する必要があります。抽象メソッドを一つでも持つクラスはインスタンス化できません。
・抽象メソッドは、「現時点では何をするかを確定できないメソッド」となる。
・抽象クラスは、newによるインスタンス化が禁止される
→継承して使ってもらうのが目的のため
・抽象メソッドは、オーバーライドしなければならない。(オーバーライド=メソッドの継承による上書き)
それまで未確定だったメソッドの内容を確定させることを実装(implements)すると表現することもある。
インタフェース
クラスから「型」だけを取り出したもの。
インタフェースは他のクラスからの「扱い方」を規定したもの。
規定する抽象メソッドはすべてpublicであると解釈される
インターフェースは抽象クラスの中の抽象クラス。
→特に抽象度が高いもの
要するに抽象クラスの親玉
public interface Sample {
void hello(); // コンパイラによってpublicで修飾される
}
インタフェースはインスタンス化できません。
インタフェースを実現するクラスを作ってインスタンス化します。
→implementというキーワードで表現する
public class ConcreteClass implememts InterfaceA, InterfaceB {
// any code
}
インタフェースには次の二つのルールを満たすフィールドであれば記述できる
- finalを使って動的に値が変更されないこと(つまり定数)
- staticを使って、インスタンスが生成できなくても使えること
implementsとextendsの使い分け
継承元 | 継承先 | 使用するキーワード | 継承元の数 |
---|---|---|---|
クラス | クラス | extends | 1つ |
インターフェース | クラス | implements | 1つ以上 |
インターフェース | インターフェース | extends | 1つ以上 |
多様性
ざっくり捉えること
Character c = new SuperHero();
本来、左辺と右辺は同じ型でなくてはならない。
Character = 箱の型
そのインスタンスを「何とみなすか」
同じSuperHeroインスタンスでも、Character型やHero型など、さまざまな箱に入れ替えることで、捉え方を変えることができる。
SuperHero();
そのインスタンスが、いったい「何」かは、一度newされたら変わることはない
is-の関係値のみ、異なる型でも代入可能
static
同じクラスから生成されたインスタンスでフィールドを共有したい場合には、staticを使う
staticがついた静的フィールドは、クラス変数とも呼ばれる
変化しない定数を共有したい場合は
public static finalを利用する
staticがついているメソッドは、静的メソッドまたはクラスメソッドと呼ばれる。
参考サイト
出典