2012-02-10 4 views
15

Calendar 개체의 방어 복사본을 만드는 방법을 구현하는 가장 좋은 방법을 찾으려했습니다.Calendar의 방어 복사본

예 : 널 (null) 입력을 확인하고 사본을 만들거나 내가 매우 명백한 뭔가를 놓치고 때 스레드의 인터리빙에 대해 특히 걱정

public void setDate(Calendar date) { 
    // What to do.... 
} 

?

copy = Calendar.getInstance(original.getTimeZone()); 
copy.setTime(original.getTime()); 

하지만 난 강력하게 제안 자바에서 시간과 날짜를 표현하는 JodaTime를 사용 (가능하면) 그 :

+1

복제본의 문제점은 무엇입니까? (나는 정말로 흥미 롭습니다.) – zeller

+0

좋은 점은, 객체 자체가 확장 가능하지 않다면 클론이 좋다는 것입니다. 불행히도 캘린더 (GregorianCalendar)는 그렇지만 개체가 일정 및 다른 장난 꾸러기 하위 클래스가 아니라면 복제본을 사용할 수 있습니다. 사실 내 내부 달력이 사실임을 확신하기 때문에 동일한 클래스의 getter에서 clone 메서드를 사용하고 있습니다. –

+0

나는 네가 옳다는 것을 알았다. 그러나 객체가 당신을 지원하고 싶지 않은 클래스의 것이라면 복사를 금지 할 수 있습니다. 맞습니까? – zeller

답변

22

내가 절대적으로 (대신 Joda 시간) 모두에서 Calendar을 사용했다 만약 내가 clone()을 사용합니다. 당신은 "나쁜 하위 클래스"에 대해 걱정하고 있다고 논평에서 논합니다. 스키마에서 그 문제를 해결하기 위해 어떻게 제안하겠습니까? 관련된 하위 클래스에 대해 알지 못하고 신뢰할 수 없다면 유형별 데이터를 보존 할 방법이 없습니다. 하위 클래스를 신뢰할 수 없다면 문제가 커집니다. 날짜/시간 계산을 수행 할 때 올바른 결과를 얻으려는 방법을 어떻게 신뢰할 수 있습니까?

clone() 개체를 복제의 예상 방법이다 : 나는 분별 서브 클래스가 필요한 모든 종류의 특정 행동에 후크 기대할 수있는 곳이있다. 관련성이있는 비트를 알 필요가 없습니다. 유형을 처리하도록합니다. 속성을 직접 Calendar.getInstance()를 사용하여 설정을 통해

장점 :

  • 당신은 같은 일정 유형 당신은 속성을 잊고에 대해 걱정할 필요가 없습니다
  • 을 보존합니다 : 그것은 종류의 책임
  • 명시 적으로 을 말하고 있습니다.을 수행하고 구현하면 을 처리하는 방법을 항상으로 처리하는 것이 좋습니다. 귀하의 코드는 귀하의 의도를 정확하게 표현합니다.

편집 : date 매개 변수 의 값이 다른 스레드가 무엇 이건을 변경하지 않습니다에 대한 원래의 질문 걱정이 "스레드 인터리빙"의 관점에서. 그러나 수비 사본을 가져 오는 동안 다른 스레드가 객체의 내용을 변경하면 이 매우 쉽게 문제를 일으킬 수 있습니다. 이것이 위험하다면 기본적으로 더 큰 문제가 발생합니다.

15

간단한 방법이 될 것입니다. 그것은 변경할 수있는 클래스뿐만 아니라 변경할 수 있습니다. (지금은 약간 다른 청중을 대상으로, 제 생각 엔 ...)

+2

나는 이것이 달력이 동일하게 될 것이라고 확신하지 않는다고 생각합니다. – zeller

+0

그래,이게 어디로 가고 싶은지, 널 값을 검사 할 때 동시 스레드 사이의 인터리빙에 대해 걱정하고 결과적으로 원본의 타임 스탬프에 복사본을 설정하면 이것이 문제가된다고 생각한다. 그래, 나는 JodaTime에 관해 매우 좋은 것을 들었다. 나는 그것에 대해 아무런 경험이 없다는 것을 인정해야한다. :) 한번보세요. –

+2

@zeller 시간대가 맞습니다. 예를 편집했습니다. –

1

Calendar 객체를 ThreadLocal로 랩핑하면됩니다. 이것에 의해, Calendar의 각 인스턴스는 1 개의 thread만이 사용되는 것을 보증합니다. 다음과 같은 내용 :

public class ThreadLocalCalendar 
{ 
    private final static ThreadLocal <Calendar> CALENDAR = 
     new ThreadLocal <Calendar>() 
     { 
      @Override 
      protected Calendar initialValue() 
      { 
       GregorianCalendar calendar = new GregorianCalendar(); 

       // Configure calendar here. Set time zone etc. 

       return calendar; 
      } 
     }; 

    // Called from multiple threads in parallel 
    public void foo() 
    { 
     Calendar calendar = CALENDAR.get(); 

     calendar.setTime (new Date()); 
     // Use calendar here safely, because it belongs to current thread 
    } 
} 
0

이것은 보장 할 수 없습니다.

스레드 안전성 : 참조를 얻은 곳에서 당사자가 구현 한 안전 계획에 대해 알고 있지 않으면 보장 할 수 없습니다. 그 당사자는 새로운 참조를 제공 할 수 있었고 그 경우 참조를 그대로 사용할 수 있습니다. 그 당사자는 그 Calendar 레퍼런스에 관해서 안전성 스킴을 공개 할 수 있습니다.이 경우, null가 아닌 참조를 확인해, getInstance()를 사용해 방어 적으로 카피하도록 (듯이) 같은 schema를 따를 수가 있습니다. . 이것들을 모른 채 스레드 안전성을 보장하는 것은 불가능하다고 생각합니다.

방어 달력 복사 : 참조를 가져온 곳을 신뢰할 수 없다면 복제가 옵션이 아닙니다! Calendar는 기존의 Calender 객체를 사용하고 새 객체를 만드는 생성자를 지원하지 않습니다!

요약하면 문제를 해결할 방법이 없습니다. JodaTime이 최선의 방법입니다.

-2

여기에 "동기화 된 블록"의 사용을 제안합니다.

+0

동기화는 방어 복사본을 가져 오는 것에 대해 아무 것도하지 않습니다. –

2

나는 이것이 오래되었다는 것을 알고 있지만 나는 나의 두 센트를 넣을 것이라고 생각했다.

계약으로 프로그램을 작성하면 개체가 다른 개체의 실수에 대해 책임지지 않습니다. Calendar는 Cloneable을 구현합니다. 즉, 하위 클래스도 마찬가지입니다. Calendar의 서브 클래스가 Cloneable 규약을 파기하는 경우는, clone를 호출하는 클래스는 아니고, 그것을 고쳐야 할 서브 클래스입니다.

객체 지향 프로그래밍에서 객체는 객체가 포함 된 클래스 &에만 관심을 가져야합니다. "하위 클래스가 문제를 일으키는 경우 어떻게해야합니까?"라는 질문을하면 요인에 따라 디자인이 크게 복잡해집니다. 객체가 매개 변수로 객체를 가져올 때마다 항상 그 객체가 하위 클래스이고 모든 것을 망칠 기회가 있습니다. getX()를 호출 할 때 방어 적으로 프로그래밍합니까? 서브 클래스에 대해 ArithmeticException 예외가 발생하지 않습니까?

Jon Skeet도 내 대답보다 훌륭한 답변을 주었지만이 질문에 대한 잠재적 인 방해물은 '계약서 디자인'의 작은 비트를 듣는 것으로부터 이익을 얻을 수 있다고 생각했습니다. 이 접근법은 거의 죽어 가고 있지만,이 방법론은 내 설계를 조용하게하는 데 도움이되었습니다.

0

아래 내용은 무엇입니까?

public synchronized void setDate(Calendar date) { 
    // What to do.... 
    Calendar anotherCalendar = Calendar.getInstance(); 
    anotherCalendar.setTimeInMillis(date.getTimeInMillis()); 
} 

동기화 코드의 올바른 사용법은 사용 사례에 따라 다릅니다.

+0

또한 작동 할 수 있습니다, 나는 불변의 타입으로 완벽한 세계에서 클론 응답을 선호합니다 - 클론 제가 추측 할 수있는 길일 것입니다,하지만 당신의 대답은 유효한 시도입니다. –