Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 170 additions & 0 deletions TIL/sample/2026-06-30-인스턴스기본조작.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# 2026-06-30 인스턴스 기본 조작.

## 오늘 배운 내용

- Object 클래스의 기본기능
-
1. 모든 클래스는 Object 클래스의 메서드를 가지고 있다
-
2. Object 타입 변수에는 모든 인스턴스를 대입할수있따
- <Object 클래스의 대표 메서드>
- toString() : 문자열 표현을 얻음
- equals() : 비교
- hashCode() : 해시값을 얻음
- toString()는 오버라이드하여 원하는 결과를 얻도록 수정할 수 있따
- equals()는 메서드를 오버라이드하여 동등성 규칙을 정의하고 List에서 동등성 비교시 사용된다
- hashCode()를 재정의하면 Set, Map 내부에서의 동등성 규칙으로 사용된다

## 기억할 것

- Set, Map 계열은 요소를 검색할 때 equals() 보다 비용이 싼 hashCode() 비교를 사용함
- List 는 순차 검색이라 느림
-
1. 모든 객체는 해시값을 가진다
-
2. 동일한 객체는 항상 같은 해시값을 가진다.
-
3. 하지만, 같은 해시값이라고 항상 동일한 객체는 아니다.
- Collections.sort() 메서드는 컬렉션 내부를 정렬해 준다
- 정렬 대상은 반드시 Comparable 인터페이스를 구현해야 한다
- Comparable 인터페이스를 구현하지 않은 객체도 즉석에서 정렬 규칙을 정해줄 수 있음
- 규칙은 동일 compareTo() 의 규칙과 동일
- a, b 가 매개변수인 경우
-
1. a 가 b 보다 작으면 음수 (-1)
-
2. 같으면 0
-
3. a 가 b 보다 크면 양수 (+1)
- 얕은 복사는 객체 자체는 새로 생성되지만, 객체 내의 참조 타입 필드(다른 객체에 대한 참조)는 원본과 동일한 객체를 참조합니다.
- 즉, 중첩된 객체는 복사되지 않고 주소만 복사됩니다.
- 원본 객체의 참조 타입 필드를 변경하면 복사본의 해당 필드도 함께 변경됩니다.

## 정리

### 객체의 내용을 알기 쉽게 보여주기 위해 다음 메서드를 재정의 해 준다

- toString()

### 객체의 동등성 비교 규칙을 위해 다음 메서드를 재정의 해 준다

- equals
- hashCode

### 복사를 지원하기 위해 다음 메서드를 작성한다.

- Cloneable 인터페이스를 구현하여 얕은 복사를 구현하기로 한다

### 얕은 복사

- 객체 자체는 새로 생성되지만, 객체 내의 참조 타입 필드(다른 객체에 대한 참조)는 원본과 동일한 객체를 참조합니다.
- 즉, 중첩된 객체는 복사되지 않고 주소만 복사됩니다.
- 원본 객체의 참조 타입 필드를 변경하면 복사본의 해당 필드도 함께 변경됩니다.

### 깊은 복사

- 객체 자체뿐만 아니라, 객체 내의 모든 참조 타입 필드(중첩된 객체들)까지도 재귀적으로 완전히 새로 생성하여 복사합니다.
- 원본 객체와 복사본 객체는 완전히 독립적입니다. 한쪽을 변경해도 다른 쪽에는 영향을 주지 않습니다.
Comment on lines +54 to +67

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

복사 설명이 현재 구현과 맞지 않습니다.

Line 56은 “얕은 복사”라고 적혀 있지만, 아래 코드의 clone()publishDate를 별도 Date로 복제해서 부분적인 깊은 복사를 하고 있습니다. TIL 내용과 예제 코드가 서로 다르게 읽히니 한쪽으로 맞춰 주세요.

