ホームページ  >  記事  >  Java  >  Java での型転送に注意する

Java での型転送に注意する

王林
王林オリジナル
2024-09-12 10:16:50741ブラウズ

Java は厳密に型指定された言語ですが、異なる型のプリミティブ変数間で値を転送することは可能です。たとえば、値を受け取る型の記憶容量が処理できる限り、int の値を double に問題なく代入できます。

各プリミティブ型のサイズについては以下を参照してください:

Cuidados com transferência de tipos em Java

より大きなストレージ容量を持つ型への値の転送には、「拡張変換」という技術名が付いています。この用語はポルトガル語では通常「拡大変換」または「拡大変換」と訳されます。これは、情報を失うことなく、より小さい、またはより制限されたデータ型の値を、より大きい、またはより包括的な型に変換するプロセスを指します。

しかし、ストレージ容量が小さい型に値を転送したい場合はどうすればよいでしょうか? Java コンパイラはこれを好みませんが、以下の例のようにキャストすると許可します。

double decimal = 65.9;
int i = (int) decimal; //aqui ele perde a casa decimal e vira 65
char c = (char) i; //aqui ele vira a letra A (que corresponde a 65)

新しい型に渡される値のサイズがその型の制限を超える場合、より劇的なことが起こる可能性があります。 int i = 10 は、-128 ~ +127 の範囲の 8 ビットを含むため、バイト変数に収まります。ただし、int i = 128 を byte 型の変数に入れたい場合はどうなるでしょうか...情報が失われます。

public class Main
{
    public static void main(String[] args) {
        int i = 128;
        byte b = (byte) i;

        System.out.println(b); // o valor de b agora é -128 :S
    }
}

オートボクシング

前回の投稿 [ここで読んでください] では、Wrapper クラスについて少しお話しました。例として、私は Integer.parse(i) = i が型
であると想像してくださいと書きました。 プリミティブ int。

現在、Wrapper parse メソッドの使用は非推奨であるため推奨されません。プリミティブを Wrapper クラスに変換し、この方法で組み込みメソッドを使用するには、次の例のように「オートボックス化」を行うことをお勧めします。

Character ch = 'a';
Integer i = 10;

これはより直接的なアプローチであることに注意してください。一度に値を代入するだけです。

逆にデータをプリミティブ型として返すには、valueOf:
メソッドを使用して「ボックス化解除」を行うことができます。

Integer i = 10;
int j = Integer.valueOf(i);

前の投稿で述べたように、プリミティブからラッパーを作成すると、クラスのメソッドを使用できるようになり、データの操作が容易になるという利点があります。

プリミティブのラッパー バージョンは一見するとよく似ているように見えますが、JVM はオブジェクトとプリミティブを同じように扱うわけではないことを忘れないでください。プリミティブはスタックに移動し、オブジェクトはヒープに移動することを思い出してください [ここを思い出してください]。

パフォーマンスの点では、値が参照ではなく直接保存されるため、プリミティブからデータを取得する方がコンピューターのコストが低いことは明らかです。断片をメモリ内にまとめ続けるよりも、既成のデータを取得する方がはるかに高速です。

ただし、Wrapper の使用が不可欠な場合もあります。たとえば、ArrayList クラスを操作する場合です。オブジェクトのみをパラメータとして受け入れ、プリミティブ値は受け入れません。

プリミティブからオブジェクトへ、またはその逆のこの変換がもたらす柔軟性は、この言語の優れた点です。しかし、私たちはここで説明したこれらの落とし穴や他の多くの落とし穴に注意する必要があります。

社会に衝撃を与えるためです (笑) オーバーロードを扱う際のコードの予期せぬ動作に関わる問題のあるケースの例を示します (オーバーロードについてはまだ投稿していませんが、投稿します。基本的にはそうします) 、メソッドに異なるシグネチャがある場合、オーバーロードが発生します)。

この事例は、Joshua Bloch 著「Effective Java」という本で言及されています。

public class SetListTest {
    public static void main(String[] args) {
        Set<Integer> set = new TreeSet<>();
        List<Integer> list = new ArrayList<>();

        for (int i = -3; i < 3; i++) {
            set.add(i);
            list.add(i);
        }

        for (int i = 0; i < 3; i++) {
            set.remove(i);
            list.remove(i); // como corrigir: list.remove((Integer) i);
        }

        System.out.println(set + " " + list);

    }

このプログラムの目的は、-3 から 2 までの整数値 [-3, -2, -1, 0, 1, 2] をセットとリストに追加することでした。次に、正の値 [0、1、2] を削除します。しかし、このコードを実行すると、セットとリストが同じ結果を示さないことがわかります。セットは期待どおり [-3, -2, -1] を返します。リストは [-2, 0, 2] を返します。

これは、List クラスの組み込み Remove(i) メソッドの呼び出しが i をプリミティブ型 int として扱い、それ以外は何も扱わないために発生します。次に、このメソッドは位置 i の要素を削除します。

Set クラスのremove(i) メソッドの呼び出しは、Integer オブジェクトをパラメータとして受け取るオーバーロードを呼び出し、元は int であった i を Integer に自動的に変換します。このメソッドの動作では、i に等しい値を持つ (i に等しいインデックスではない) 要素がセット要素から除外されます。セットとリストの両方で予期される型は整数であることに注意してください。 (セットセット/リストリスト)。 Set クラスから削除メソッドに選択されたオーバーロードがそれを Integer に変換したのはそのためです。

List の Remove の動作はインデックスによって削除されますが、Set の Remove は値によって削除されます。すべては、Integer を受け取る Remove のオーバーロードが原因です。

以上がJava での型転送に注意するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。