Skip to content

260630_07_문재원#98

Open
Clair93 wants to merge 1 commit into
SurvivalCodingCampus:student/07_문재원from
Clair93:master
Open

260630_07_문재원#98
Clair93 wants to merge 1 commit into
SurvivalCodingCampus:student/07_문재원from
Clair93:master

Conversation

@Clair93

@Clair93 Clair93 commented Jun 30, 2026

Copy link
Copy Markdown

260630_07_문재원

📝 과제 정보

  1. Book 클래스를 만들고 제목과 출간일이 같으면 같은 책으로 판단.
  2. List, Map, Set 등의 컬렉션에 넣어도 동일 객체로 판단.
  3. 출간일이 신상 순서대로 정렬
  4. clone() 메서드를 제공하고 깊은 복사 수행
  • 교육 주제:

📋 체크리스트

  • 코드 컨벤션 준수 (Formatter 적용)
  • 모든 테스트 케이스 통과 (JUnit)

📷 실행 결과 (또는 테스트 결과)

2026-06-30-Book

❓질문 및 어려웠던 점

🔄 자체 평가 & 회고

  • 클래스의 기초로 생성자, getter, setter, equals, hashCode, toString 으로 기본 셋팅 해주는게 좋다.

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

이번 변경에서는 Book의 기본 인스턴스 동작을 정리하고 구현했습니다.

  • Book 클래스를 추가해 제목, 출판일, 코멘트 정보를 관리하도록 했습니다.
  • 책의 동일성 기준을 제목 + 출판일로 맞추고, equals/hashCode를 이에 맞게 구현했습니다.
  • Comparable을 구현해 출판일 기준 내림차순 정렬이 가능하도록 했습니다.
  • clone()을 추가해 복제 시 날짜 정보가 분리되도록 처리했습니다.
  • 동작 확인을 위한 JUnit 테스트를 추가해 List, Set, 정렬, 복제 동작을 검증했습니다.
  • 학습 정리 문서와 UML 다이어그램도 함께 추가했습니다.

Walkthrough

Book 클래스를 신규 추가하여 Comparable<Book>Cloneable을 구현한다. 날짜 문자열을 SimpleDateFormat으로 파싱하고, equals/hashCode/compareTo/clone을 오버라이드한다. Main.java에서 Book 인스턴스를 생성해 리스트로 출력하고, BookTest로 동등성·정렬·복제를 검증한다. PlantUML 다이어그램과 TIL 문서도 함께 추가된다.

Changes

Book 클래스 구현 및 문서화

Layer / File(s) Summary
Book 클래스 필드·생성자·핵심 메서드
post-oop/Book.puml, post-oop/src/main/java/com/survivalcoding/Book.java
BookComparable<Book>, Cloneable을 구현하는 구조를 PlantUML로 정의하고, 실제 Java 클래스로 날짜 파싱 생성자(파싱 실패 시 RuntimeException), 복사 생성자(방어 복사), getter/setter, equals/hashCode/toString/compareTo(내림차순)/clone을 구현한다.
Main 연동
post-oop/src/main/java/com/survivalcoding/Main.java
List, ArrayList import를 추가하고 main 메서드에서 Book 인스턴스 2개를 생성·출력하고 List<Book>에 담아 리스트를 출력하는 흐름을 추가한다.
BookTest - 동등성·컬렉션·정렬·clone 검증
post-oop/src/test/java/com/survivalcoding/BookTest.java
같은 제목/출간일의 Book 동등성, List 삭제, Set 중복 제거, Collections.sort 내림차순 결과, clone() 동등성을 각각 검증하는 테스트를 추가한다.
TIL 문서
TIL/sample/2026-06-30-인스턴스 기본 조작.md
Object 메서드(toString/equals/hashCode), Comparable/Comparator/람다 정렬, 얕은·깊은 복사 개념 정리와 실습 Book 코드, 학습 회고를 담은 TIL 문서를 추가한다.

