장르: 애초에 역경을 딛고 이룩하는 숭고한 사랑이란 없다. 그 역경 자체가 사랑이다.
프로그램 특징: 그 곳에서 살아남는 사랑이 어떤 모습으로 걸어오는지 기다려 보고 싶다.
-
이것이 자바다(3판) 9장 익명객체 풀다가 new와 final을 이해하기 위해 JVM 메모리 동작 공부0425분7. 다음 Chatting 클래스는 컴파일 에러가 발생합니다. 원인을 설명해보세요.public class Chatting { class Chat { void start() {} void sendMessage(String message) {} } void startChat(String chatId) { String nickName = null; nickName = chatId; Chat chat = new Chat() { @Override public void start() { while(true) { String inputData = "안..
-
[JAVA][BOJ 1911] 흙길 보수하기 - 그리디 pq0424분[Gold V] 흙길 보수하기 - 1911문제 링크성능 요약 메모리: 39344 KB, 시간: 448 ms분류 그리디 알고리즘, 정렬, 스위핑문제 설명어젯밤 겨울 캠프 장소에서 월드 본원까지 이어지는, 흙으로 된 비밀길 위에 폭우가 내려서 N(1 ≤ N ≤ 10,000)개의 물웅덩이가 생겼다. 월드학원은 물웅덩이를 덮을 수 있는 길이가 L(1 ≤ L ≤ 1,000,000)인 널빤지들을 충분히 가지고 있어서, 이들로 다리를 만들어 물웅덩이들을 모두 덮으려고 한다. 물웅덩이들의 위치와 크기에 대한 정보가 주어질 때, 모든 물웅덩이들을 덮기 위해 필요한 널빤지들의 최소 개수를 구하여라.입력첫째 줄에 두 정수 N과 L이 들어온다.둘째 줄부터 N+1번째 줄까지 총 N개의 줄에 각각의 웅덩이들의 정보가 주어진다. ..
-
[JAVA] 이것이 자바다(3판) 7장 상속 확인문제 답안0423분6. Parent 클래스를 상속해서 Child 클래스를 다음과 같이 작성했는데, Child 생성자에서 컴파일 에러가 발생했습니다. 그 이유와 해결 방법을 설명해보세요.public class Parent { public String name; // 매개변수가 있는 생성자 public Parent(String name) { this.name = name; }}public class Child extends Parent { public int studentNo; public Child(String name, int studentNo) { this.name = name; this.studentNo = studentNo; }..
-
[JAVA] 객체지향의 꽃: 클래스0417분OOP 프로그래밍이 뭘까요?Object-Oriented Programming 에서 Object는 데이터(필드)와 메소드를 하나로 묶어서 사용하겠다는 개념입니다.Encapsulation → 정보 보안Inheritance → 유지보수 용이Polymorphism → 클래스 형변환: 실무에서 많이 사용 클래스 기본 구조 field, method, Constructor필드와 메소드는 선택적으로 가질 수 있다. public class Car { String company = "현대자동차"; String model; String color; int maxSpeed; // 생성자 선언하지 않으면 자동 선언된다. // 선언한 경우에는 필요한 경우에 대한 선언자를 만들어줘야 한다. Car(..
-
[JAVA] 이것이 자바다(3판) 6장 20번 답안0417분20. 키보드로부터 계좌 정보를 입력받아 계좌를 관리하는 프로그램입니다. 계좌는 Account 객체로 생성되고 BankApplication에서 길이 100 Account[] 배열로 관리됩니다. Account.classpackage ThisisJAVA.ch06.bank;public class Account { static final int MIN_BALANCE = 0; static final int MAX_BALANCE = 1000000; String accountNum; String accountOwner; int balance, withdraw, deposit; Account(String accountNum, String accountOwner, int deposit) ..
-
[BOJ 2178][JAVA] 공백없이 입력된 문자 하나씩 받아올때0416분문제 2178 문제링크 N×M크기의 배열로 표현되는 미로가 있다.101111101010101011111011미로에서 1은 이동할 수 있는 칸을 나타내고, 0은 이동할 수 없는 칸을 나타낸다. 이러한 미로가 주어졌을 때, (1, 1)에서 출발하여 (N, M)의 위치로 이동할 때 지나야 하는 최소의 칸 수를 구하는 프로그램을 작성하시오. 한 칸에서 다른 칸으로 이동할 때, 서로 인접한 칸으로만 이동할 수 있다.위의 예에서는 15칸을 지나야 (N, M)의 위치로 이동할 수 있다. 칸을 셀 때에는 시작 위치와 도착 위치도 포함한다.입력첫째 줄에 두 정수 N, M(2 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.출력첫째 줄에 지나..
-
[JAVA] 참조형 : 배열 초기화, 복사0416분Data TypePrimitive TypeReference Type정수 실수논리ArrayEnumClassInterfacebytecharshortintlongfloatdoubleboolean 참조형에서 가장 많이 사용되는 배열을 보자. 배열은 마지막 인덱스에 length를 가진다. 배열은 크기가 정해지면 변경할 수 없다. 배열명(배열 변수:scores)는 stack에 저장되어 heap 영역에 생성된 배열을 참조하는 방식으로 이용한다. 배열 변수(scores)는 힙 영역의 배열 주소를 저장한다. 따라서 인덱스로 접근할 수 있다.배열 내부는 같은 type 값으로 관리하나, 해당 배열이 가리키는 주소의 객체 타입은 다를 수 있다. 배열 초기화// 정적 초기화String season = {"Spring", ..
-
[JAVA] 이것이 자바다(3판) 5장 9번 답안0415분9. 키보드로 학생 수와 각 학생들의 점수를 입력받고 최고 점수 및 평균 점수를 출력하는 코드를 작성해보세요.package ch05.referenceType;import java.util.Scanner;public class Chap5 { public static void main(String[] args) { boolean run = true; Scanner sc = new Scanner(System.in); int studentNum = 0; Integer[] scoreList = null; int max = 0; int total = 0; while (run) { System.out.pr..
-
[BOJ 10552][JAVA] 박싱/언박싱0415분[Silver II] DOM - 10552문제 링크성능 요약 메모리: 178132 KB, 시간: 1000 ms분류 너비 우선 탐색, 깊이 우선 탐색, 그래프 이론, 그래프 탐색제출 일자 2025년 4월 15일 12:16:15문제 설명In a retirement home, N senior citizens are watching television. The television programme consists of M channels denoted with numbers from 1 to M. Each of the pensioners has their own favourite and hated TV channel.If the television is currently displaying the hated c..
7. 다음 Chatting 클래스는 컴파일 에러가 발생합니다. 원인을 설명해보세요.
public class Chatting {
class Chat {
void start() {}
void sendMessage(String message) {}
}
void startChat(String chatId) {
String nickName = null;
nickName = chatId;
Chat chat = new Chat() {
@Override
public void start() {
while(true) {
String inputData = "안녕하세요.";
String message = "[" + nickName + "]" + inputData;
sendMessage(message);
}
}
};
chat.start();
}
}
닉네임은 메소드의 지역변수이므로 final의 특징을 가진다. 따라서 값을 변경할 수 없어 String nickName = chatId;로 선언해야 한다.
💥 나는 왜 계속 String null로 초기화하면 값 넣을 때 new로 해야하는 줄 알았을까 ㅠ
⇒ 요약: String은 기본형처럼 자주 쓰여서, 특별하게 최적화된 참조형, JVM에서 String Pool이라는 영역을 따로 만들어 관리.
참조형을 null로 초기화하고 new없이 값 대입하려고 하면 컴파일 에러나는 것이 맞다. String만 특이한 경우다.
new를 써야 하는 경우 vs 안 써도 되는 경우
자바에서의 기본 규칙
- 기본형(primitive type)→ 값 자체를 스택(stack)에 저장함
- → int, boolean, double …
- 참조형(reference type)→ 스택에는 참조(주소)만 저장되고,
- 진짜 객체는 힙(heap)에 저장됨
- → String, Array, Class, Object, List 등
상황 | new | 예시 | 설명 |
String 리터럴 | ❌ | String s = "hello"; | "hello"는 String pool에 자동 등록됨 |
String 강제로 새로 만들기 | ✅ | String s = new String("hi"); | 힙에 따로 객체 만듦 (비효율적) |
배열 생성 | ✅ | int[] arr = new int[5]; | 크기 지정해야 하므로 반드시 new 필요 |
클래스 인스턴스 생성 | ✅ | Student s = new Student(); | new 없이 객체 없음 |
List/Map 등 컬렉션 | ✅ | List<String> list = new ArrayList<>(); | 인터페이스라서 반드시 구현체 생성해야 함 |
왜 어떤 경우에는 new가 필요한가?
null로 초기화된 참조 변수는 아무 객체도 가리키지 않음. → 사용 시 NullPointerException 발생함
Student s = null;
s.name = "kim"; // ❌ NPE 발생
하지만 이렇게 하면 OK:
Student s = new Student();
s.name = "kim"; // ✅ 안전하게 사용 가능
질문 | 답변 |
참조형은 new로 꼭 생성해야 하나요? | ❌ String처럼 안 써도 되는 경우 있음 |
new로 안 만들면 메모리 할당 안 되나요? | 참조만 있고 힙 객체 없음 → NPE 위험 |
언제 new 써야 하나요? | 객체를 직접 만들어야 할 때만 써야 함 |
null 초기화한 참조형에 값 대입 가능해요? | ❌ String 제외, new로 객체 없으면 → 대입 불가, NullPointerException |
local class 내부 local variable 은 왜 final처럼 값 변경이 되지 않는걸까??
⇒ 요약: 지역 변수는 스택에 저장되고 메서드 실행이 되면 사라진다. 로컬 클래스/익명클래스는 힙에 저장되어 나중에 스레드나 이벤트로 호출 가능해지는 모순 발생. 이를 막기 위해 JVM이 지역 변수의 복사본을 힙에 같이 저장. 복사값이 원본과 달라지면 동기화 문제가 생기니까 변수 변경을 막아버림
void example() {
int count = 10;
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println(count); // ← 여기를 참조함
}
};
r.run();
}
여기서 count는 스택에 위치. Runnable r은 힙에 올라가는 익명 클래스
메서드가 끝나면 count는 사라지는데, 익명 클래스 내부에서는 계속 참조하려 함 → 위험
자바는 JVM이 지역 변수의 복사본을 내부적으로 만들어 힙에 같이 저장
복사된 값은 힙에 올라간 객체의 일부 필드처럼 존재해서 익명 클래스 내부에서 안전하게 사용 가능하다.
그런데 복사한 값과 원본이 달라지면 동기화 문제가 생기니까 애초에 변수 변경을 못 하게 막아버림
💢 익명 클래스를 재사용한다는 말은 뭐지? 익명 클래스는 선언하면 메소드 영역에 $class 이런식으로 올라가서 1회용으로 사용하고 재사용이 안된다고 알고 있는데 힙에 올라가서 재사용 된다는 건 뭔 말일까
용어 | 의미 | 예시 |
클래스(Class) | 코드 정의 (메서드, 필드 정보 등) → .class 파일 | public class MyClass {...} |
객체(Object) | 클래스 기반으로 생성된 인스턴스 (실제 데이터 덩어리) | new MyClass() |
JVM 기준
영역 | 설명 | 관리자 |
메서드 영역 (Method Area) | 클래스의 정의 정보(바이트코드)가 올라감 → 클래스 로딩 시 | 클래스 로더(정적 구조) |
힙 영역 (Heap) | 실제 객체(인스턴스)가 생성되어 저장됨 | GC(런타임 객체) |
스택 영역 (Stack) | 지역 변수, 참조 변수 등 저장됨 |
실행 과정
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("익명 클래스");
}
};
- 컴파일러가 자동으로 익명클래스 정의 생성 → static area : Outer$1.class → 1회용
- new Runnable() 이므로 객체가 힙에 생성 : 익명 클래스의 인스턴스 생성
익명객체의 재사용성을 메모리 관점에서 생각해본 결론
클래스 로딩될 때 클래스 정의는 메소드 영역에 올라가고, 함수 내 변수는 stack에 올라간다.
이때 익명 객체를 이용하면 Outer$1.class 이런 식으로 메서드 영역에 올라가고, 변수(스택)에 객체 주소(힙)를 연결해 한 번은 사용 가능하다.
메서드가 종료되면 스택에 올라간 변수가 사라져서 익명 객체에 접근할 길이 없어진다.
힙이 참조가 끊긴 객체는 GC(Garbage Collector)가 수거해가면서 생애주기가 끝난다.
지역 클래스의 지역 변수가 final처럼 값 변경이 안되는 이유
지역 변수는 스택에, 클래스 객체는 힙에 올라가서 스택에서 힙 주소값을 주어야 힙에 있는 객체가 사용 가능하다.
근데 지역 변수는 메서드가 끝나면 사라져 버려서 힙 주소를 잃어버리는 dangling이 일어난다. 클래스 객체는 자신의 주소를 아는 변수가 없으니 GC에서 수거해가면서 사라진다.
이를 막고자 JVM이 지역변수를 객체를 힙에 올릴 때 복사해서 같이 올린다.
복사된 값은 힙에 올라간 객체의 일부 필드처럼 존재해서 익명 클래스 내부에서 안전하게 사용 가능하다.
근데 스택에 있는 원본 변수 값을 바꿔버리면 힙에 올라간 지역변수명과 동기화 문제가 난다. 그래서 로컬 클래스 내부 지역 변수는 값 변경이 안되도록 final 특성을 가진다.
'Programming' 카테고리의 다른 글
[JAVA][BOJ 1911] 흙길 보수하기 - 그리디 pq (1) | 2025.04.24 |
---|---|
[JAVA] 이것이 자바다(3판) 7장 상속 확인문제 답안 (0) | 2025.04.23 |
[JAVA] 객체지향의 꽃: 클래스 (2) | 2025.04.17 |
[JAVA] 이것이 자바다(3판) 6장 20번 답안 (0) | 2025.04.17 |
[BOJ 2178][JAVA] 공백없이 입력된 문자 하나씩 받아올때 (1) | 2025.04.16 |