Title: 아이템 89. 인스턴스 수를 통제해야 한다면 readResolve보다는 열거 타입을 사용하라 - Fin · Issue #210 · Study-2-Effective-Java/Effective-Java · GitHub
Open Graph Title: 아이템 89. 인스턴스 수를 통제해야 한다면 readResolve보다는 열거 타입을 사용하라 - Fin · Issue #210 · Study-2-Effective-Java/Effective-Java
X Title: 아이템 89. 인스턴스 수를 통제해야 한다면 readResolve보다는 열거 타입을 사용하라 - Fin · Issue #210 · Study-2-Effective-Java/Effective-Java
Description: Discussed in https://github.com/orgs/Study-2-Effective-Java/discussions/204 Originally posted by bunsung92 April 10, 2023 0. TL;DR 📚 불변식을 지키기 위해 인스턴스를 통제한다면, 열거 타입을 이용하자. 직렬화와 인스턴스 통제가 모두 필요하면 readResolve() 작성하고, 클래스의 모든 참조 타입 인스턴스 필드를 t...
Open Graph Description: Discussed in https://github.com/orgs/Study-2-Effective-Java/discussions/204 Originally posted by bunsung92 April 10, 2023 0. TL;DR 📚 불변식을 지키기 위해 인스턴스를 통제한다면, 열거 타입을 이용하자. 직렬화와 인스턴스 통제가 모두 필요하면 read...
X Description: Discussed in https://github.com/orgs/Study-2-Effective-Java/discussions/204 Originally posted by bunsung92 April 10, 2023 0. TL;DR 📚 불변식을 지키기 위해 인스턴스를 통제한다면, 열거 타입을 이용하자. 직렬화와 인스턴스 통제가 모두 필요하면 read...
Opengraph URL: https://github.com/Study-2-Effective-Java/Effective-Java/issues/210
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"아이템 89. 인스턴스 수를 통제해야 한다면 readResolve보다는 열거 타입을 사용하라 - Fin","articleBody":"### Discussed in https://github.com/orgs/Study-2-Effective-Java/discussions/204\r\n\r\n\u003cdiv type='discussions-op-text'\u003e\r\n\r\n\u003csup\u003eOriginally posted by **bunsung92** April 10, 2023\u003c/sup\u003e\r\n# 0. TL;DR 📚\r\n\r\n- 불변식을 지키기 위해 인스턴스를 통제한다면, 열거 타입을 이용하자.\r\n- 직렬화와 인스턴스 통제가 모두 필요하면 `readResolve()` 작성하고, 클래스의 모든 참조 타입 인스턴스 필드를 `transient` 키워드를 이용하자.\r\n\r\n---\r\n\r\n# 1. 인스턴스 수의 통제\r\n\r\n인스턴스 수를 통제하는 기법은 바로 `싱글턴`이다.\r\n그리고 `직렬화`와 `싱글턴`은 상성이 맞지 않다.\r\n\r\n바로 `implement Serializable` 을 추가하는 순간 싱글턴이 아니게 되기 때문이다.\r\n기본 직렬화를 쓰지 않더라도 (아이템 87) \r\n명시적인 `readObject()` (아이템88) 를 제공하더라도 소용없다.\r\n\r\n어떤 `readObject()`를 사용하든 이 클래스가 초기화될 때 만들어진 인스턴스와는 별개의 인스턴스를 반환하기 때문이다.\r\n\r\n\r\n\r\n---\r\n\r\n# 2. readResolve()\r\n\r\n`readObject()` 가 별개의 인스턴스를 반환하기만을 마냥 기다릴 수 없다.\r\n`readResolve()`를 가용하여 필연적으로 원본의 Instance를 반환하게 지시할 수 있다.\r\n\r\n``` java\r\npublic class Foo {\r\n\tprivate static final Foo INSTANCE = new Foo();\r\n\r\n\tprivate Foo() {\r\n\t}\r\n\r\n\tpublic static Foo getINSTANCE() {\r\n\t\treturn INSTANCE;\r\n\t}\r\n\r\n // readResolve 메서드를 정의한다.\r\n\tprivate Object readResolve() {\r\n // 싱글턴을 보장하기 위함!\r\n\t\treturn INSTANCE;\r\n\t}\r\n}\r\n```\r\n\r\n이때 만약에 싱글턴 클래스의 필드가 존재한다면, 해당 필드는 반드시 모두다 `transient` 키워드를 추가해야한다.\r\n`readResolve()`가 수행되기전에 역 직렬화된 객체의 참조를 공격할 여지가 남는다.\r\n\r\n## 2.1 deep To `readResolve()`\r\n\r\n- readObject()는 ObjectInputStream클래스 의 기존 메서드임.\r\n- 역직렬화 readObject()메서드는 역직렬화 중인 개체에 readResolve()메서드가 구현되어 있는지 여부를 내부적으로 확인함. \r\n- 메소드가 존재 하면 readResolve()호출됨.\r\n\r\n\u003e 즉 구현 여부를 판단하여 `readResolve()` 를 호출하기 전에 어떤 동작을 해버리면 막기 어려워진단 말임!\r\n\r\n[readResolve()와 도둑 클래스](https://donghyeon.dev/%EC%9D%B4%ED%8E%99%ED%8B%B0%EB%B8%8C%EC%9E%90%EB%B0%94/2021/11/12/%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EC%88%98%EB%A5%BC-%ED%86%B5%EC%A0%9C%ED%95%B4%EC%95%BC-%ED%95%9C%EB%8B%A4%EB%A9%B4-readResolve-%EB%B3%B4%EB%8B%A4%EB%8A%94-%EC%97%B4%EA%B1%B0-%ED%83%80%EC%9E%85%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EC%9E%90/)\r\n\r\n---\r\n\r\n# 3. 싱글턴과 열거 타입\r\n\r\n- 직렬화 가능한 인스턴스 통제 클래스를 열거 타입을 이용해 구현하면, 선언한 상수 외의 다른 객체가 존재하지 않는다는것을 `자바`가 보증한다.\r\n - 하지만 `native 코드`까지 조작한다면 이는 완전하지 않을 수 있다.\r\n\r\n- readResolve()는 완전히 쓸모 없어진것이 아니다. \r\n - 직렬화 가능 인스턴스 통제 클래스를 작성해야 하는데, 컴파일에는 어떤 인스턴스들이 있는지 알 수 없는 상황이라면, 열거타입으로 표현하는 것이 불가능하기 때문이다.\r\n\r\n## 3.1 readResolve()와 접근제어자\r\n\r\n- final Class 에서는 readResolve()는 private으로 선언해야한다.\r\n- final Class가 아닌 경우에는 package-private, protected, public으로 해당 메서드를 정의 할 수 있는데 이때 주의 할 점이있다.\r\n\r\n\u003e 하위 클래스에서 readResolve()를 재정의 하지 않고 형 변환을 통해 해당 직렬화를 이용 했다면, `ClassCastException` 이 발생한다.\r\n\r\n정리하자면 반드시 하위 클래스에서는 readResolve()를 정의해야 한다는 것이다!\r\n\r\n---\r\n\r\n# 4. 핵심 정리 📚\r\n\r\n- 내가 커스텀 직렬화를 하고 있고, 싱글턴 인스턴스를 보장 해야한다면, 두가지 선택권이 있다는걸 인지하자.\r\n\r\n```\r\n1. readResolve()\r\n2. 열거타입\r\n```\r\n\r\n- 반드시 1이 좋고, 2가 좋다. 보다는 각 상황에 알맞게 사용하도록 하자.\r\n- 고려할 사항은 열거 타입이 `readResolve()`보다 적다.\r\n\r\n---\r\n\r\n# 5. 회고 🧹\r\n\r\n2023-04-23 (일)\r\n\r\n- 해당 아이템의 회고보다 마지막 회고는 시점에 대한 느낌을 남기고 싶다.\r\n- 마지막 아이템을 맡아 마지막 정리를 하게 되었고, 자바의 여러 재미를 알아 볼 수 있어서 좋았던 것 같다.\r\n- 언젠간 다시 이 페이지로 돌아와, 우리 7인의 노고를 다시 보게 된다면, 이 시점에 우린 이렇게 살고 있었구나 느낄 수 있는 작은 발자취가 되었다고 생각한다.\r\n\r\n---\r\n\r\n\u003e 참조 자료\r\n\u003e \u003e https://madplay.github.io/post/what-is-readresolve-method-and-writereplace-method\r\n\u003e \u003e https://stackoverflow.com/questions/1168348/java-serialization-readobject-vs-readresolve\r\n\u003e \u003e https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%A7%81%EB%A0%AC%ED%99%94Serializable-%EC%99%84%EB%B2%BD-%EB%A7%88%EC%8A%A4%ED%84%B0%ED%95%98%EA%B8%B0\u003c/div\u003e","author":{"url":"https://github.com/Irisation23","@type":"Person","name":"Irisation23"},"datePublished":"2023-04-23T07:13:28.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},"url":"https://github.com/210/Effective-Java/issues/210"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:060546a9-912e-5fe7-8e4f-a63df167bb2c |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 868A:FB3CA:8C1C97:C11F47:696E63FE |
| html-safe-nonce | ae7b607b88976c168452c09559fa53a67fa73ba6b44d951218a4b53e377ff574 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4NjhBOkZCM0NBOjhDMUM5NzpDMTFGNDc6Njk2RTYzRkUiLCJ2aXNpdG9yX2lkIjoiMTcyMTcyMDI0MzE4MTQ3ODkxMCIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | edaf31e8c5af7835f08503ad3f031f75f1d4e839f2d24da8fc6a38cd3aa53c9a |
| hovercard-subject-tag | issue:1679896999 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/Study-2-Effective-Java/Effective-Java/210/issue_layout |
| twitter:image | https://opengraph.githubassets.com/77b72737240310d68b3bdb2d935b9677651abb8c8660e011ab8a849b83af35fa/Study-2-Effective-Java/Effective-Java/issues/210 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/77b72737240310d68b3bdb2d935b9677651abb8c8660e011ab8a849b83af35fa/Study-2-Effective-Java/Effective-Java/issues/210 |
| og:image:alt | Discussed in https://github.com/orgs/Study-2-Effective-Java/discussions/204 Originally posted by bunsung92 April 10, 2023 0. TL;DR 📚 불변식을 지키기 위해 인스턴스를 통제한다면, 열거 타입을 이용하자. 직렬화와 인스턴스 통제가 모두 필요하면 read... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | Irisation23 |
| hostname | github.com |
| expected-hostname | github.com |
| None | 99a4a74f92e7618f6e15b4dbb9f4470c8d31701a90d89c21ff31970528b7f0c3 |
| turbo-cache-control | no-preview |
| go-import | github.com/Study-2-Effective-Java/Effective-Java git https://github.com/Study-2-Effective-Java/Effective-Java.git |
| octolytics-dimension-user_id | 120388640 |
| octolytics-dimension-user_login | Study-2-Effective-Java |
| octolytics-dimension-repository_id | 577325341 |
| octolytics-dimension-repository_nwo | Study-2-Effective-Java/Effective-Java |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 577325341 |
| octolytics-dimension-repository_network_root_nwo | Study-2-Effective-Java/Effective-Java |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | ef0d97829e997c64864f25a29b00067f5dc3a4c4 |
| ui-target | canary-2 |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width