[java] 단순한 1L 대신 긴 serialVersionUID를 생성하는 이유는 무엇입니까?

클래스가 Eclipse에서 Serializable을 구현할 때 add default serialVersionUID(1L)또는 generated 옵션이 있습니다 serialVersionUID(3567653491060394677L). 나는 첫 번째 것이 더 시원하다고 생각하지만, 두 번째 옵션을 사용하는 사람들을 여러 번 보았습니다. 생성 할 이유가 long serialVersionUID있습니까?



답변

내가 알 수있는 한, 그것은 이전 릴리스와의 호환성을위한 것입니다. 이전에 serialVersionUID 사용을 무시한 다음 호환 가능 해야 하지만 직렬화가 중단 되도록 변경 한 경우에만 유용합니다 .

자세한 내용은 Java Serialization Spec 을 참조하십시오.


답변

직렬화 버전 UID의 목적은 객체의 유효한 직렬화를 수행하기 위해 클래스의 다른 버전을 추적하는 것입니다.

아이디어는 클래스의 특정 버전에 고유 한 ID를 생성하는 것이며, 이는 직렬화 된 객체의 구조에 영향을주는 새 필드와 같이 클래스에 추가 된 새로운 세부 사항이있을 때 변경됩니다.

1L미래에 클래스 정의가 변경되어 직렬화 된 객체의 구조가 변경되면 객체를 직렬화 해제하려고 할 때 문제가 발생할 가능성이 있음 을 의미하는 것과 같은 항상 동일한 ID를 사용하십시오 .

ID가 생략되면 Java는 실제로 객체의 필드를 기반으로 ID를 계산하지만 비싼 프로세스이므로 수동으로 제공하면 성능이 향상됩니다.

다음은 클래스의 직렬화 및 버전 관리에 대해 설명하는 기사 링크입니다.


답변

생성 된 것의 주된 이유는 이미 사본을 보유한 기존 버전의 클래스와 호환되도록하기 위해서입니다.


답변

의 “long”기본값은 기본 직렬화 동작에서 계산 된 Java Serialization Specification에serialVersionUID 정의 된 기본값입니다.

따라서 기본 버전 번호를 추가하면 구조적으로 변경된 것이없는 한 클래스의 직렬화가 더 디 직렬화되지만 클래스를 변경하면 (필드 추가 / 제거) 클래스를 업데이트해야합니다. 일련 번호.

기존 비트 스트림과 호환되지 않아도되는 1L경우 변경 사항이있을 때 필요에 따라 버전을 추가하고 버전을 늘릴 수 있습니다. 즉, 변경된 클래스의 기본 직렬화 버전이 이전 클래스의 기본 버전과 다른 경우입니다.


답변

구현하는 클래스를 정의 할 때마다 반드시 serialVersionUID를 작성해야합니다 java.io.Serializable. 그렇지 않으면 자동으로 생성되지만 이것은 나쁘다. 자동 생성 된 serialVersionUID는 클래스의 메서드 서명을 기반으로하므로 나중에 클래스를 변경하여 메서드를 추가하면 (예 🙂 “이전”버전의 클래스를 직렬화 해제하는 데 실패합니다. 일어날 수있는 일은 다음과 같습니다.

  1. serialVersionUID를 정의하지 않고 클래스의 첫 번째 버전을 만듭니다.
  2. 클래스의 인스턴스를 영구 저장소로 직렬화하십시오. serialVersionUID가 자동으로 생성됩니다.
  3. 클래스를 수정하여 새 메소드를 추가하고 애플리케이션을 재배치하십시오.
  4. 2 단계에서 직렬화 된 인스턴스를 직렬화 해제하려고 시도했지만 자동 생성 된 serialVersionUID가 다르기 때문에 이제는 실패합니다 (성공해야 할 경우).

답변

serialVersionUID를 지정하지 않으면 Java가 즉시 작성합니다. 생성 된 serialVersionUID는 해당 번호입니다. 클래스에서 이전의 직렬화 된 버전과 호환되지 않지만 해시를 변경하는 것을 변경하는 경우 생성 된 매우 큰 serialVersionUID (또는 오류 메시지의 “예상”번호)를 사용해야합니다 . 그렇지 않으면 모든 것을 스스로 추적하는 경우 0, 1, 2 …가 더 좋습니다.


답변

serialVersionUID (3567653491060394677L)를 생성하는 대신 serialVersionUID (1L)를 사용하면 무언가를 말하는 것입니다.

이 클래스의 버전 번호 1과 호환되지 않는이 클래스의 직렬화 된 버전을 가진이 클래스를 다루지 않는 시스템이 없다고 100 % 확신한다고합니다.

직렬화 된 버전 기록이 알려지지 않았다는 변명을 생각할 수 있다면 자신감을 가지고 말하기가 어려울 수 있습니다. 평생 동안 성공적인 수업은 많은 사람들에 의해 유지되고 많은 프로젝트에 살고 많은 시스템에 상주 할 것입니다.

당신은 그것을 고민 할 수 있습니다. 또는 당신은 잃고 싶어 복권을 재생할 수 있습니다. 버전을 생성하면 문제가 발생할 가능성이 거의 없습니다. “아직 아무도 1을 사용하지 않았다”고 가정하면 확률은 작은 것보다 큽니다. 우리 모두가 0과 1이 멋지다고 생각하기 때문입니다.

serialVersionUID (1L)를 사용하지 않고 serialVersionUID (3567653491060394677L)를 생성하면 무언가를 말하는 것입니다.

사람들 이이 클래스의 역사에서 다른 버전 번호를 수동으로 만들거나 생성했을 수 있으며 Longs가 큰 숫자이기 때문에 걱정하지 않아도됩니다.

어떤 방식 으로든 클래스가 존재하거나 존재하는 전체 유니버스에서 클래스를 직렬화 할 때 사용 된 버전 번호 기록을 완벽하게 알지 못하면 기회가 생깁니다. 1이 AOK인지 100 % 확신 할 시간이 있다면 그것을 찾으십시오. 그것이 많은 일이라면, 계속해서 맹목적으로 숫자를 생성하십시오. 복권 당첨 가능성이 더 높습니다. 그렇다면, 알려주세요. 맥주를 사겠습니다.

추첨에 대한이 모든 이야기를 통해 serialVersionUID가 무작위로 생성된다는 인상을 받았을 것입니다. 실제로 숫자 범위가 Long의 가능한 모든 값에 균등하게 분배되는 한 괜찮습니다. 그러나 실제로는 다음과 같이 수행됩니다.

http://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100

당신이 얻는 유일한 차이점은 무작위 소스가 필요 없다는 것입니다. 클래스 자체의 변경 사항을 사용하여 결과를 변경하고 있습니다. 그러나 비둘기 구멍 원리에 따르면 여전히 잘못되어 충돌을 일으킬 가능성이 있습니다. 정말 믿을 수 없을 것입니다. 나 한테 맥주를 가져다 줘서 행운을 빌어

그러나 클래스가 하나의 시스템과 하나의 코드베이스에만 살더라도 손으로 숫자를 늘리면 충돌 가능성이 전혀 없다고 생각하면 인간을 이해하지 못한다는 것을 의미합니다. 🙂