2016-07-12 4 views
-1

有用なメソッドが見つかりましたhere
ですが、配列メンバーのクラスでは機能しません。Reflection APIを使用して、生成されたfinalクラスのオブジェクトのディープコピーを作成する方法

public class Test { 
    int [] arr = new int[2]; 
} 
新しい配列をインスタンス化するために私の失敗の試みで
上記の回答から

全コード:

public static Object cloneObject(Object _obj) { 
    try { 
     // begin my changes 
     Object copy = null; 
     if (!_obj.getClass().isArray()) 
      copy = _obj.getClass().newInstance(); 
     else { 
      int len = Array.getLength(_obj); 
      Class type = _obj.getClass().getComponentType(); 
      // Next line fails with: Compiler(syntax) error 
      // copy = (type.getClass()[])Array.newInstance(_obj.getClass(), len); 
      // Next line fails with: "InstantiationException: int cannot be instantiated" 
      // copy = _obj.getClass().getComponentType().newInstance(); 
      // how then? 
     } 
     // end my changes 
     for (Field field : _obj.getClass().getDeclaredFields()) { 
      field.setAccessible(true); 
      if (field.get(_obj) == null || Modifier.isFinal(field.getModifiers())) 
       continue; 
      if (field.getType().isPrimitive() || 
       field.getType().equals(String.class) || 
       field.getType().getSuperclass().equals(Number.class) || 
       field.getType().equals(Boolean.class) 
      ) 
       field.set(copy, field.get(_obj)); 
      else { 
       Object child = field.get(_obj); 
       if (child == _obj) 
        field.set(copy, copy); 
       else 
        field.set(copy, cloneObject(field.get(_obj))); 
      } 
     } 
     return copy; 
    } catch (Exception _e){ 
     return null; 
    } 
} 

を達成することも可能ですか?

答えて

1

注意Reflectionによって報告されるので、それを反映させるにはObject.clone()を検索し、この基本クラスのメソッドがprotectedと宣言されているので、配列の優先メソッドがpublicであるにもかかわらず、setAccessible(true)でアクセス可能にします。

さらに、これは浅いコピーのみを作成するため、オブジェクト配列または複数のディメンションの場合は、この手順を再帰的に繰り返す必要があります。すべての多次元配列もObject[]のサブタイプであるため、しかし、彼らは一様に扱うことができます。

if(_obj.getClass().isArray()) { 
    Method cloneMethod = Object.class.getDeclaredMethod("clone"); 
    cloneMethod.setAccessible(true); 
    copy=cloneMethod.invoke(_obj); 
    if(copy instanceof Object[]) { 
     Object[] array=(Object[])copy; 
     for (int ix = 0; ix < array.length; ix++) 
      array[ix]=cloneObject(array[ix]); 
    } 
    return copy; 
} 
0

ちょうど行うあなたがタイプObjectの変数に代入されているようArray.newInstanceメソッドによって返される配列にキャストする必要はありません(任意のオブジェクトを受け入れる、と配列もオブジェクトです) :すべての配列型は、あなたが残念ながら、この方法ではありません

int[] array={ 1, 2, 3 }, copy=array.clone(); 

のように使用することができcloneメソッドを持っていることを

copy = Array.newInstance(type, len); 
+0

今ではライン 'field.setに失敗する(コピー、cloneObject(field.get(_obj)));' 'IllegalArgumentException:"フィールドでTest.arrにint []型があります。int [] [] "' –

+0

@AlexeyAndronovあなたの変更について質問したところ、私はあなたの質問に答えました。その部分が今働いていると思われるので、正しい答えだと思います。新しい質問がある場合は、別の質問としてそれを聞いてください。 –

+1

@Alexey Andronov: 'Array.newInstance'はコンポーネントタイプを想定しているので、' _obj.getClass() 'ではなく、この答えのように' type'を使用する必要があります。しかし、これはコピーではなく、同じタイプの新しい配列を作成するだけであることに注意してください。 – Holger

関連する問題