このリファレンス
なぜこの参照があるのですか
まず日付クラスの例を見てみましょう。
public class Date {
public int year;
public int month;
public int day;
//设置日期方法
public void setDay(int y, int m, int d){//这里隐藏了一个Date this参数
year = y;
month = m;
day = d;
}
public void printDate(){
System.out.println(year + "/" + month + "/" + day);
}
public static void main(String[] args) {
//构造三个日期类的对象d1,d2,d3
Date d1 = new Date();
Date d2 = new Date();
Date d3 = new Date();
//对d1,d2,d3三个日期进行设置
d1.setDay(1931,9,18);
d2.setDay(1937,7,7);
d3.setDay(1932,1,28);
//打印日期中的内容
d1.printDate();
d2.printDate();
d3.printDate();
}
}
上記のコードは、単純な日付クラスを定義し、メイン メソッドで 3 つのオブジェクトを作成し、Date クラスのメンバー メソッドを通じてオブジェクトを設定して出力します。コード全体のロジックは非常に単純で、何の問題もありません。
しかし、いくつかの疑問があります。
1. コードの可読性を向上させるために、setDate のパラメーターを年、月、日に変更しました。しかし、ここで、仮パラメータ名が誤ってメンバ変数と同じになってしまうという問題があります。
public void setDay(int year, int month, int day){
year = year;
month = month;
day = day;
}
現時点では、誰が誰に参照を渡しているのかを把握することは困難です。
2. 3 つのオブジェクトは setDate メソッドと printDate メソッドを呼び出していますが、これら 2 つのメソッドにはオブジェクトに関する説明がありません。設定やどのオブジェクトが印刷されるかはどのようにしてわかるのでしょうか? ? ?
この参考書は何ですか
this 参照は現在のオブジェクト (メンバー メソッドの実行時にメンバー メソッドを呼び出すオブジェクト) を指し、メンバー メソッド内のすべてのメンバー変数の操作はこの参照を通じてアクセスされます。このプロセスがユーザーから隠されているだけです (上記のコードpublic void setDay(int y, int m, int d){//a Date thisparameters is hidden here など)。つまり、ユーザーは次のことを行う必要はありません。これを渡すと、コンパイラによって自動的に完了します。
つまり、誰がこのメソッドを呼び出したとしても、これはどのオブジェクトの参照になります。(下の図からわかるように、オブジェクトのハッシュ コードは同じであり、同じオブジェクトが使用されていることを示しています)。
this によって参照されるプロパティ
1. this の型: 対応するクラス型の参照、つまり、呼び出されるオブジェクトがどのオブジェクトの参照型であるか
2.これはメンバーメソッドでのみ使用できます
3. メンバーメソッドでは、現在のオブジェクトのみを参照でき、他のオブジェクトを参照できません。
4.これはメンバー メソッドの最初の隠しパラメータであり、コンパイラは自動的にそれを渡します。メンバー メソッドが実行されると、コンパイラは、呼び出されたメンバー メソッド オブジェクトの参照をメンバー メソッドに渡す責任を負います。受け取る責任がある
4番目の機能のデモンストレーション
オブジェクトの構築と初期化
オブジェクトを初期化する方法
これまでの知識ポイントの学習を通じて、Java メソッド内でローカル変数を定義する場合は初期化する必要があり、初期化しないとコンパイルが失敗することがわかりました。
public static void main(String[] args) {
int a;
System.out.println(a);
}
//Error:java:可能为初始化变量a
上記のコードをコンパイルに渡すのは非常に簡単です。 a を正式に使用する前に、 a の初期値を設定するだけで済みます。オブジェクトの場合:
public static void main(String[] args) {
Date d = new Date();
d.printDate();
d.setDate(1931, 9, 18);
d.printDate();
}
//代码正常通过编译
特定の日付をオブジェクトに設定するには、前の SetDate メソッドを呼び出す必要があります。上記の例を通じて、次の 2 つの問題が見つかりました。
1. オブジェクトを作成するたびに SetDate メソッドを呼び出して特定の日付を設定するのは面倒ですが、オブジェクトの初期化はどのようにすればよいですか?
2. ローカル変数は使用する前に初期化する必要がありますが、ここで値を指定しなくても正常にコンパイルできるのはなぜですか?
施工方法
コンセプト
コンストラクター (コンストラクターとも呼ばれます) は、名前がクラス名と同じである必要がある特別なメンバー メソッドです。オブジェクトが作成されると、コンパイラーによって自動的に呼び出され、ライフ サイクル全体で 1 回だけ呼び出されます。オブジェクトの。
以下では、引き続き Date を使用して構築方法を示しています。
public class Date {
public int year;
public int month;
public int day;
//构造方法与类名相同,没有返回类型,设置为void也不行
//一般情况下使用public修饰
//在创建对象时由编译器自动调用,并且在对象的生命周期中只调用一次
//带有参数的构造方法
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
System.out.println("Date(int, int, int)方法被调用了");
}
public void printDate() {
System.out.println(year + "-" + month + "-" + day);
}
public static void main(String[] args) {
//这里创建了一个Date类型的对象,并没有显式调用构造方法
Date d = new Date(2021,6,9);//输出Date(int, int, int),表明方法被调用了
d.printDate();
}
}
注: コンストラクターの機能はオブジェクトのメンバーを初期化することであり、オブジェクト用のスペースを開く責任はありません。
特性
1. 名前はクラス名と同じである必要があります
2. 戻り値の型はありません (void も含む)
3. オブジェクトの作成時にコンパイラによって自動的に呼び出され、オブジェクトのライフサイクルで 1 回だけ呼び出されます。
4.建設方法は過負荷を可能にします(独自のニーズに応じて異なる建設方法を提供します)。
コンストラクターのオーバーロード:
public class Date {
public int year;
public int month;
public int day;
//无参的构造方法
public class Date () {
}
//带有三个参数的构造方法
public class Date (int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
}
上記の 2 つの構築メソッド (同じ名前、異なるパラメーター リスト) は、メソッドのオーバーロードを構成します。
5. ユーザーが明示的に定義しない場合、コンパイラはデフォルトの構築メソッドを生成します。これにはパラメータを含めることはできません (注: ユーザーが定義した場合、コンパイラはそれを再生成しません)。
public class Date {
public int year;
public int month;
public int day;
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
System.out.println("Date(int, int, int)方法被调用了");
}
public void printDate() {
System.out.println(year + "-" + month + "-" + day);
}
public static void main(String[] args) {
//如果编译器会生成,则生成的构造方法是无参的,则会通过编译
//但此处未通过编译
Date d = new Date();
d.printDate();
}
}
//这里没有通过编译,原因是编译器未生成构造方法,而是默认用用户的构造方法
//用户构造的和创建对象时的参数类型不匹配,所以没有通过编译
6. 構築メソッドでは、この参照を通じて他の構築メソッドを呼び出してコードを簡素化できます。
public class Date {
public int year;
public int month;
public int day;
//无参的构造方法-内部给各个成员赋初值,该部分功能与三个参数的构造方法相重复
//但是此处可以通过this调用带有三个参数的构造方法
//this(1900,1,1);必须是构造方法的第一条语句
public class Date () {
//调用当前类的其它构造方法,不让自己构造自己
this(1900,1,1);
//this.year = 1900;
//this.month = 1;
//this.day = 1;
}
//带有三个参数的构造方法
public class Date (int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
}
注: this(...) はコンストラクターの最初のステートメントでなければなりません。
リングを形成できません:
//コンパイルエラー: 再帰的コンストラクターの使用
7. ほとんどの場合、変更には public を使用しますが、特殊なシナリオでは、private によって変更されます。
デフォルトの初期化
上記の 2 番目の質問と同じです。ローカル変数は使用時に初期化する必要があるのに、メンバー変数は初期化しないのはなぜですか?
このプロセスを理解するには、新しいキーワードの背後で何が起こっているかを知る必要があります。
日付 d = 新しい日付(2021, 6, 9);
プログラムの表面ではこれは単純なステートメントかもしれませんが、仮想マシン レベルでは実行すべきことがたくさんある可能性があります。
1. オブジェクトに対応するクラスがロードされているかどうかを確認し、ロードされていない場合はロードします。
2. オブジェクト用のスペースを割り当てる
3. 同時実行性のセキュリティ問題への対処
例: 複数のスレッドが同時にオブジェクトに適用されるため、JVM はオブジェクトに割り当てられたスペースが競合しないことを確認する必要があります。
4. 割り当てられた領域を初期化します
つまり、オブジェクト空間が適用された後、オブジェクトに含まれるメンバーの初期値が次のように設定されます。
5. オブジェクトヘッダー情報を設定する
6. コンストラクターを呼び出し、オブジェクトの各メンバーに値を割り当てます
今回はこれで終わりです。ご支援ありがとうございました。!!