Java キャストの例: アップまたはダウン キャスト

PHPz
リリース: 2017-03-12 15:40:26
オリジナル
1783 人が閲覧しました

この記事では主に Java 変換 (上向き変換または下向き変換) の詳細な説明と簡単な例を紹介します。必要な方は参考にしてください。

Java プログラミングでは、

型変換 が主に含まれます。そして下方変形。

上方変革

私たちは現実でよくこう言います、「この人は歌える」。ここでは、その人が黒人か白人か、大人か子供かは気にしません。つまり、「人」という抽象的な概念を使用することを好みます。別の例として、スズメは鳥の一種 (鳥のサブタイプ) であり、鳥は動物の一種 (動物のサブタイプ) です。現実でも「スズメは鳥だ」とよく言われます。これら 2 つのステートメントは、実際にはいわゆる上向き変換であり、平たく言えば、サブクラスから親クラスへの変換を意味します。これは、Java が提唱する抽象指向プログラミングの考え方とも一致しています。次のコードを見てみましょう:



package a.b; 
public class A { 
public void a1() { 
    System.out.println("Superclass"); 
} 
}
ログイン後にコピー

A のサブクラス B:

package a.b; 
public class B extends A { 
public void a1() { 
    System.out.println("Childrenclass"); //覆盖父类方法 
} 
    public void b1(){} //B类定义了自己的新方法 
}
ログイン後にコピー

C クラス:

package a.b; 
public class C { 
public static void main(String[] args) { 
    A a = new B(); //向上转型 
    a.a1(); 
} 
}
ログイン後にコピー

C を実行すると、出力はスーパークラスですか、それともチルドレンクラスですか?当初期待していたスーパークラスではなく、チルドレンクラスです。これは、 a が実際にはサブクラス オブジェクトを指しているためです。もちろん、心配する必要はありません。Java 仮想マシンは、どの特定のメソッドを呼び出す必要があるかを自動的かつ正確に識別します。ただし、上方変換により、オブジェクトは b1() など、親クラスとは異なるメソッドを失います。 「これは必要ないのではないか?」と疑問に思う人もいるかもしれません。次のように書くこともできます:



B a = new B(); 
a.a1();
ログイン後にコピー

確かに!しかし、これにより抽象化指向のプログラミング機能が失われ、スケーラビリティが低下します。実際、それだけでなく、上方変換によってプログラミングの作業負荷も軽減されます。次のモニター クラス Monitor を見てみましょう:

package a.b; 
public class Monitor{ 
public void displayText() {} 
public void displayGraphics() {} 
}
ログイン後にコピー

LCD Monitor は Monitor のサブクラスです:



package a.b; 
public class LCDMonitor extends Monitor { 
public void displayText() { 
    System.out.println("LCD display text"); 
} 
public void displayGraphics() { 
    System.out.println("LCD display graphics"); 
} 
}
ログイン後にコピー

ブラウン管ディスプレイ クラス CRTMonitor は当然 Monitor のサブクラスです:

package a.b; 
public class CRTMonitor extends Monitor { 
public void displayText() { 
    System.out.println("CRT display text"); 
} 
public void displayGraphics() { 
    System.out.println("CRT display graphics"); 
} 
}
ログイン後にコピー

プラズマ モニター PlasmaMonitor もモニターですサブクラス:



package a.b; 
public class PlasmaMonitor extends Monitor { 
public void displayText() { 
    System.out.println("Plasma display text"); 
} 
public void displayGraphics() { 
    System.out.println("Plasma display graphics"); 
} 
}
ログイン後にコピー

これで、MyMonitor クラスが追加されました。上向きの変換がないと仮定すると、MyMonitor クラスのコードは次のとおりです:

package a.b; 
public class MyMonitor { 
public static void main(String[] args) { 
    run(new LCDMonitor()); 
    run(new CRTMonitor()); 
    run(new PlasmaMonitor()); 
} 
public static void run(LCDMonitor monitor) { 
    monitor.displayText(); 
    monitor.displayGraphics(); 
} 
public static void run(CRTMonitor monitor) { 
    monitor.displayText(); 
    monitor.displayGraphics(); 
} 
public static void run(PlasmaMonitor monitor) { 
    monitor.displayText(); 
    monitor.displayGraphics(); 
} 
}
ログイン後にコピー

