23

私は、Javaがプリミティブ型であるジェネリック引数をサポートしていないことを知っています。確かに、次のようなものです。

Vector<byte> test;

コンパイルに失敗します。

しかし、私がプログラムで誤って実行したちょっとした操作で、プリミティブ型の汎用オブジェクトを実際に作成できることがわかりました (以下に示す手法)。

Vector<Byte>さらに、javaは、print ステートメントが示すように、byte.class と Byte.class が 2 つの別個の獣である場合に、このインスタンスをタイプの変数に割り当てることを誤って許可します。このため、オブジェクトに対して呼び出しを実行しようとすると、予期しない奇妙な動作/エラーが発生します。

これはJavaのバグですか?それとも、この狂気に何らかの韻や理由があるのでしょうか? Java がプリミティブ型のジェネリックを作成するという予期しない動作を許可したとしても、プリミティブとは異なるクラスのラッパー型のジェネリックに割り当てることはできないようです。

import java.util.Vector;

public class Test
{
    //the trick here is that I am basing the return type of
    //the vector off of the type that was given as the generic
    //argument for the instance of the reflections type Class,
    //however the the class given by byte.class yields a non-class
    //type in the generic, and hence a Vector is created with a
    //primitive type
    public static <Type> Vector<Type> createTypedVector(Class<Type> type)
    {
        return new Vector<Type>(0,1);
    }

    public static void main(String ... args)
    {
        //these lines are to demonstrate that 'byte' and 'Byte'
        //are 2 different class types
        System.out.println(byte.class);
        System.out.println(Byte.class);

        //this is where I create an instance of type Vector<byte>
        //and assign it to a variable of type Vector<Byte>
        Vector<Byte> primitiveTypedGenericObject = createTypedVector(byte.class);

        //this line causes unexpected exceptions to be thrown
        //because primitiveTypedGenericObject is not actually type
        //Vector<Byte>, but rather Vector<byte>
        primitiveTypedGenericObject.set(0,(byte)0xFF);

    }

}
4

3 に答える 3

20

Byte.classとはどちらByte.TYPEClass<Byte>オブジェクトです。後者は、プリミティブ型とオブジェクト型を区別するために使用されます。

実際に Byte.TYPE は次のように定義されています。

public static final Class<Byte> TYPE = (Class<Byte>) Class.getPrimitiveClass("byte");

VM から型を取得する不透明なメソッドでgetPrimitiveClassあるため、これ以上調査することはできません。

したがって、プリミティブ データ型 Class を渡していると思っていても、それらは存在しないため (プリミティブを含まないオブジェクトの Java 型付けシステムに従って型付け可能なものを参照しているため、なぜそうすべきなのでしょうか?タイプがラッパー クラスにボックス化されるまでVector<Byte>)、.

しかし、最終的には、これは大した問題ではありません。実行時に実行型の注釈が消去され、ジェネリック型は何の意味もありません。を追加するたびbyteに、Byteオブジェクトに自動ボックス化され、それだけです。

現時点ではコードをテストする方法がありませんVector

于 2013-09-07T06:55:29.400 に答える
16

オートボクシングとアンボクシングに出くわしました。http://docs.oracle.com/javase/tutorial/java/data/autoboxing.htmlを参照してください。

簡単なバージョン

List<Integer> list = new List<Integer>(); 
list.add(1); // works

byte.class,などは,int.classなどに解決されます。Java 言語仕様 15.8.2を参照してください。ByteInteger

15.8.2. クラス リテラル

……

p.classp がプリミティブ型の名前 ( §4.2 )であるの型は ですClass<B>。ここで、 B はボックス化変換後の型 p の式の型です ( §5.1.7 )。

void.class( §8.4.5 )の型は ですClass<Void>

于 2013-09-07T06:53:19.750 に答える
8

いいえ!バグではありません。これはオートボクシングと呼ばれますByteを期待するジェネリック メソッドにbyteを渡すと、コンパイラはそれを Object のインスタンスである Byte に自動的にオートボックス化します。その操作のアンチテーゼはAuto Unboxingと呼ばれ、以下に示すような操作が合法である理由です。

int a = new Integer(5);
Integer b = 5;
于 2013-09-07T06:50:15.953 に答える