2009-07-06 3 views
10

누구든지 Java에서 복사 생성자/팩토리 메서드 등의 권장되거나 설정된 모범 사례 및 명명 규칙을 갖고 있습니까? 특히 클래스가 Thing이고, Thing과 동일한 값을 가진 새로운 Thing (또는 인스턴스 메소드 인 경우 인스턴스로)을 반환하는 메소드가 필요합니다. 이걸 생성자 또는 정적 팩토리 메서드 또는 인스턴스 메서드로 사용 하시겠습니까? 뭐라고 부릅니까?자바로 복제하지 않으면 무엇을하고 무엇을 부릅니까?

제목에 따라 clone()Cloneable을 피하고 싶습니다.

+0

왜 clone() 및 Cloneable을 사용하지 않으시겠습니까? –

+0

@Thomas Owens, 여기를 참조하십시오. http://www.artima.com/intv/bloch13.html – Yishai

+0

답변으로 복사 생성자가 해결책으로 표시됩니다. 복사 생성자가 모든 사례를 올바르게 처리하지 못합니다. 예를 들어 구체적인 클래스를 모르는 경우 (하지만 복제/복사/whateveryoucallit 메서드 내에서 여전히 복사 생성자를 사용할 수 있습니다). –

답변

3

필자는이를 복사 방법 또는 복사 생성자 (경우에 따라)라고 부릅니다. 그것이 정적 메서드라면, 나는 그것을 공장이라고 부릅니다.

무엇을해야 할 지에 관해서는, 가장 유연하고 긴 생활 옵션은 복사 생성자입니다. 하위 클래스는 부모와 마찬가지로 자신을 복사 할 수 있습니다. 당신이 Cloneable을 구현, 당신은 몇 가지 옵션을 가지고 그것을

Thing copy = new Thing(copy from me); 
2

그때 생성자

... 
public Thing(Thing copyFrom) 
{ 
    attr1 = copyFrom.attr1; 
    attr2 = copyFrom.attr2; 
    //etc... 
} 

을 할 거라고 복사 작업의 내용을 설명하는 이름을 가진 메소드 (정적 또는 인스턴스)를 사용하는 것입니다. 즉, 복사가 깊거나 얕은 복사입니다.

0

를 복제 복사 생성자하지만 내 선호하는 방법을 추가 할 때

15

Effective Java recom 수선 다음 중 하나 (다른 사람에 의해 언급 된 바와 같이)

  1. 복사 생성자 :

    공개 항목 (항목 항목)

  2. 사본 공장 방법 :

    공공 정적 항목 newInstance (항목 항목)

(또한 무 변위 자용 복사 없음)

가장 큰 차이점은 # 1을 사용하면 결과의 실제 클래스를 선택하고 # 2를 사용하면 구현자가 하위 클래스를 반환 할 수 있다는 것입니다. 클래스의 의미는 어느 것이 가장 적합한지를 안내 할 수 있습니다.

0

immutable data structures을 사용하십시오. clone()이 필요하다고 생각하는 유일한 이유는 개체를 제자리에 돌연변이시키고 있다는 것입니다. 그만해. 가능한 방법에 대해 생각해보십시오.

  • 수업을 최우선으로 생각하십시오.
  • 클래스의 필드를 최종적으로 비공개로 설정합니다.

    public Vector3D setX(double x) { 
        return new Vector3D(x, this.y, this.z); 
    } 
    

    그래서 내가 무슨 말인지 추측 내가 대신 돌연변이의 복사 생성자를 사용하고, 나는 ...입니다 :

예를 들어, 다음은 불변의 3D 벡터 개체에 대한 "세터"입니다 수정할 속성에 따라 이름을 지정하면됩니다. 당신은 다음과 같은 코드의 조각으로 복사를 구현하는 것이

interface Has3DCoords { 
    void setLocation(double x, double y, double z); 

    void copyCoordsTo(Has3DCoords dest); 
} 

:

0

또 다른 옵션은 소스 객체의 복사 방법, 예를 구현하는 것입니다

class Thing implements Has3DCoords { 
    private Point3D loc; 
    // ... 

    void setLocation(double x, double y, double z) { 
     loc.setLocation(x, y, z); 
     // or: loc = new Point3D(x, y, z); 
    } 

    void copyCoordsTo(Has3DCoords dest) { 
     loc.copyCoordsTo(dest); 
     // or: dest.setLocation(loc.getX(), loc.getY(), loc.getZ()); 
    } 

    OtherThing createOtherThing() { 
     OtherThing result = new OtherThing(); 
     this.copyCoordsTo(result); 
     return result; 
    } 
} 

를이 될 수 있습니다 유용 할 경우 :

  • 전체 개체를 복제하는 것이 적절하지 않습니다. 너무 자주 하나 개의 단위로 복사됩니다 관련 속성 그룹이 있습니다
  • 당신은 Thing
  • 속성의 수는 큰의 속성으로 loc을 노출하고 싶지 않은 (또는 많은 그런 그룹이 있습니다) 모든 매개 변수를 매개 변수로 요구하는 생성자는 다루기 힘들 수 있습니다.
0

이 개체를 복사하는 가장 좋은 방법은 아니지만 당신이 직렬화 객체의 딥 카피을 수행하고자하는 경우 다음과 같은 때로는 유용합니다. 이렇게하면 복사 구성자를 작성하거나 Cloneable을 구현하거나 팩토리 클래스를 작성하지 않아도됩니다.

ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
ObjectOutputStream oos = new ObjectOutputStream(bos); 

//Serializes the input object 
oos.writeObject(input); 

ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray()); 
ObjectInputStream ois = new ObjectInputStream(bais); 

//Copy of the input object 
Object output = ois.readObject(); 

예외를 처리하고 스트림을 멋지게 닫는 것을 잊지 마십시오.

관련 문제