1

配列リストがあり、この配列リストにほとんど変更を加えずにいくつかのオブジェクトを追加したいと考えています。

これが私のコードです。

Student student = createSampleStudent();
List<Student> studentList= new ArrayList<Student>();

for(int i = 0; i < 5; i++) {
    student.setId(getRandomId());
    studentList.add(student);
}

異なるIDで学生をstudentListに追加したいのですが、学生の作成に時間がかかりすぎるため、forループで学生を作成できません。clone メソッドがあることがわかりましたが、 Student オブジェクトには多くのフィールドがあります (それらのほとんどは別のオブジェクトを参照しています)。アイデアはありますか?

4

1 に答える 1

0

オブジェクトをコピーする不気味な方法を教えてください。本番コードでは使用しないでください。しかし、うまくいくと思います。Unsafe、Sun のバックドアを使用できます。Unsafe インスタンスを取得するだけです。

Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null);

IDE を無視すると、アクセス制限について警告が表示されますが、このコードを実行するとすべてが機能します。エラーが煩わしい場合は、環境設定のエラーを無視してください。この後、低レベルのメモリ コピーでオブジェクトのコピーを実行できます。

private static long normalize(int value) {
    if(value >= 0) return value;
    return (~0L >>> 32) & value;
}

public static long sizeOf(Object object){
    return getUnsafe().getAddress(
        normalize(getUnsafe().getInt(object, 4L)) + 12L);
}

private static long toAddress(Object obj) {
    Object[] array = new Object[] {obj};
    long baseOffset = getUnsafe().arrayBaseOffset(Object[].class);
    return normalize(getUnsafe().getInt(array, baseOffset));
}

private static Object fromAddress(long address) {
    Object[] array = new Object[] {null};
    long baseOffset = getUnsafe().arrayBaseOffset(Object[].class);
    getUnsafe().putLong(array, baseOffset, address);
    return array[0];
}

static Object shallowCopy(Object obj) {
    long size = sizeOf(obj);
    long start = toAddress(obj);
    long address = getUnsafe().allocateMemory(size);
    getUnsafe().copyMemory(start, address, size);
    return fromAddress(address);
}

結局のところ、この構造を for ループで呼び出すことができます。

Student student = createSampleStudent();
List<Student> studentList= new ArrayList<Student>();
for(int i = 0; i < 5; i++) {
    student = MyUnsafeUtil.shallowCopy(student);
    student.setId(getRandomId());
    studentList.add(student);
}

覚えておいてください、これは Java の非常に悪い魔法です。

于 2013-12-16T09:07:34.827 に答える