こんにちは!今日は、instanceof 演算子について説明し、その使用例を見て、その操作に関連するいくつかの点に触れます :) JavaRush の初期レベルでは、すでにこの演算子に遭遇しています。なぜそれが必要なのか覚えていますか? そうでなくても大丈夫ですので、一緒に思い出しましょう。変数 X によって参照されるオブジェクトがクラス Y から作成されたかどうかを確認するには、instanceof 演算子が必要です。簡単そうに思えます。なぜこの話題に戻ったのでしょうか? まず第一に、Java の継承メカニズムやその他の OOP 原則についてはよく理解できたと思います。instanceofのトピックはより明確になり、より高度な使用例を見ていきます。行く!たぶん、instanceof 演算子は、テストが true の場合はtrueを返し、結果が false の場合はfalse を返すことを覚えているでしょう。したがって、さまざまなタイプのテスト条件で最も頻繁に見られます (
if…else
)。より簡単な例から始めましょう。
public class Main {
public static void main(String[] args) {
Integer x = new Integer(22);
System.out.println(x instanceof Integer);
}
}
コンソールには何が出力されると思いますか? まあ、ここでは明らかです:) オブジェクトはх
整数なので、結果はtrueになります。コンソール出力: true たとえば、それが String に属しているかどうかを確認してみましょう。
public class Main {
public static void main(String[] args) {
Integer x = new Integer(22);
System.out.println(x instanceof String);// error!
}
}
エラーが発生しました。そして、注意してください。コードが実行される前であっても、コンパイラはそれを発行しました。彼はすぐに、Integer と String は相互に自動的に変換できず、継承関係がないことに気づきました。したがって、Integer クラスのオブジェクトは String からは作成されません。これは便利で、プログラムの実行中にすでに発生している奇妙なエラーを回避するのに役立ちます。そのため、コンパイラーがここで私たちを助けてくれました :) 次に、より複雑な例を見てみましょう。継承について触れたので、この小さなクラス システムを使ってみましょう。
public class Animal {
}
public class Cat extends Animal {
}
public class MaineCoon extends Cat {
}
通常の状況で、オブジェクトがクラスに属しているかどうかを確認するときに、instanceof がどのように動作するかはすでにわかっていますが、ここに親子関係を追加するとどうなるでしょうか? たとえば、次のチェックでは何が生成されると思いますか。
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
System.out.println(cat instanceof Animal);
System.out.println(cat instanceof MaineCoon);
}
}
出力: true false 答える必要がある主な質問は、instanceof が「クラスに基づいて作成されたオブジェクト」という概念をどのように正確に解読するかということです。結果として、私たちはそれを得ることができましたСat instanceof Animal == true
が、そのような公式には間違いを見つけることができます。なぜこのオブジェクトはCat
クラスに基づいて作成されるのでしょうかAnimal
? 独自のクラスに基づいて作成されているだけではありませんか? 答えは非常に簡単で、あなたはすでにそれを見つけているかもしれません。オブジェクトの作成時にコンストラクターが呼び出され、変数が初期化される順序を覚えておいてください。このトピックについては、クラス コンストラクターに関する記事ですでに説明しました。その講義の例を次に示します。
public class Animal {
String brain = "The initial value of brain in the Animal class";
String heart = "The initial value of heart in the Animal class";
public static int animalCount = 7700000;
public Animal(String brain, String heart) {
System.out.println("The constructor of the Animal base class is being executed");
System.out.println("Have the variables of the Animal class already been initialized?");
System.out.println("The current value of the static variable animalCount = " + animalCount);
System.out.println("Current value of brain in class Animal = " + this.brain);
System.out.println("Current value of heart in class Animal = " + this.heart);
this.brain = brain;
this.heart = heart;
System.out.println("Animal base class constructor completed!");
System.out.println("Current value of brain = " + this.brain);
System.out.println("Current value of heart = " + this.heart);
}
}
class Cat extends Animal {
String tail = "The initial value of tail in the Cat class";
static int catsCount = 37;
public Cat(String brain, String heart, String tail) {
super(brain, heart);
System.out.println("The constructor of the Cat class has started (the Animal constructor has already been executed)");
System.out.println("The current value of the static variable catsCount = " + catsCount);
System.out.println("Current value tail = " + this.tail);
this.tail = tail;
System.out.println("Current value tail = " + this.tail);
}
public static void main(String[] args) {
Cat cat = new Cat("Brain", "Heart", "Tail");
}
}
これを IDE で実行すると、コンソール出力は次のようになります: 基本クラス Animal のコンストラクターが実行されています。Animal クラスの変数はすでに初期化されていますか? 静的変数の現在値animalCount = 7700000 Animalクラスのbrainの現在値 = Animalクラスのbrainの初期値 Animalクラスのheartの現在値 = Animalクラスのheartの初期値 基本Animalクラスのコンストラクタ作業が完了しました!Brain の現在値 = Brain Heart の現在値 = Heart Cat クラスのコンストラクタが動作を開始しました (Animal コンストラクタは既に実行されています) 静的変数 catsCount の現在値 = 37 tail の現在値 = the の tail の初期値Cat クラス 現在のしっぽの値 = Tail 今覚えていますか? :) 基本クラスのコンストラクターがある場合は、オブジェクトの作成時に常に最初に呼び出されます。А
Instanceof は、オブジェクトがクラスから作成されたかどうかを判断するときにこの原則に従いますБ
。基本クラスのコンストラクターが呼び出されれば、疑いの余地はありません。2 番目のチェックでは、すべてがより簡単になります。
System.out.println(cat instanceof MaineCoon);
の作成時にコンストラクターはMaineCoon
呼び出されませんでしたがCat
、これは論理的です。結局のところ、MaineCoon
彼は先祖Cat
ではなく子孫です。しかし、Cat
それはテンプレートではありません。よし、これで明らかだ。これを実行するとどうなるでしょうか:
public class Main {
public static void main(String[] args) {
Cat cat = new MaineCoon();
System.out.println(cat instanceof Cat);
System.out.println(cat instanceof MaineCoon);
}
}
うーん...これはもっと複雑です。推論してみましょう。type の変数がありCat
、それに type のオブジェクトを割り当てていますMaineCoon
。ところで、なぜこれが機能するのでしょうか?これは可能でしょうか?できる。結局のところ、メインクーンはどれも猫です。完全に明確でない場合は、プリミティブ型拡張を使用した例を思い出してください。
public class Main {
public static void main(String[] args) {
long x = 1024;
}
}
1024という 数字は短いです。バイト数で十分なので、長い変数に簡単に収まります(入れ子人形の例を覚えていますか?)。子オブジェクトは常に祖先変数に割り当てることができます。とりあえずこれを覚えておいてください。次の講義では、このプロセスをさらに分析します。それでは、この例では何が生成されるのでしょうか?
Cat cat = new MaineCoon();
System.out.println(cat instanceof Cat);
System.out.println(cat instanceof MaineCoon);
instanceof は何をチェックしますか: クラス変数ですかCat
、それともクラス オブジェクトMaineCoon
ですか? 実は、この質問に対する答えは簡単です。演算子の定義をもう一度読む必要があるだけです。instanceof 演算子は、変数によって参照されるオブジェクトがX
何らかのクラスに基づいて作成されたかどうかを確認するために必要ですY
。 instanceof 演算子は、変数ではなくオブジェクトの起源をチェックします。したがって、この例では、どちらの場合もコンソールにtrue と 表示されます。タイプ のオブジェクトがありますMaineCoon
。当然、クラスに基づいて作成されましたMaineCoon
が、親クラスにも基づいて作成されましたCat
。
GO TO FULL VERSION