誰かが拡大または縮小変換を使用する理由を説明できますか? 私はこれらについて多くのことを読んだことがありますが、誰も私に実用的な例を教えてくれません. ありがとう!
5 に答える
(Java) 拡大変換と縮小変換は、関連する型間の変換に関係しています。たとえば、抽象 (スーパー) クラスとその (子) サブクラスの間の関係を考えてみましょう。java.lang.Number クラス (抽象) と直接のサブクラス Integer を使用してみましょう。ここに次のものがあります。
(superclass) Number
__________/\__________
/ | | \
(concrete subclasses) Integer Long Float Double
拡張変換: 特定の型 (サブクラス) を取り、それをあまり具体的でない型 (スーパークラス) に割り当てようとすると発生します。
Integer i = new Integer(8);
Number n = i; // this is widening conversion; no need to cast
ナローイング変換: 特定性の低い型 (スーパークラス) を取得して、それをより具体的な型 (サブクラス) に割り当てようとすると発生します。これには、明示的なキャストが必要です。
Number n = new Integer(5); // again, widening conversion
Integer i = (Integer) n; // narrowing; here we explicitly cast down to the type we want - in this case an Integer
ClassCastExceptions など、注意が必要な特定の問題があります。
Integer i = new Integer(5);
Double d = new Double(13.3);
Number n;
n = i; // widening conversion - OK
n = d; // also widening conversion - OK
i = (Integer) d; // cannot cast from Double to Integer - ERROR
// remember, current n = d (a Double type value)
i = (Integer) n; // narrowing conversion; appears OK, but will throw ClassCastException at runtime - ERROR
これを処理する 1 つの方法は、次のキーワードを含むif
ステートメントを使用することです。instanceof
if( n instanceof Integer) {
i = (Integer) n;
}
なぜこれを使いたいのですか?あるプログラムのために人事の階層を作成していて、姓と名をパラメーターとして受け取る「Person」と呼ばれる汎用スーパークラスと、「Student」、「Teacher」、「Secretary」などのサブクラスがあるとします。最初に一般的な人物を作成し、それを(継承を通じて)たとえば、コンストラクターに設定されたStudenIDの追加の変数フィールドを持つ学生に割り当てることができます。より一般的な (より広い) 型をパラメーターとして取り、その型のすべてのサブクラスも処理する単一のメソッドを使用できます。
public static void main(String[] args) {
Person p = new Student("John", "Smith", 12345);
printInfo(p);
}
// this method takes the wider Person type as a parameter, though we can send it a narrower type such as Student if we want
public static void printInfo(Person p) {
System.out.println("First: " + p.getFirstName());
System.out.println("Last: " + p.getLastName());
if (p instanceof Student) {
System.out.println( (Student)p).getStudentID() ); // we cast p to Student with Narrow Conversion which allows us to call the getStudentID() method; only after ensuring the p is an instance of Student
}
}
これは物事を処理する理想的な方法ではないかもしれませんが、デモンストレーションのために、いくつかの可能性を示すのに役立つと思いました.
拡大変換と縮小変換の標準的な例の 1 つは、特定のファイル I/O ライブラリがどのように機能するかです。多くの場合、ファイル処理ライブラリには、ファイルから単一の文字を読み取る関数/メソッドがあります。読み取る文字がある場合、関数はその文字を返す必要があり、文字が残っていない場合は、これを通知するためにセンチネル値 EOF を返す必要があります。
ファイルには任意の文字が表示される可能性があるため、通常、関数/メソッドには次のシグネチャがあります。
int readCharacter();
ここで、関数は、文字が読み取られた場合は値を保持し、それ以外の場合は番兵として int
保持する を返します。は通常、大きすぎて に保持できない整数として選択されます。そうすれば、これを行うことができます:char
EOF
EOF
char
while (true) {
int ch = readCharacter();
if (ch == EOF) break;
char actualCharValue = (char) ch;
/* process actualCharValue here */
}
お役に立てれば!