4

パラメータタイプのオブジェクトを複製できるようにする必要があるジェネリッククラスがあります。非常に簡単な例を以下に示します。コンパイラは、Object型のclone()が表示されないと主張しています。

public class GenericTest<T extends Cloneable>
    {
    T obj;
    GenericTest(T t)
        {
        obj = t;
        }
    T getClone()
        {
        // "The method clone() from the type Object is not visible."
        return (T) obj.clone();
        }
    }

オブジェクトの整合性を維持するために発生しなければならないことが他にもあるので、呼び出し元にクローンを作成させたくありません。上記のコードは、クローンオブジェクトに関連して維持する必要のある他のデータのノイズがない問題の単なる例示です。

これを回避する方法はありますか、それともJavaの設計者がJavaの設計者が欠点を合理化することを、何も持たないことと同等と見なすケースの1つですか?

4

3 に答える 3

6

protectedメソッドはクラス上でマークされているため、Object通常、このメソッドを任意のオブジェクトで呼び出すことはできません。個人的には、これが最初は問題になるとは思いませんでした(ねえ、私はのサブクラスなObjectので、保護されたメソッドを呼び出すことができるはずですよね?)が、コンパイラはあなたがサブクラスであることを知る必要があります保護されたメソッドを呼び出すためのターゲットオブジェクトのクラス(またはそのパッケージ内)の。どちらもここでは適用されません。

メソッドの背後にある考え方は、clone()メソッドをサポートするクラスがメソッドをオーバーライドし、メソッドをとして宣言することpublicです。

ここで完全な機能を保持する唯一の実際の解決策は、リフレクションを使用してメソッドにアクセスし、アクセス修飾子を回避することです。別の方法は、パブリックメソッドが宣言された独自のMyCloneableインターフェイスを作成することです。これは、独自のドメインクラスのみを渡す場合に機能する可能性がありますが、インターフェイスの実装を強制できないため、外部クラス(またはなど)では使用できないことを意味します。 clone()java.util.Stringjava.util.ArrayList

リンクされた質問への回答によると、これは非常に疑わしいデザインです。

于 2011-03-22T16:58:59.820 に答える
3

Java側の間違い。リフレクションは正しい道です

static Method clone = Object.class.getMethod("clone"); 

static public <T extends Cloneable> 
T clone(T obj)
    return (T) clone.invoke(obj);
于 2011-03-22T22:19:11.477 に答える
0

フィールドを含むPOJOのクローンを作成する必要がありました。動作したのは次のとおりです。

public static Object clone(Object o)
{
  Object clone = null;

  try
  {
     clone = o.getClass().newInstance();
  }
  catch (InstantiationException e)
  {
     e.printStackTrace();
  }
  catch (IllegalAccessException e)
  {
     e.printStackTrace();
  }

  // Walk up the superclass hierarchy
  for (Class obj = o.getClass();
    !obj.equals(Object.class);
    obj = obj.getSuperclass())
  {
    Field[] fields = obj.getDeclaredFields();
    for (int i = 0; i < fields.length; i++)
    {
      fields[i].setAccessible(true);
      try
      {
        // for each class/suerclass, copy all fields
        // from this object to the clone
        fields[i].set(clone, fields[i].get(o));
      }
      catch (IllegalArgumentException e){}
      catch (IllegalAccessException e){}
    }
  }
  return clone;
}
于 2013-02-08T10:54:20.720 に答える