🤖 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 54 - 67, 복사 설명과 `clone()` 예제가
서로 다른 수준의 복사를 설명하고 있습니다. `clone()`이 `publishDate`를 새 `Date`로 복제하는 현재 동작에 맞게 문서의
“얕은 복사” 설명을 수정하거나, 반대로 예제를 완전한 얕은 복사로 바꿔서 `clone()`과 설명이 일치하도록 정리하세요. `clone()`과
“얕은 복사/깊은 복사” 섹션이 같은 의미를 가리키도록 맞추면 됩니다.


## 실습 코드

```java
package com.survivalcoding;

import java.util.Date;
import java.util.Objects;

public class Book implements Comparable<Book>, Cloneable {
private String title;
private Date publishDate;
private String comment;

public Book() {
}

public Book(String title, Date publishDate, String comment) {
this.title = title;
this.publishDate = publishDate;
this.comment = comment;
}

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 String toString() {
return "Book{" +
"title='" + title + '\'' +
", publishDate=" + publishDate +
", 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) && Objects.equals(publishDate, book.publishDate);
}

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

@Override
public int compareTo(Book other) {
if (this.publishDate == null || other.publishDate == null) {
return 0;
}
return other.publishDate.compareTo(this.publishDate);
}


@Override
public Book clone() {
Book result = new Book();
result.title = this.title;
result.comment = this.comment;
if (this.publishDate != null) {
result.publishDate = (Date) this.publishDate.clone();
}
return result;
}
}


```

## 어려웠던 점

- 수업 내용이랑 연습문제가 어려웠다

## 해결 방법

- 최대한 찾아가며 연습문제를 풀었다

## 내일 더 공부할 것

- 복사랑 정렬에 대해 공부해야될거 같다
34 changes: 34 additions & 0 deletions post-oop/06_30.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
@startuml
skinparam classAttributeIconSize 0

interface Comparable<T> {
+ compareTo(other: T): int
}

interface Cloneable {
}

class Book {
- title: String
- publishDate: Date
- comment: String

+ Book()
+ Book(title: String, publishDate: Date, comment: String)
+ getTitle(): String
+ setTitle(title: String): void
+ getPublishDate(): Date
+ setPublishDate(publishDate: Date): void
+ getComment(): String
+ setComment(comment: String): void
+ toString(): String
+ equals(o: Object): boolean
+ hashCode(): int
+ compareTo(other: Book): int
+ clone(): Book
}

Comparable <|.. Book : <<realizes>>
Cloneable <|.. Book : <<realizes>>

@enduml
20 changes: 20 additions & 0 deletions post-oop/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
plugins {
id 'java'
}

group = 'com.survivalcoding'
version = '1.0-SNAPSHOT'

repositories {
mavenCentral()
}

