Java の学習ノートを記録しておきます。
重载#
重载:オーバーロードは、メソッドのオーバーロードを指し、オーバーロードの特徴は、2 つ以上のメソッドが同じ名前を持つことです。
クラシックなオーバーロードメソッド#
オーバーロードは主にコンストラクタメソッドで使用されます。なぜなら、コンストラクタの役割はオブジェクトの構築を初期化することであり、コンストラクタの名前はクラス名と同じでなければならないため、これがクラシックな引数なしコンストラクタと引数付きコンストラクタのオーバーロードメソッドのペアを形成します。
以下に例を示します:
/**
* 作者:mingyu
*/
public class User {
private Integer id;
private String userName;
// 引数なしコンストラクタ
public User() {
}
// 単一の引数を持つコンストラクタ
public User(Integer id) {
this.id = id;
}
// 全引数を持つコンストラクタ
public User(Integer id, String userName) {
this.id = id;
this.userName = userName;
}
}
なぜオーバーロードが必要なのか#
私たちは皆、Java で最も重要な概念である「オブジェクト」を知っています。メソッドはオブジェクトの行動です。同じ名前の行動をするオブジェクトは、異なることをしているかもしれません。例えば、小明が麻雀を打っているとします。
文字通りの意味:小明は他の人と一緒に麻雀をするという娯楽活動をしています。
他の意味:小明は「麻雀」という名前の人を「打つ」ことをしています。
したがって、現実の生活の言語の曖昧さはコードでも発生する可能性があります。
また、人が何かを食べている場合、私が彼に何かを与えると、彼はそれを食べます。私が彼に麺を与えると、彼の行動は麺を食べることです。私が彼にご飯を与えると、彼の行動はご飯を食べることですが、彼の行動はすべて「食べる」と呼ばれます。
まとめると、オーバーロードはコードで非常に必要です。
オーバーロードの区別#
同じ名前の異なるメソッドをどのように区別しますか?
オーバーロードを区別するための重要な原則:各オーバーロードメソッドには一意のパラメータタイプリストが必要です(つまり、各メソッドには他の同名のメソッドと異なる引数があります)
では、どのような点が異なるのでしょうか?
パラメータタイプの違い#
public class Test {
public static void main(String[] args) {
// ageの型が異なるため、同じ名前の2つのメソッドを区別できます
getPerson("mingyu", 18);
getPerson("mingyu", "18");
}
static void getPerson(String name, int age) {
System.out.println("name: " + name + ", " + "int_age: " + age);
}
static void getPerson(String name, String age) {
System.out.println("name: " + name + ", " + "String_age: " + age);
}
}
出力結果:
name: mingyu, int_age: 18
name: mingyu, String_age: 18
パラメータの順序の違い#
パラメータの順序が異なる場合、同じ名前のオーバーロードメソッドを区別することはできますが、このような方法で区別することはお勧めしません。なぜなら、このようなコードを書くと、メンテナンスが困難になるからです。
public class Test {
public static void main(String[] args) {
getPerson("mingyu", 18);
getPerson(18,"mingyu");
}
static void getPerson(String name, int age) {
System.out.println("name: " + name + ", " + "behind_age: " + age);
}
static void getPerson(int age, String name) {
System.out.println("name: " + name + ", " + "first_age: " + age);
}
}
出力結果:
name: mingyu, behind_age: 18
name: mingyu, first_age: 18
戻り値でオーバーロードメソッドを区別する#
パラメータリストの型、順序だけでなく、戻り値でオーバーロードメソッドを区別することはできますか?
答えはできません、以下に例を示します。
void f() {}
int f() { return 1; }
f()
メソッドを呼び出す必要があり、メソッドの戻り値は必要ない場合(System.out.println
メソッドなど)、Java はどのメソッドを呼び出す必要があるかを区別することができません。
基本型のオーバーロード#
基本型のみが異なるオーバーロードメソッドの場合、基本型は小さい型から大きい型に自動的に昇格する場合があります。
public class Test {
public static void main(String[] args) {
int x = 5;
checkBasicTypes(x);
}
static void checkBasicTypes(long x) {
System.out.println("Type long: " + x);
}
static void checkBasicTypes(float x) {
System.out.println("Type float: " + x);
}
static void checkBasicTypes(double x) {
System.out.println("Type double: " + x);
}
}
出力結果:
Type long: 5
変数 x は int 型ですが、checkBasicTypes()
メソッドには int 型の引数がありません。プログラムが実行されると、int 型よりも大きい型のメソッドを呼び出すため、渡されるデータ型は自動的に昇格されます。( int -> long)
重写#
オーバーライドは通常、親子クラスの関係で発生し、親クラスと子クラスの間には名前とパラメータリストの両方が同じメソッドが 2 つあります。同じメソッド名を持つため、メソッド呼び出し時には子クラスのメソッドが親クラスの同名メソッドを上書きします。
以下はオーバーライドの例です。
public class Test {
public static void main(String[] args) {
Animal animal = new Dog();
animal.say();
}
}
class Animal {
public void say() {
System.out.println("I'm animal.");
}
}
class Dog extends Animal {
@Override
public void say() {
System.out.println("I'm Dog.");
}
public void eat() {
System.out.println("Dog like eat meat.");
}
}
出力結果:
I'm Dog.
上記の例では、親クラスと子クラスの両方で say()
メソッドが定義されていますが、実際には子クラスが親クラスの say()
メソッドをオーバーライドしています。
オーバーライドされたメソッドでは、子クラスのオブジェクトの型が Animal であっても、Java は依然として Dog の say()
メソッドを呼び出します。なぜなら、子クラスのメソッドは同名の親クラスのメソッドを上書きするからです。
オーバーライドの原則#
メソッドをオーバーライドする場合、リスコフの置換原則を満たす必要があります。
- サブクラスのメソッドのアクセス権限は、スーパークラスのメソッドのアクセス権限以上でなければなりません。
- 例:スーパークラスのメソッドの修飾子が protected の場合、サブクラスのメソッドの修飾子は protected または public でなければなりません。
- サブクラスのメソッドの戻り値の型は、スーパークラスのメソッドの戻り値の型と同じか、そのサブタイプでなければなりません。
- 例:B extends A の場合、スーパーメソッドの戻り値の型が A の場合、サブクラスのメソッドは A 型または B 型を返すことができます。
- サブクラスのメソッドがスローする例外の型は、スーパークラスがスローする例外の型と同じか、そのサブタイプでなければなりません。
@Override アノテーション#
@Override
アノテーションは Java のキーワードではありませんが、キーワードと同じように使用できます。このアノテーションをオーバーライドメソッドに追加すると、コンパイラが上記の 3 つの制限条件をチェックし、オーバーライドメソッドが有効かどうかを確認してくれます。時には、意図しないオーバーロードを防ぐのにも役立ちます。