おそらく、上記のコードには重複コードが多く、保守が簡単ではないことに気づいたでしょう。上向き変換を使用すると、コードをより簡潔にすることができます:



package a.b; 
public class MyMonitor { 
public static void main(String[] args) { 
    run(new LCDMonitor());           //向上转型 
    run(new CRTMonitor());           //向上转型 
    run(new PlasmaMonitor());      //向上转型 
} 
public static void run(Monitor monitor) { //父类实例作为参数 
    monitor.displayText(); 
    monitor.displayGraphics(); 
} 
}
ログイン後にコピー

また、

interfaceを使用することもできます。例:

package a.b; 
public interface Monitor { 
abstract void displayText(); 
abstract void displayGraphics(); 
}
ログイン後にコピー

LCD モニター クラス LCDMonitor を少し変更します。 LCDMonitor:

package a.b; 
public class LCDMonitor implements Monitor { 
public void displayText() { 
    System.out.println("LCD display text"); 
} 
public void displayGraphics() { 
    System.out.println("LCD display graphics"); 
} 
}
ログイン後にコピー

CRTMonitor、PlasmaMonitor クラス 変更方法LCDMonitor に似ていますが、MyMonitor は変更する必要がありません。


上向き変換は

クラスのポリモーフィズムを反映し、プログラムの単純さを強化していることがわかります。

下方変換

サブクラスから親クラスへの変換は上方変換であり、逆に親クラスからサブクラスへの変換は下方変換です。しかし、下方変換はいくつかの問題を引き起こす可能性があります。スズメは鳥であるとは言えますが、鳥はスズメであるとは言えません。次の例を見てみましょう:


A クラス:

package a.b; 
public class A { 
void aMthod() { 
    System.out.println("A method"); 
} 
}
ログイン後にコピー

A サブクラス B:

package a.b; 
public class B extends A { 
void bMethod1() { 
    System.out.println("B method 1"); 
} 
void bMethod2() { 
    System.out.println("B method 2"); 
} 
}
ログイン後にコピー

C クラス:

package a.b; 
public class C { 
   public static void main(String[] args) { 
      A a1 = new B(); // 向上转型 
      a1.aMthod();  // 调用父类aMthod(),a1遗失B类方法bMethod1()、bMethod2() 
      B b1 = (B) a1; // 向下转型,编译无错误,运行时无错误 
      b1.aMthod();  // 调用父类A方法 
      b1.bMethod1(); // 调用B类方法 
      b1.bMethod2(); // 调用B类方法 
      A a2 = new A(); 
      B b2 = (B) a2; // 向下转型,编译无错误,运行时将出错 
      b2.aMthod(); 
      b2.bMethod1(); 
      b2.bMethod2(); 
   } 
}
ログイン後にコピー

上記のコードから、下向き変換には

cast の使用が必要であるという結論を引き出すことができます。 C プログラムを実行すると、コンソールに次の出力が表示されます:

Exception in thread "main" java.lang.ClassCastException: a.b.A cannot be cast to a.b.B at 
        a.b.C.main(C.java:14) 
A method 
A method 
B method 1 
B method 2
ログイン後にコピー

実際、太字の下向き変換コードの後のコメントは、実行時エラーが発生することをすでに警告しています。最初の文の下向き変換コードはOKなのに、2番目の文のコードが間違っているのはなぜですか?これは、a1 がサブクラス B のオブジェクトを指しているためで、当然、サブクラス B のインスタンス オブジェクト b1 も a1 を指すことができます。また、a2 は親クラス オブジェクトであり、サブクラス オブジェクト b2 は親クラス オブジェクト a2 を指すことはできません。では、ダウンキャスト実行時のランタイム ClassCastException を回避するにはどうすればよいでしょうか?セクション5.7.7で学習したinstanceofを使用するだけです。クラス C のコードを変更してみましょう:

A a2 = new A(); 
if (a2 instanceof B) { 
B b2 = (B) a2; 
b2.aMthod(); 
b2.bMethod1(); 
b2.bMethod2(); 
}
ログイン後にコピー

このように処理すると、型変換中に ClassCastException が発生することを心配する必要がなくなります。

以上がJava キャストの例: アップまたはダウン キャストの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート