Cloneable이 더 이상 사용되지 않는 이유는 무엇입니까?


139

CloneableJava의 인터페이스가 손상 되었다는 것이 일반적으로 이해 됩니다. 여기에는 여러 가지 이유가 있지만 언급하지 않겠습니다. 다른 사람들은 이미 그것을했습니다. 또한 Java 설계자 자신 의 위치이기도합니다 .

따라서 내 질문은 : 왜 아직 폐기되지 않았습니까? 핵심 Java 팀이 중단되었다고 판단한 경우 사용 중단을 고려해야합니다. 그렇게 하지 않은 이유는 무엇입니까 (Java 8에서는 더 이상 사용되지 않습니다 )?


41
많은 사람들이 판단 할 권리가있는 것처럼,이 질문은 "주로 의견 기반"이 아닙니다. 이유에 대한 의견을 가진 사람은 대답 할 자격이 없습니다. 그러나 여기에서 정식 답변을 얻을 수있는 원격 기회 만 있다는 것은 사실입니다. 귀하의 질문이 해결 가능한 문제에 관한 것이 아니기 때문에 적어도 주제의 경계를 벗어난 것입니다.
Marko Topolnik

6
@MarkoTopolnik 저는 전세계에 권위있는 답변을 제공 할 수있는 사람들이 있다는 데 동의하지만, 이것이 우리가 적용하는 테스트라고는 믿지 않습니다. 폐쇄 이유는 "이 질문에 대한 답변 거의 전적으로 의견에 근거 하는 경향 이있다"고 명시 하고 있습니다. 우리가 운이 좋지 않다면 이것이 사실 일 것입니다.
Duncan Jones

2
다음은 "언제 어떻게 ..."(Oracle에서 더 이상 사용하는 docs.oracle.com/javase/6/docs/technotes/guides/javadoc/... ) Cloneable을 인터페이스는 가을 "버그, 또는 매우 비효율적"수도의 경우 만 의견에 매우 개방적입니다.
Maxx

8
@Duncan 나는 아직도 응답자 부분 의 징계 부족에 대한 나의 가정에 근거 하여 질문 에 대한 판단을 통과하는 것이 공정하다고 생각하지 않습니다 . 사용자가 질문 한 이유를 모르는 경우, 응답 시설을 남용하여 해당 문제에 대한 의견을 제시 할 권한이 없습니다.
Marko Topolnik

4
@lexicore 그렇습니다 .-- 그리고 당신은 그들이 그 옵션을 철저히 고려했으며 내포 하여 그것을 사용하지 않을 강력한 이유 가 있어야 합니다. 그들 자신의 비판 Cloneable은 널리 알려져 있습니다.
Marko Topolnik 8

답변:


120

버그 로 1997 년에 제출 된 자바 버그 데이터베이스에 추가하는 방법에 대한 clone()메서드에 Cloneable더 이상 쓸모가 없을 것이다, 그래서는. 그것은 "수정하지 않을 것"이라는 결의안으로 마감되었으며 정당화는 다음과 같습니다.

Sun의 TRC (Technical Review Committee)는이 문제를 오랫동안 고려 하여 현재 Cloneable 인터페이스의 문서를 개선하는 것 이외의 조치 를 취하지 않는 것이 좋습니다 . 권장 사항은 다음과 같습니다.

기존 Java 객체 복제 API에 문제가 있습니다. java.lang.Object에 보호 된 "복제"메소드가 있으며 인터페이스 java.lang.Cloneable이 있습니다. 다른 사람들이 클래스를 복제 할 수있게하려면 클래스가 Cloneable 인터페이스를 지원하고 공용 복제 방법으로 기본 보호 된 복제 방법을 재정의해야합니다. 불행하게도, 안개 속에서 편리하게 잃어버린 이유로 Cloneable 인터페이스는 복제 방법을 정의하지 않습니다.

이 조합은 상당한 양의 혼란을 초래합니다. 일부 클래스는 Cloneable을 지원한다고 주장하지만 실수로 clone 메소드를 지원하는 것을 잊어 버립니다. 개발자는 Cloneable의 작동 방식과 클론의 작동 방식에 대해 혼란스러워합니다.

불행하게도, "복제"방법을 Cloneable에 추가하는 것은 호환되지 않는 변경이 될 것입니다. 이진 호환성을 깨뜨리지는 않지만 소스 호환성을 깨뜨릴 것입니다. 일화 적 증거에 따르면 실제로 클래스가 Cloneable 인터페이스를 지원하지만 공용 클론 메소드를 제공하지 못하는 경우가 많이 있습니다. 토론 후에 TRC는 만장일치로 호환성 영향으로 인해 기존 Cloneable 인터페이스를 수정하지 말 것을 권장했습니다.

대체 제안은 원래 의도 된 Cloneable 목적을 반영하기 위해 새 인터페이스 java.lang.PubliclyCloneable을 추가하는 것이 었습니다. TRC는 5 ~ 2의 다수로 이에 대해 권장했습니다. 주된 관심사는 이것이 이미 혼란 스러워진 그림에 더 많은 혼동 (맞춤법 혼동 포함)을 추가 할 것이라는 점이었습니다.

TRC는 만장일치로 기존 Cloneable 인터페이스추가 문서를 추가하여 사용 방법을보다 잘 설명하고 구현자를위한 "모범 사례"를 설명 할 것을 권장했습니다.

따라서 이것은 사용 중단 에 대한 직접적인 내용은 아니지만 Cloneable을 "사용 중단"하지 않는 이유는 Technical Review Comitee가 기존 문서수정하는 것이이 인터페이스를 유용하게 만들기에 충분하다고 판단했기 때문 입니다. 그리고 그들은 그렇게했습니다. Java 1.4까지는 Cloneable다음과 같이 문서화되었습니다.

클래스는 Cloneable 인터페이스를 구현하여 Object.clone () 메소드에 해당 메소드가 해당 클래스의 인스턴스에 대한 필드 필드 사본을 작성하는 것이 합법적임을 표시합니다.

Cloneable 인터페이스를 구현하지 않은 인스턴스를 복제하려고하면 예외 CloneNotSupportedException이 발생합니다.

Cloneable 인터페이스는 메소드를 선언하지 않습니다.

2002 년 2 월에 릴리스 된 Java 1.4 (현재 버전) (Java 8)부터 다음과 같습니다.

클래스는 Cloneable 인터페이스를 구현하여 Object.clone () 메소드에 해당 메소드가 해당 클래스의 인스턴스에 대한 필드 필드 사본을 작성하는 것이 합법적임을 표시합니다. Cloneable 인터페이스를 구현하지 않는 인스턴스에서 Object의 clone 메소드를 호출하면 CloneNotSupportedException 예외가 발생합니다.

일반적으로이 인터페이스를 구현하는 클래스는 공용 메소드로 Object.clone (보호 된)을 대체해야합니다. 이 메서드를 재정의하는 방법에 대한 자세한 내용은 Object.clone ()을 참조하십시오.

이 인터페이스에는 clone 메소드가 포함되어 있지 않습니다. 따라서이 인터페이스를 구현한다는 사실만으로 개체를 복제 할 수 없습니다. clone 메소드가 반사적으로 호출 되더라도 성공할 것이라는 보장은 없습니다.


3
왜 그 clone방법이 Object처음 에 왔는지 아십니까 ?
njzk2

8
@ njzk2 메커니즘의 필수 부분입니다. 객체 이미지를 비트 단위로 복사하는 저수준의 비언어적 마법을 수행하는 방법입니다.
Marko Topolnik

3
@Unheilig이 마술은 복사 생성자로 복제 할 수없는 것 Object#clone()입니다. 컴파일 타임에 해당 클래스를 알지 못하면 원본과 동일한 클래스의 인스턴스를 생성합니다.
Marko Topolnik

4
@AVolpe : "클래스가 Cloneable 인터페이스를 지원하지만 공용 클론 메소드를 제공하지 못하는 경우"라는 대답에 언급 된 소스 비 호환성을 수정하지는 않습니다. 특히, 비공개 복제 방법을 제공하는 클래스가 손상 될 수 있습니다.
Louis Wasserman

2
좋은 역사. 다음 은 버그 데이터베이스에 대한 직접 링크 입니다. 나는 거기에 더 많은 역사를 추가했고, 내 대답 에 그 일부를 인용했다 .
스튜어트 마크

64

"왜 Cloneable더 이상 사용되지 않습니까?"에 대한 짧은 대답 (또는 실제로 X더 이상 사용 되지 않는 이유는) 더 이상 사용되지 X않도록주의를 기울이지 않았다는 것입니다.

더 이상 사용되지 않는 대부분의 항목은 제거 할 특정 계획이 있으므로 더 이상 사용되지 않습니다. 예를 들어, Java SE 9에서는 LogManager의 메소드 addPropertyChangeListenerremovePropertyChangeListener메소드가 Java SE 8 에서 제거 되기 위해 더 이상 사용되지 않습니다. 그 이유는 모듈 상호 종속성이 불필요하게 복잡하기 때문입니다. 실제로 이러한 API는 JDK 9 초기 개발 에서 이미 제거 되었습니다. 빌드합니다. (유사한 속성 변경 리스너 호출도 제거되었습니다 ( JDK-8029806 참조 ).Pack200

그런 유사한 계획에 대한에 존재하지 않는 CloneableObject.clone().

더 긴 답변에는 이러한 API에 발생할 것으로 예상되는 사항, 더 이상 사용되지 않는 플랫폼에 어떤 비용 또는 이점이 발생하는지, API가 더 이상 사용되지 않을 때 개발자에게 전달되는 내용과 같은 추가 질문에 대해 논의해야합니다. 최근 JavaOne 토론 Debt and Deprecation 에서이 주제를 살펴 보았습니다 . (이 링크에서 제공되는 슬라이드; 여기 비디오 ) JDK 자체는 사용 중단에있어 일관성이없는 것으로 나타났습니다. 예를 들어 다음과 같은 여러 가지 다른 의미로 사용되었습니다.

  • 이것은 위험하며 당신은 그것을 사용의 위험을 알고 있어야합니다 (예를 Thread.stop(), Thread.resume()Thread.suspend()).

  • 향후 릴리스에서 제거 될 예정입니다.

  • 이것은 더 이상 사용되지 않으며 다른 것을 사용하는 것이 좋습니다 (예 :의 많은 메소드 java.util.Date)

이 모든 것들은 별개의 의미이며, 다른 부분 집합은 더 이상 사용되지 않는 다른 것에 적용됩니다. 그리고 그들 중 일부는 더 이상 사용되지 않는 것들에 적용됩니다 (그러나 더 이상 사용되지 않아야 할 수도 있습니다).

Cloneable그리고 Object.clone()그들이 설계 결함을 가지고 올바르게 사용하기 불편하다는 의미에서 "깨진"입니다. 그러나 clone()여전히 배열을 복사하는 가장 좋은 방법이며 복제에는 신중하게 구현 된 클래스 인스턴스의 복사본을 만드는 데 약간의 유용성이 있습니다. 복제를 제거하면 호환되지 않는 변경으로 인해 많은 문제가 발생합니다. 복제 작업은 다른 방식으로 다시 구현 될 수 있지만 아마도 속도가 느릴 수 있습니다 Object.clone().

그러나 대부분의 경우 복제본보다 사본 생성자가 선호됩니다. 따라서 Cloneable"사용되지 않음"또는 "대체 됨"또는 이와 유사한 것으로 표시하는 것이 적절합니다. 이것은 개발자들에게 아마도 다른 곳을보고 싶다고 말하지만, 이후 릴리스에서 복제 메커니즘이 제거 될 것이라는 신호는 아닙니다. 불행히도, 그러한 마커는 존재하지 않습니다.

상황이 잘 드러나면서, "더 이상 사용되지 않음"은 사용되지 않는 기능이 거의 사라 졌음에도 불구하고 궁극적 인 제거를 의미하는 것으로 보이므로 사용 중단이 복제 메커니즘에 대해 보증되지 않는 것 같습니다. 아마도 미래에는 개발자가 대체 메커니즘을 대신 사용하도록하는 대체 표시를 적용 할 수 있습니다.

최신 정보

버그 보고서 에 몇 가지 추가 기록을 추가했습니다 . 초기 JVM 구현 자이자 JVM 스펙의 공동 저자 인 Frank Yellin은 다른 답변 에서 인용 된 TRC 권장 사항의 "미시간에 잃어버린"주석에 대한 응답으로 일부 주석을 작성했습니다 . 여기에 관련 부분을 인용했습니다. 전체 메시지는 버그 보고서에 있습니다.

Cloneable에는 Serializable과 달리 동일한 방법이 없습니다. Cloneable은 클래스가 지원하는 메서드에 대해 구체적으로 말하지 않고 클래스의 속성을 나타냅니다.

반영하기 전에, 우리는 객체의 얕은 사본을 만들기위한 기본 방법이 필요했습니다. 따라서 Object.clone ()이 탄생했습니다. 또한 많은 클래스가이 메소드를 재정의하고 모든 클래스를 복제하려는 것은 아니라는 것이 분명했습니다. 따라서 Cloneable은 프로그래머의 의도를 나타 내기 위해 탄생했습니다.

요컨대 Cloneable의 목적은 공용 clone () 메소드가 있음을 나타 내기위한 것이 아닙니다. Object.clone ()을 사용하여 복제 할 의사가 있음을 나타 내기 위해 clone ()을 공개할지 여부를 결정하는 것은 구현에 달려 있습니다.


3
여기에 좋은 대답이 있습니다. 특히 Object.clone()다른 사람들이 원하기 때문에 불에 타지 말고 좋은 것을 추론하고 기꺼이 내놓고 싶습니다.
icza

2
그러나 clone ()은 여전히 ​​배열을 복사하는 가장 좋은 방법이며 복제에는 신중하게 구현 된 클래스 인스턴스의 복사본을 만드는 데 약간의 유용성이 있습니다. 6428387의 수정으로 인상을 받았으며 모든 코드 경로 (clone, new / arrayCopy, Arrays.copyOf)가 동일한 내장 함수를 생성했습니다. 최근에 변경된 것이 있습니까?
bestsss

2
@bestsss 나는 array.clone()다른 대안보다 빠르다고 생각하지 않습니다 . API 관점에서 배열을 복제하는 가장 간결한 방법입니다. Arrays.copyOf(array, newlen)가까워 지지만 길이 매개 변수가 필요합니다. 길이를 변경하지 않으면 중복됩니다.
스튜어트 마크

2
@Holger 네, 우리가 볼 수있는 한, 1.1 이후의 API의 실제 제거입니다. 우리가 동의 Thread.suspend()하고 Thread.stop()(비 인수) 위험하다는 데 동의하더라도 사람들은 실제로 그것들을 사용하기 때문에 제거되거나 무조건 예외를 던지도록 변경되지 않을 것입니다! 아마도 그들은 기꺼이 위험을 감수 할 것입니다. 속성 변경 리스너의 완화 요소 중 하나는 매우 드물게 사용되었으므로 제거 효과가 적다는 것입니다.
Stuart Marks

2
@Holger Bean은 속성에 대한 라이브러리 API 이므로 개념적 java.beans으로 독립적으로 만들 수 있습니다 java.desktop. 불행히도 bean API를 파헤 치면 AWT에 많은 의존성이 있습니다. 구현에는 더 많은 것이 있습니다. 확실히 그것들을 구사하는 것이 가능할 수도 있지만, 그렇게하는 것은 콩에서 로깅을 분리하는 것보다 훨씬 더 많은 일처럼 보입니다. 전체 모듈화 노력은 이러한 분리를 수행하는 것입니다. 의심 할 여지없이 더 많은 일을 할 수 있지만 퍼즐은 훨씬 더 오래 걸릴 것입니다.
스튜어트 마크

-1

왜 더 이상 사용되지 않습니까?

JCP는 그렇게하기에 적합하지 않았기 때문에 결코 그렇게하지 않을 수 있습니다. 그들에게 묻다. 당신은 잘못된 곳에서 묻고 있습니다.

Java API 에서이 일을 유지하는 이유는 무엇입니까

이전 버전과의 호환성 요구 사항으로 인해 아무도 Java API에서 아무것도 제거하지 않습니다. 마지막으로 발생한 것은 1996/7 년 1.0과 1.1 사이의 AWT 이벤트 모델 변경이었습니다.


17
그들은 Thread.stop(Throwable)항상 UnsupportedOperationException(대상 스레드가 아닌) 호출자에게 던지기 위해 계약을 변경하여 효과적으로 제거 했습니다 .
Marko Topolnik

22
같은시기에 무슨 일이 있었습니까? Thread.stop(Throwable)의 기능 제거는 Java 8에서 일어났습니다. 어쨌든, 오늘날 자바 설계자 자신이 Stack Overflow의 활발한 멤버이기 때문에 "요청"에 대한 자격이없는 조언은 잘못되었습니다. 그는 스트림 관련 질문 외에는 아무것도 대답하지 않습니다.
Marko Topolnik

13
또한 OP의 질문은 제거 가 아니라 폐기 에 관한 것이며 분명하게 폐기가 진행되고 있습니다.
Marko Topolnik

17
@ EJP CloneableJava API에서 제거 될지 묻지 않습니다 . 나는 그것이 왜 더 이상 사용되지 않을지 묻고있다. 그리고 나는 이것이 물어보기에 완벽한 장소라고 생각합니다.
Kao

5
@VaheHarutyunyan 소리 질러 주셔서 감사하지만 Java 건축가는 아닙니다. 저는 Oracle JDK 그룹의 엔지니어입니다.
스튜어트 마크
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.