예상 코드 리뷰 노력

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive 제목이 과제 ID와 작성자명만 있어 변경 내용을 파악할 수 없어, 의도가 드러나지 않습니다. 주요 변경을 드러내는 짧은 제목으로 바꾸세요. 예: Book 클래스 구현 및 복사·정렬 추가.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed 필수 섹션은 대부분 갖췄고 과제 정보, 체크리스트, 실행 결과, 회고가 포함되어 템플릿을 대체로 충족합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (3)
TIL/sample/2026-06-30-인스턴스 기본 조작.md (3)

164-173: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

compareTopublishDate 기반으로 단순화

year/month/day를 개별 비교하는 대신 publishDate.compareTo()를 활용하면 내림차순 정렬을 더 간결하게 표현할 수 있습니다.

♻️ 제안: publishDate 기반 compareTo
     `@Override`
     public int compareTo(Book o) {
-        if (this.year != o.year) {
-            return Integer.compare(this.year, o.year) * -1;
-        }
-        if (this.month != o.month) {
-            return Integer.compare(this.month, o.month) * -1;
-        }
-        return Integer.compare(this.day, o.day) * -1;
+        return o.publishDate.compareTo(this.publishDate); // 내림차순
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@TIL/sample/2026-06-30-인스턴스` 기본 조작.md around lines 164 - 173, `Book.compareTo`
is comparing `year`, `month`, and `day` manually; simplify it by delegating to
the existing `publishDate` field’s compareTo and reversing the result for
descending order. Update the `compareTo(Book o)` implementation to use
`publishDate` directly so the ordering logic stays concise and easier to
maintain while preserving the same descending date sort.

58-67: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

깊은 복사와 equals/hashCode 관계 설명 정정

Line 61의 "Equals, HashCode 는 재정의 필수로"는 문법도 어색하고, 내용도 정확하지 않습니다. 깊은 복사 자체는 equals/hashCode 재정의 없이도 동작합니다. 이들은 복사 후 컬렉션에서 동등성 비교가 올바르게 작동하도록 하기 위해 필요합니다. 문장을 명확히 다듬으세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@TIL/sample/2026-06-30-인스턴스` 기본 조작.md around lines 58 - 67, 깊은 복사 설명에서
Hero/Sword 예시 주변의 “Equals, HashCode 는 재정의 필수로” 문구를 정정하세요. 깊은 복사 자체와
equals/hashCode의 관계를 분리해서, deep copy는 객체를 새로 만들며 동작하고 equals/hashCode는 복사 후 동등성
비교나 컬렉션 사용을 위해 필요하다는 식으로 자연스럽게 문장을 다듬으세요. 해당 섹션의 깊은 복사 설명 전체를 읽기 쉽게 정리하고, 문법도 함께
바로잡으세요.

146-157: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

equals/hashCode에서 publishDate 직접 비교 권장

현재 year/month/day 필드를 개별 비교하는 대신, publishDate 객체를 직접 사용하면 코드가 간결해지고 setPublishDate() 호출 시 발생할 수 있는 불일치 위험도 줄어듭니다.

♻️ 제안: publishDate 직접 사용
     `@Override`
     public boolean equals(Object o) {
         if (o == null || getClass() != o.getClass()) return false;
         Book book = (Book) o;
-        return Objects.equals(title, book.title) &&
-                this.year == book.year && this.month == book.month && this.day == book.day;
+        return Objects.equals(title, book.title) &&
+                Objects.equals(publishDate, book.publishDate);
     }

     `@Override`
     public int hashCode() {
-        return Objects.hash(title, year, month, day);
+        return Objects.hash(title, publishDate);
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@TIL/sample/2026-06-30-인스턴스` 기본 조작.md around lines 146 - 157, `Book.equals`
and `Book.hashCode` are comparing `year`/`month`/`day` separately, which should
be replaced with direct `publishDate` comparison to keep the methods consistent
with `setPublishDate()` and reduce mismatch risk. Update the logic in
`equals(Object o)` and `hashCode()` to rely on the `publishDate` field together
with `title`, and keep the same equality semantics while removing the individual
date component checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@post-oop/src/main/java/com/survivalcoding/Book.java`:
- Around line 11-15: `Book` is keeping duplicate publish-date state in
`publishDate` and `year/month/day`, which can drift and break `equals`,
`hashCode`, `compareTo`, and `toString`. Make `publishDate` the single source of
truth inside `setPublishDate()`, `getPublishDate()`, and any date-based
comparisons, and remove or consistently derive the auxiliary fields instead of
storing them separately. Also defensively copy `Date` on input/output in the
`Book` accessors so callers cannot mutate internal state through shared
references.
- Around line 21-24: In Book’s date parsing logic, SimpleDateFormat is currently
using lenient parsing, so invalid inputs like "2024-02-31" can be silently
adjusted instead of rejected. Update the parsing path in the constructor that
handles publishDateStr to set the formatter to strict mode with
setLenient(false) before parse is called, so ParseException is thrown for
invalid dates and only valid publish dates are stored.
- Around line 98-105: `Book.compareTo()` is inconsistent with `equals()` because
it only compares the publication date, so books with the same date but different
titles can collapse to 0 in sorted collections. Update `compareTo(Book o)` to
keep the existing year/month/day ordering and then compare the title as a final
tie-breaker, so `compareTo() == 0` only when `equals()` would also be true.

In `@post-oop/src/test/java/com/survivalcoding/BookTest.java`:
- Around line 77-84: `cloneTest`는 `Book.clone()`의 deep copy를 검증하지 못하므로,
`BookTest.cloneTest`에서 `assertEquals(book1, book2)`만 두지 말고 두 객체가 같은 인스턴스가 아님을
확인하는 `assertNotSame(book1, book2)`를 추가하세요. 또한 `Book`의 mutable 필드인 `publishDate`가
있으면 `clone()` 결과가 원본과 독립적인지 함께 검증해, `clone()`이 얕은 복사가 아닌 깊은 복사임을 보장하도록 테스트를
보강하세요.

In `@TIL/sample/2026-06-30-인스턴스` 기본 조작.md:
- Around line 42-53: Fix the example code typos in the anonymous class and
lambda snippets: in the Comparator/Hero examples, replace the mistaken
`01.compareTo(o2)` in the anonymous class with the correct `o1.compareTo(o2)`
and ensure the lambda expressions under Collections.sort have balanced
parentheses, especially the `compareTo` calls in the `Hero` sorting examples.
Use the existing `Collections.sort`, `Comparator<Hero>`, and `compare`/lambda
snippets in the document to locate and correct these compile-breaking typos.
- Around line 30-41: `Collections.sort()`의 내림차순 설명이 부정확하므로, 해당 문장을 `compareTo()`
결과를 반대로 쓰거나 `Comparator.reversed()`를 사용하는 방식으로 명확히 고쳐주세요. `Collections.sort`,
`Comparable`, `Comparator`, `compareTo`, `this.name.compareTo(o.name)` 같은 기존 설명
흐름을 유지하되, “x -1”처럼 애매한 표현은 제거하고 내림차순을 만드는 정확한 방법을 예시와 함께 자연스럽게 정리하세요.
- Around line 17-23: 학습 노트의 equals()/hashCode() 설명이 부정확하므로 수정하세요. sample 문서의
equals() / hashCode() 항목에서 “list 에만 해당되고 Set, Map 는 적용되지 않는다”는 표현을 제거하고,
equals()는 컬렉션 종류와 무관하게 값 비교에 사용되며 List.contains()/remove()에서 직접 쓰이고 Set/Map은
hashCode()로 후보를 찾은 뒤 equals()로 최종 비교한다는 점을 반영해 일관되게 정리하세요. hashCode() 항목은 기존처럼
Set/Map에서 동등성 판단에 함께 사용된다는 설명을 유지하되, equals()와의 관계가 드러나도록 문장을 맞춰 주세요.
- Around line 85-174: Book class is missing the required Cloneable support and
clone behavior. Update the Book declaration to implement Cloneable alongside
Comparable<Book>, then add a clone() method on Book that returns a deep copy by
delegating to super.clone() and cloning the publishDate field as well. Keep the
existing Comparable, equals, hashCode, and toString methods unchanged while
locating the fix in the Book class definition and its new clone()
implementation.

---

Nitpick comments:
In `@TIL/sample/2026-06-30-인스턴스` 기본 조작.md:
- Around line 164-173: `Book.compareTo` is comparing `year`, `month`, and `day`
manually; simplify it by delegating to the existing `publishDate` field’s
compareTo and reversing the result for descending order. Update the
`compareTo(Book o)` implementation to use `publishDate` directly so the ordering
logic stays concise and easier to maintain while preserving the same descending
date sort.
- Around line 58-67: 깊은 복사 설명에서 Hero/Sword 예시 주변의 “Equals, HashCode 는 재정의 필수로”
문구를 정정하세요. 깊은 복사 자체와 equals/hashCode의 관계를 분리해서, deep copy는 객체를 새로 만들며 동작하고
equals/hashCode는 복사 후 동등성 비교나 컬렉션 사용을 위해 필요하다는 식으로 자연스럽게 문장을 다듬으세요. 해당 섹션의 깊은 복사
설명 전체를 읽기 쉽게 정리하고, 문법도 함께 바로잡으세요.
- Around line 146-157: `Book.equals` and `Book.hashCode` are comparing
`year`/`month`/`day` separately, which should be replaced with direct
`publishDate` comparison to keep the methods consistent with `setPublishDate()`
and reduce mismatch risk. Update the logic in `equals(Object o)` and
`hashCode()` to rely on the `publishDate` field together with `title`, and keep
the same equality semantics while removing the individual date component checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: dc8c9a8a-56ef-4c52-b7cb-19e4ffb4e2f7

📥 Commits

Reviewing files that changed from the base of the PR and between 206291c and 0b53203.

📒 Files selected for processing (5)
  • TIL/sample/2026-06-30-인스턴스 기본 조작.md
  • post-oop/Book.puml
  • post-oop/src/main/java/com/survivalcoding/Book.java
  • post-oop/src/main/java/com/survivalcoding/Main.java
  • post-oop/src/test/java/com/survivalcoding/BookTest.java

Comment on lines +11 to +15
private Date publishDate;
private String comment;
private int year;
private int month;
private int day;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

출간일 상태가 쉽게 불일치합니다.

publishDateyear/month/day를 중복 보관하는데, setPublishDate()는 보조 필드를 다시 계산하지 않고 getter/setter도 Date 참조를 그대로 주고받습니다. 한 번 수정되면 equals/hashCode/compareTo/toString이 실제 publishDate와 다른 값을 보게 되어 Set/Map 동작이 깨집니다. 날짜 정보는 한 곳만 기준으로 두고, Date는 복사해서 저장/반환하세요.

수정 예시
     private Date publishDate;
     private String comment;
     private int year;
     private int month;
     private int day;
+
+    private void syncDateParts() {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(this.publishDate);
+        this.year = cal.get(Calendar.YEAR);
+        this.month = cal.get(Calendar.MONTH) + 1;
+        this.day = cal.get(Calendar.DAY_OF_MONTH);
+    }
 
     public Book(String title, String publishDateStr, String comment) {
         this.title = title;
         this.comment = comment;
 
@@
-        Calendar cal = Calendar.getInstance();
-        cal.setTime(this.publishDate);
-        this.year = cal.get(Calendar.YEAR);
-        this.month = cal.get(Calendar.MONTH) + 1;
-        this.day = cal.get(Calendar.DAY_OF_MONTH);
+        syncDateParts();
@@
     public Date getPublishDate() {
-        return publishDate;
+        return (Date) publishDate.clone();
     }
 
     public void setPublishDate(Date publishDate) {
-        this.publishDate = publishDate;
+        this.publishDate = (Date) publishDate.clone();
+        syncDateParts();
     }

Also applies to: 27-31, 63-69

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@post-oop/src/main/java/com/survivalcoding/Book.java` around lines 11 - 15,
`Book` is keeping duplicate publish-date state in `publishDate` and
`year/month/day`, which can drift and break `equals`, `hashCode`, `compareTo`,
and `toString`. Make `publishDate` the single source of truth inside
`setPublishDate()`, `getPublishDate()`, and any date-based comparisons, and
remove or consistently derive the auxiliary fields instead of storing them
separately. Also defensively copy `Date` on input/output in the `Book` accessors
so callers cannot mutate internal state through shared references.

Comment on lines +21 to +24
try {
this.publishDate = new SimpleDateFormat("yyyy-MM-dd").parse(publishDateStr);
} catch (ParseException e) {
throw new RuntimeException("날짜 형식이 잘못되었습니다.");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

날짜 파싱을 엄격 모드로 바꾸세요.

SimpleDateFormat은 기본값이 lenient라 "2024-02-31" 같은 입력도 다른 날짜로 보정해 파싱합니다. 지금은 예외 대신 잘못된 출간일이 저장될 수 있으니 setLenient(false)를 켜는 편이 안전합니다.

수정 예시
         try {
-            this.publishDate = new SimpleDateFormat("yyyy-MM-dd").parse(publishDateStr);
+            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+            format.setLenient(false);
+            this.publishDate = format.parse(publishDateStr);
         } catch (ParseException e) {
             throw new RuntimeException("날짜 형식이 잘못되었습니다.");
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try {
this.publishDate = new SimpleDateFormat("yyyy-MM-dd").parse(publishDateStr);
} catch (ParseException e) {
throw new RuntimeException("날짜 형식이 잘못되었습니다.");
try {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
format.setLenient(false);
this.publishDate = format.parse(publishDateStr);
} catch (ParseException e) {
throw new RuntimeException("날짜 형식이 잘못되었습니다.");
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@post-oop/src/main/java/com/survivalcoding/Book.java` around lines 21 - 24, In
Book’s date parsing logic, SimpleDateFormat is currently using lenient parsing,
so invalid inputs like "2024-02-31" can be silently adjusted instead of
rejected. Update the parsing path in the constructor that handles publishDateStr
to set the formatter to strict mode with setLenient(false) before parse is
called, so ParseException is thrown for invalid dates and only valid publish
dates are stored.

Comment on lines +98 to +105
public int compareTo(Book o) {
if (this.year != o.year) {
return Integer.compare(this.year, o.year) * -1;
}
if (this.month != o.month) {
return Integer.compare(this.month, o.month) * -1;
}
return Integer.compare(this.day, o.day) * -1;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

compareTo()equals()와 일치하지 않습니다.

equals()는 제목+출간일을 보는데 compareTo()는 날짜만 비교합니다. 출간일이 같고 제목이 다른 두 책은 compareTo() == 0이 되어 TreeSet/TreeMap에서 하나가 사라질 수 있습니다. 같은 날짜일 때는 제목으로 한 번 더 비교해 0equals() == true인 경우에만 나오게 맞춰주세요.

수정 예시
     `@Override`
     public int compareTo(Book o) {
-        if (this.year != o.year) {
-            return Integer.compare(this.year, o.year) * -1;
-        }
-        if (this.month != o.month) {
-            return Integer.compare(this.month, o.month) * -1;
-        }
-        return Integer.compare(this.day, o.day) * -1;
+        int byDate = o.publishDate.compareTo(this.publishDate);
+        if (byDate != 0) {
+            return byDate;
+        }
+        return this.title.compareTo(o.title);
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@post-oop/src/main/java/com/survivalcoding/Book.java` around lines 98 - 105,
`Book.compareTo()` is inconsistent with `equals()` because it only compares the
publication date, so books with the same date but different titles can collapse
to 0 in sorted collections. Update `compareTo(Book o)` to keep the existing
year/month/day ordering and then compare the title as a final tie-breaker, so
`compareTo() == 0` only when `equals()` would also be true.

Comment on lines +77 to +84
@Test
@DisplayName("clone으로 값이 일치한지")
void cloneTest() {
Book book1 = new Book(BOOKNAME, BOOK_DAY, COMMENT_A);
Book book2 = book1.clone();

assertEquals(book1, book2);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

clone 테스트가 깊은 복사 요구사항을 검증하지 못합니다.

지금은 assertEquals(book1, book2)만 확인해서 clone()이 같은 인스턴스를 반환해도 통과하고, Date publishDate를 얕게 공유해도 통과합니다. PR 목표가 deep copy라면 최소한 assertNotSame(book1, book2)를 추가하고, 가능하면 mutable 상태도 서로 독립적인지 검증해 주세요.

예시
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotSame;

 `@Test`
 `@DisplayName`("clone으로 값이 일치한지")
 void cloneTest() {
     Book book1 = new Book(BOOKNAME, BOOK_DAY, COMMENT_A);
     Book book2 = book1.clone();

     assertEquals(book1, book2);
+    assertNotSame(book1, book2);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Test
@DisplayName("clone으로 값이 일치한지")
void cloneTest() {
Book book1 = new Book(BOOKNAME, BOOK_DAY, COMMENT_A);
Book book2 = book1.clone();
assertEquals(book1, book2);
}
`@Test`
`@DisplayName`("clone으로 값이 일치한지")
void cloneTest() {
Book book1 = new Book(BOOKNAME, BOOK_DAY, COMMENT_A);
Book book2 = book1.clone();
assertEquals(book1, book2);
assertNotSame(book1, book2);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@post-oop/src/test/java/com/survivalcoding/BookTest.java` around lines 77 -
84, `cloneTest`는 `Book.clone()`의 deep copy를 검증하지 못하므로, `BookTest.cloneTest`에서
`assertEquals(book1, book2)`만 두지 말고 두 객체가 같은 인스턴스가 아님을 확인하는
`assertNotSame(book1, book2)`를 추가하세요. 또한 `Book`의 mutable 필드인 `publishDate`가 있으면
`clone()` 결과가 원본과 독립적인지 함께 검증해, `clone()`이 얕은 복사가 아닌 깊은 복사임을 보장하도록 테스트를 보강하세요.

Comment on lines +17 to +23
- equals()
- 주소가 아닌 값을 비교를 한다. (list 에만 해당되고 Set, Map 는 적용되지 않는다.)
- 리스트에서 같은 값을 비교 또는 제거하고 싶다면 오버라이드로 재정의 해서 한다. (동등성 비교시 사용)

- hashCode()
- 재정의하면 Set, Map 내부에서도 동등성 규칙으로 사용이 된다.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

학습 노트의 equals()/hashCode() 동작 설명 수정 필요

Line 18의 "list 에만 해당되고 Set, Map 는 적용되지 않는다"는 사실과 다릅니다. equals()는 컬렉션 종류와 무관하게 값 비교를 위해 재정의합니다. List.contains()/remove()equals()를 직접 사용하고, Set/MaphashCode()로 빠르게 후보를 찾은 뒤 equals()로 최종 동등성을 판단합니다. hashCode()를 재정의하면 Set/Map 내부에서도 동등성 규칙이 적용되는 것이 맞습니다(Line 22). Line 18의 내용을 수정하여 일관되게 설명하세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@TIL/sample/2026-06-30-인스턴스` 기본 조작.md around lines 17 - 23, 학습 노트의
equals()/hashCode() 설명이 부정확하므로 수정하세요. sample 문서의 equals() / hashCode() 항목에서
“list 에만 해당되고 Set, Map 는 적용되지 않는다”는 표현을 제거하고, equals()는 컬렉션 종류와 무관하게 값 비교에 사용되며
List.contains()/remove()에서 직접 쓰이고 Set/Map은 hashCode()로 후보를 찾은 뒤 equals()로 최종
비교한다는 점을 반영해 일관되게 정리하세요. hashCode() 항목은 기존처럼 Set/Map에서 동등성 판단에 함께 사용된다는 설명을
유지하되, equals()와의 관계가 드러나도록 문장을 맞춰 주세요.

Comment on lines +30 to +41
- Collections.sort()
- () 안에 list 이름을 받는다.
- 자동으로 오름차순으로 정렬을 해준다.
- 내림차순으로 하려면?
- x -1 를 마지막에 해주면 된다.
- 둘다 하고 싶을 경우는?
- Comparator<>
- Comparable 인터페이스를 받고 있는 것만 가능하다.
- implement 로 Comparable 를 해주면 된다.
- 글자 비교는 compareTo 로 하면 된다.
this.name.compareTo(o.name);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Collections.sort() 내림차순 설명 정확히 기술

Line 34의 "x -1 를 마지막에 해주면 된다"는 의미가 불분명합니다. compareTo() 결과에 * -1을 곱하거나, Comparator.reversed()를 사용하는 것이 정확한 설명입니다. 예시 코드와 함께 명확히 수정하세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@TIL/sample/2026-06-30-인스턴스` 기본 조작.md around lines 30 - 41,
`Collections.sort()`의 내림차순 설명이 부정확하므로, 해당 문장을 `compareTo()` 결과를 반대로 쓰거나
`Comparator.reversed()`를 사용하는 방식으로 명확히 고쳐주세요. `Collections.sort`, `Comparable`,
`Comparator`, `compareTo`, `this.name.compareTo(o.name)` 같은 기존 설명 흐름을 유지하되, “x
-1”처럼 애매한 표현은 제거하고 내림차순을 만드는 정확한 방법을 예시와 함께 자연스럽게 정리하세요.

Comment on lines +42 to +53
- 익명클래스
- Collections.sort(heroes, new Comparator<Hero>()
- main 에서 바로 Override 를 해서 사용한다. (내림차순)
- public int compare(Hero o1, Hero o2) {
- return 01.compareTo(o2) * -1;}

- 람다식
- Collections.sort(heroes, (Hero o1, Hero o2) -> o1.compareTo(o2); // 오름차순
- Collections.sort(heroes, (Hero o1, Hero o2) -> o1.compareTo(o2) * -1; // 내림차순
- 만약 Comparable 이 없다면 구체적으로 써야한다.
- Collections.sort(heroes, (Hero o1, Hero o2) -> o1.getName().compareTo(o2.getName()); // 오름차순

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

익명 클래스/람다 예시 코드 오타 수정

Line 46: 01.compareTo(o2)o1.compareTo(o2) (숫자 0이 아닌 변수 o1)
Line 49: o1.compareTo(o2);o1.compareTo(o2)); (닫는 괄호 누락)

복사하여 사용할 경우 컴파일 오류를 유발하는 오타이므로 수정하세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@TIL/sample/2026-06-30-인스턴스` 기본 조작.md around lines 42 - 53, Fix the example
code typos in the anonymous class and lambda snippets: in the Comparator/Hero
examples, replace the mistaken `01.compareTo(o2)` in the anonymous class with
the correct `o1.compareTo(o2)` and ensure the lambda expressions under
Collections.sort have balanced parentheses, especially the `compareTo` calls in
the `Hero` sorting examples. Use the existing `Collections.sort`,
`Comparator<Hero>`, and `compare`/lambda snippets in the document to locate and
correct these compile-breaking typos.

Comment on lines +85 to +174
public class Book implements Comparable<Book> {
private String title;
private Date publishDate;
private String comment;
private int year;
private int month;
private int day;

public Book(String title, String publishDateStr, String comment) {
this.title = title;
this.comment = comment;

try {
this.publishDate = new SimpleDateFormat("yyyy-MM-dd").parse(publishDateStr);
} catch (ParseException e) {
throw new RuntimeException("날짜 형식이 잘못되었습니다.");
}

Calendar cal = Calendar.getInstance();
cal.setTime(this.publishDate);
this.year = cal.get(Calendar.YEAR);
this.month = cal.get(Calendar.MONTH) + 1;
this.day = cal.get(Calendar.DAY_OF_MONTH);
}

public int getYear() {
return year;
}

public int getMonth() {
return month;
}

public int getDay() {
return day;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public Date getPublishDate() {
return publishDate;
}

public void setPublishDate(Date publishDate) {
this.publishDate = publishDate;
}

public String getComment() {
return comment;
}

public void setComment(String comment) {
this.comment = comment;
}

@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return Objects.equals(title, book.title) &&
this.year == book.year && this.month == book.month && this.day == book.day;
}

@Override
public int hashCode() {
return Objects.hash(title, year, month, day);
}

@Override
public String toString() {
return String.format("Book{%s-%d-%02d-%02d}", title, year, month, day);
}

@Override
public int compareTo(Book o) {
if (this.year != o.year) {
return Integer.compare(this.year, o.year) * -1;
}
if (this.month != o.month) {
return Integer.compare(this.month, o.month) * -1;
}
return Integer.compare(this.day, o.day) * -1;
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

임베디드 Book 클래스에 Cloneableclone() 누락

PR 목표와 UML 다이어그램에 명시된 Cloneable 구현 및 clone() 메서드가 임베디드 실습 코드에는 포함되어 있지 않습니다. Line 85의 선언부에 implements Comparable<Book>, Cloneable을 추가하고, 깊은 복사를 수행하는 clone() 메서드를 추가하여 요구사항과 일치시키세요.

🔧 제안: Cloneable 추가 및 clone() 구현
-public class Book implements Comparable<Book> {
+public class Book implements Comparable<Book>, Cloneable {
    `@Override`
    public Book clone() {
        try {
            Book cloned = (Book) super.clone();
            cloned.publishDate = (Date) this.publishDate.clone();
            return cloned;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public class Book implements Comparable<Book> {
private String title;
private Date publishDate;
private String comment;
private int year;
private int month;
private int day;
public Book(String title, String publishDateStr, String comment) {
this.title = title;
this.comment = comment;
try {
this.publishDate = new SimpleDateFormat("yyyy-MM-dd").parse(publishDateStr);
} catch (ParseException e) {
throw new RuntimeException("날짜 형식이 잘못되었습니다.");
}
Calendar cal = Calendar.getInstance();
cal.setTime(this.publishDate);
this.year = cal.get(Calendar.YEAR);
this.month = cal.get(Calendar.MONTH) + 1;
this.day = cal.get(Calendar.DAY_OF_MONTH);
}
public int getYear() {
return year;
}
public int getMonth() {
return month;
}
public int getDay() {
return day;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Date getPublishDate() {
return publishDate;
}
public void setPublishDate(Date publishDate) {
this.publishDate = publishDate;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return Objects.equals(title, book.title) &&
this.year == book.year && this.month == book.month && this.day == book.day;
}
@Override
public int hashCode() {
return Objects.hash(title, year, month, day);
}
@Override
public String toString() {
return String.format("Book{%s-%d-%02d-%02d}", title, year, month, day);
}
@Override
public int compareTo(Book o) {
if (this.year != o.year) {
return Integer.compare(this.year, o.year) * -1;
}
if (this.month != o.month) {
return Integer.compare(this.month, o.month) * -1;
}
return Integer.compare(this.day, o.day) * -1;
}
}
public class Book implements Comparable<Book>, Cloneable {
private String title;
private Date publishDate;
private String comment;
private int year;
private int month;
private int day;
public Book(String title, String publishDateStr, String comment) {
this.title = title;
this.comment = comment;
try {
this.publishDate = new SimpleDateFormat("yyyy-MM-dd").parse(publishDateStr);
} catch (ParseException e) {
throw new RuntimeException("날짜 형식이 잘못되었습니다.");
}
Calendar cal = Calendar.getInstance();
cal.setTime(this.publishDate);
this.year = cal.get(Calendar.YEAR);
this.month = cal.get(Calendar.MONTH) + 1;
this.day = cal.get(Calendar.DAY_OF_MONTH);
}
public int getYear() {
return year;
}
public int getMonth() {
return month;
}
public int getDay() {
return day;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Date getPublishDate() {
return publishDate;
}
public void setPublishDate(Date publishDate) {
this.publishDate = publishDate;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
`@Override`
public Book clone() {
try {
Book cloned = (Book) super.clone();
cloned.publishDate = (Date) this.publishDate.clone();
return cloned;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
`@Override`
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return Objects.equals(title, book.title) &&
this.year == book.year && this.month == book.month && this.day == book.day;
}
`@Override`
public int hashCode() {
return Objects.hash(title, year, month, day);
}
`@Override`
public String toString() {
return String.format("Book{%s-%d-%02d-%02d}", title, year, month, day);
}
`@Override`
public int compareTo(Book o) {
if (this.year != o.year) {
return Integer.compare(this.year, o.year) * -1;
}
if (this.month != o.month) {
return Integer.compare(this.month, o.month) * -1;
}
return Integer.compare(this.day, o.day) * -1;
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@TIL/sample/2026-06-30-인스턴스` 기본 조작.md around lines 85 - 174, Book class is
missing the required Cloneable support and clone behavior. Update the Book
declaration to implement Cloneable alongside Comparable<Book>, then add a
clone() method on Book that returns a deep copy by delegating to super.clone()
and cloning the publishDate field as well. Keep the existing Comparable, equals,
hashCode, and toString methods unchanged while locating the fix in the Book
class definition and its new clone() implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant