문제

나는 객체 인스턴스화의 대안으로 클로닝을 사용하는 것으로 보이는 구형 Java 코드베이스 (JVM 1.4)를 유지하고 있습니다. 성능 최적화로 추측하고 있습니다. 다음은 고려 된 예입니다.

public class Foo {
  private SomeObject obj; // SomeObject implements Cloneable
  public Foo() {
    obj = new SomeObject();
    obj.setField1("abc"); // these fields will have the same value every time
    obj.setField2("def");
  }
  public void doStuff() {
    SomeObject newObj = obj.clone(); // clone it instead of using a factory method
    // do stuff with newObj
  }
}

조기 최적화에 대한 일반적인 경고에도 불구하고, 이것은 실제로 어느 시점에서 권장되는 관용구였습니까?

도움이 되었습니까?

해결책

호출해야 할 한 가지 이유 clone() 사본 생성자 또는 공장 방법 대신 다른 옵션 중 어느 것도 사용할 수 없다는 것입니다.

구현 clone() 얕은 객체 사본을 수행하려면 (딥 카피가 더 관여합니다), 동일한 작업을 수행하기 위해 사본 생성자 또는 공장 방법을 구현하는 것과 비교할 때 사소한 일입니다. 구현 clone(), 클래스는 단순히 구현이 필요합니다 Cloneable 인터페이스 및 재정의 메소드 clone() 호출하는 하나와 함께 super.clone() 일반적으로 호출합니다 Object.clone(). Object.clone() 원래 객체의 모든 속성을 복사의 해당 속성에 복사하여 얕은 사본을 만듭니다.

구현되었지만 clone() 간단합니다. 여전히 구현하는 것을 잊기 쉽습니다. Cloneable. 결과적으로 사용의 잠재적 위험 clone() 객체를 복제하는 것은 해당 객체의 클래스가 구현을 무시하는 경우 Cloneable 그리고 clone() 호출 Object.clone() 직간접 적으로 던질 것입니다 CloneNotSupportedException.

이것 좀 봐 코드 예제 그리고 이전 논의열악한 디자인Cloneable 상호 작용.

다른 팁

아마도 그들은 사본을 원했을 것입니다. 아마도 그들은 그것을 다른 함수로 전달하기를 원할 것입니다. 그리고 그 함수가 그것을 변경하지 않을 것이라고 확신 할 수 없습니다. 그것은 dostuff () 메소드가 호출 된 Foo 객체의 상태와 관련하여 const인지 확인하는 방법입니다.

사본 생성자의 주요 문제 중 하나는 객체의 유형을 컴파일 시간에 알려야한다는 것입니다. 상속 가능한 클래스가 사본 생성자를 지원하고 생성자가 파생 클래스 객체를 통과하는 경우, 생성자는 기본 등급의 특성이 일반적으로 전달 된 개체의 특성과 일치하지만 새 객체가 원한다. t 기본 클래스에 존재하지 않은 통과 된 객체에 존재했던 모든 기능을 지원합니다.

사본 생성자를 "보호"하고 해당 클래스의 자체 사본 생성자를 호출하는 모든 파생 클래스에 우선 공장 사본 메소드를 사용 하여이 문제를 다소 해결할 수 있으며,이 클래스는 기본 클래스의 사본 생성자를 호출합니다. 모든 파생 클래스는 사본 생성자와 복사 메소드의 재정의가 필요하지만 새 필드를 추가하는지 여부는 필요합니다. 케이스 클래스가 "클론"을 사용하면이 추가 코드를 제거 할 수 있습니다.

생성자에서 얼마나 많은 작업이 수행되는지에 따라 성능 최적화 일 수 있습니다.

의미론이 다르기 때문에 더 많이 사용될 가능성이 높습니다. 클로닝은 일반적으로 그런 경향이없는 언어로 "프로토 타입 시맨틱 (JavaScript, Self 등)을 구현하는 방법을 제공합니다.

일부 관점 생성자가 데이터베이스에서 무언가를 잡거나 무언가를 구문 분석하거나 파일에서 무언가를 읽는 것과 같이 비싼 작업을 수행하는 경우 클론은 작업을 피하기 위해 합리적입니다.

생성자가 아무것도하지 않으면 실제로 클론을 사용할 필요가 없습니다.

편집 : Clone이 생성자와 동일한 작업을 수행 할 필요가 없음을 보여주기 위해 코드가 추가되었습니다.

class Main
    implements Cloneable
{
    private final double pi;

    public Main()
    {
        System.out.println("in Main");
        // compute pi to 1,000,000,000 decimal palaces
        pi = 3.14f;
    }

    public Object clone()
    {
        try
        {
            return (super.clone());
        }
        catch(final CloneNotSupportedException ex)
        {
            throw new Error(); // would not throw this in real code
        }
    }


    public String toString()
    {
        return (Double.toString(pi));
    }

    public static void main(String[] args)
    {
        final Main a;
        final Main b;

        a = new Main();
        b = (Main)a.clone();

        System.out.println("a = " + a);
        System.out.println("b = " + b);
    }
}

메인 아트 투 루터는 한 번이라고 불리며 컴퓨팅 PI는 한 번 수행됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top