dependencies {
testImplementation platform('org.junit:junit-bom:6.0.0')
testImplementation 'org.junit.jupiter:junit-jupiter'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

test {
useJUnitPlatform()
}
99 changes: 99 additions & 0 deletions post-oop/src/main/java/com/survivalcoding/Book.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package com.survivalcoding;

import java.util.Date;
import java.util.Objects;

public class Book implements Comparable<Book>, Cloneable {
private String title;
private Date publishDate;
private String comment;

public Book() {
}

public Book(String title, Date publishDate, String comment) {
this.title = title;
this.publishDate = publishDate;
this.comment = comment;
}

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 String toString() {
return "Book{" +
"title='" + title + '\'' +
", publishDate=" + publishDate +
", comment='" + comment + '\'' +
'}';
}

@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
if (this.publishDate != null && book.publishDate != null) {
// 년-월-일 형태로 포맷을 지정
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");

String d1 = sdf.format(this.publishDate);
String d2 = sdf.format(book.publishDate);

return Objects.equals(title, book.title) && d1.equals(d2);
}
return Objects.equals(title, book.title) && Objects.equals(publishDate, book.publishDate);
}

@Override
public int hashCode() {
if (this.publishDate != null) {
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
String dateStr = sdf.format(this.publishDate);
return Objects.hash(title, dateStr);
}

return Objects.hash(title, publishDate);
}

@Override
public int compareTo(Book other) {
if (this.publishDate == null || other.publishDate == null) {
return 0;
}
return other.publishDate.compareTo(this.publishDate);
Comment on lines +81 to +85

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

compareTo()가 현재 equals()와 충돌합니다.

같은 publishDate를 가진 서로 다른 책이거나, 둘 중 하나의 날짜가 null인 경우에도 0을 반환해서 서로 다른 객체가 같은 정렬 키로 취급됩니다. 이 상태로 TreeSet/TreeMap에 넣으면 데이터가 누락될 수 있습니다.

수정 예시
 `@Override`
 public int compareTo(Book other) {
-    if (this.publishDate == null || other.publishDate == null) {
-        return 0;
-    }
-    return other.publishDate.compareTo(this.publishDate);
+    int byPublishDate = java.util.Comparator
+            .nullsLast(java.util.Comparator.<Date>reverseOrder())
+            .compare(this.publishDate, other.publishDate);
+    if (byPublishDate != 0) {
+        return byPublishDate;
+    }
+    return java.util.Comparator
+            .nullsFirst(String::compareTo)
+            .compare(this.title, other.title);
 }
📝 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 int compareTo(Book other) {
if (this.publishDate == null || other.publishDate == null) {
return 0;
}
return other.publishDate.compareTo(this.publishDate);
public int compareTo(Book other) {
int byPublishDate = java.util.Comparator
.nullsLast(java.util.Comparator.<Date>reverseOrder())
.compare(this.publishDate, other.publishDate);
if (byPublishDate != 0) {
return byPublishDate;
}
return java.util.Comparator
.nullsFirst(String::compareTo)
.compare(this.title, other.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 66 - 70,
`Book.compareTo()`가 `equals()`와 일치하지 않아 같은 `publishDate`이거나 `null`일 때 모두 0을
반환합니다. `compareTo(Book other)`에서 `publishDate`만으로 동등 처리하지 말고, `publishDate`가 같거나
둘 다 null인 경우에는 `title`이나 식별자 같은 다른 필드로 2차 비교를 추가해 서로 다른 `Book`이 0으로 묶이지 않도록
수정하세요. `Book` 클래스의 `compareTo()`, `equals()`, `publishDate` 처리 로직이 일관되게 정렬되도록
맞추면 됩니다.

}


@Override
public Book clone() {
Book result = new Book();
result.title = this.title;
result.comment = this.comment;
if (this.publishDate != null) {
result.publishDate = (Date) this.publishDate.clone();
}
return result;
}
}
17 changes: 17 additions & 0 deletions post-oop/src/main/java/com/survivalcoding/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.survivalcoding;

//TIP 코드를 <b>실행</b>하려면 <shortcut actionId="Run"/>을(를) 누르거나
// 에디터 여백에 있는 <icon src="AllIcons.Actions.Execute"/> 아이콘을 클릭하세요.
public class Main {
public static void main(String[] args) {
//TIP 캐럿을 강조 표시된 텍스트에 놓고 <shortcut actionId="ShowIntentionActions"/>을(를) 누르면
// IntelliJ IDEA이(가) 수정을 제안하는 것을 확인할 수 있습니다.
System.out.printf("Hello and welcome!");

for (int i = 1; i <= 5; i++) {
//TIP <shortcut actionId="Debug"/>을(를) 눌러 코드 디버그를 시작하세요. 1개의 <icon src="AllIcons.Debugger.Db_set_breakpoint"/> 중단점을 설정해 드렸습니다
// 언제든 <shortcut actionId="ToggleLineBreakpoint"/>을(를) 눌러 중단점을 더 추가할 수 있습니다.
System.out.println("i = " + i);
}
}
}
Loading