목차
1. Chapter 2 - 3 : 래퍼클래스(기본형, 참조형)
1. 래퍼클래스(Wrapper Class)
- 기본 자료형을 객체로 감싸는 클래스.
기본 자료형 (Primitive Type) | 래퍼 클래스 (Wrapper Class) |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
2. 참조형(Reference Type)
- 변수에 객체가 담기면 해당 변수를 "참조형 변수" 라고 함.
- 참조형 변수는 데이터가 저장된 메모리 주소(Heap)를 가리킴
- 객체 데이터는 Heap 영역에 저장되어 있기 때문.
- 객체, 배열 등이 참조형에 속함.
예시)
Person personA = new Person("Steve"); // ✅ 객체가 담긴 personA 는 참조형 변수입니다.
Syetem.out.println(personA.name);
System.out.println(personA); // ✅ 출력하면 @123 메모리의 주소값이 출력됩니다.
int[] arr = {1, 2, 3, 4}; // ✅ 배열이 담긴 arr 는 참조형 변수입니다.
System.out.println(arr); // ✅ 출력하면 @123 메모리의 주소값이 출력됩니다.
- 래퍼클래스가 담겨 있는 변수도 참조형 변수.
BUT 출력 시 메모리 주소값이 나오지 않음. → 내부적으로 toString()이 오버라이딩 되어있음.
Integer num = 100;
System.out.println(num); // 출력 100
🤓 오버라이딩(Overriding)
- 부모 클래스에 정의된 메서드를 자식 클래스에서 새롭게 정의하는 것.
매개변수와 리턴 타입이 같아야 함.(= 정적 다형성).
→ 기존에 부모 클래스에서 정의한 메서드가 아닌,
자식 클래스에서 새롭게 정의한 메서드가 실행된다.
래퍼 클래스를 사용하는 이유
- 기본 자료형은 객체처럼 속성, 기능을 가질 수 없음.
- 객체는 기능을 가질 수 있음 → 기본형을 감싼 객체를 만들어서 기능을 제공하면 편리하게 데이터 처리 가능.
Integer num = 123; // 래퍼클래스
String str = num.toString(); // ✅ 편리한 기능
int a = 100; // 그냥 데이터 100
String str = a.toString(); // ❌ 변환 불가
- 래퍼클래스는 객체기 때문에 기능 부분을 활용할 수 있음.
* Wrapper 클래스는 객체이기 때문에 다양한 편리 기능을 미리 내부적으로 정의해둠.
→ 기능 중에 하나가 toString()
→ toString()은 정수형 데이터를 문자열 데이터로 바꾸어주는 역할을 함.
Integer num = 200;
String num2 = num.toString();
오토박싱 vs 언박싱
- 래퍼 클래스 ↔ 기본형으로 형변환이 굉장히 자주 일어남.
- Java에서는 형변환 과정을 자동으로 지원.
Integer num3 = 10; // 오토박싱 (기본형을 자동으로 래퍼 클래스 객체로 변환)
int num = num3; // 오토 언박싱(참조형을 자동으로 기본형으로 변환)
오토박싱(Auto-boxing)
- 기본형 → 래퍼형 으로 변환하는 과정.
- Integer는 참조형(객체)이지만 기본형 int값을 직접 대입할 수 있음.
Integer num3 = 10; // ✅ 오토박싱
// ✅ 내부적 자동 처리(래퍼형 <- 기본형)
Integer num = Integer.valueOf(10);
- 내부적으로는 valueOf()를 사용하여 자동처리하는 것이다.
오토 언박싱(Auto-Unboxing)
- 래퍼형 → 기본형으로 변환하는 과정.
- num은 Integer 객체지만 기본형 int 변수에 대입 가능.
Integer num3 = 10;
int num = num3; // ✅ 오토 언박싱
// ✅ 내부적 자동처리(기본형 <- 래퍼형)
int a = num.intValue();
- 내부적으로 컴파일러가 num.intValue()를 호출하여 기본형으로 변환하기 때문.
기본형과 래퍼형 성능 비교
- 래퍼형은 내부적으로 데이터를 감싸고 있기 때문에 연산 시 불리함.
→ 객체에서 기본형 값을 꺼내서 연산하는 추가작업이 발생하기 때문.
- 빠른 작업이 필요한 경우 기본형을 직접 활용하는 것이 좋은 선택.
[퀴즈]
Q1. double 기본형과 직접만든 MyDouble 래퍼형의 연산 성능차이 확인하기
정답)
// 직접 만든 Double 래퍼 클래스
class MyDouble {
private final double value;
public MyDouble(double value) {
this.value = value;
}
public double getValue() {
return value;
}
// 덧셈
public MyDouble add(MyDouble other) {
return new MyDouble(this.value + other.value);
}
@Override
public String toString() {
return String.valueOf(value);
}
}
public class DoubleWrapperPerformance {
public static void main(String[] args) {
int iteration = 10_000_000; // 1000만 번 반복
// 1. 기본형 double 연산
long startTime1 = System.nanoTime();
double sum1 = 0.0;
for (int i = 0; i < iteration; i++) {
sum1 += i * 1.1;
}
long endTime1 = System.nanoTime();
long primitiveTime = endTime1 - startTime1;
// 2. MyDouble 연산
long startTime3 = System.nanoTime();
MyDouble sum3 = new MyDouble(0.0);
for (int i = 0; i < iteration; i++) {
sum3 = sum3.add(new MyDouble(i * 1.1));
}
long endTime3 = System.nanoTime();
long myDoubleTime = endTime3 - startTime3;
// 결과 출력
System.out.println("기본형(double) 연산 시간: " + primitiveTime + " ns");
System.out.println("MyDouble 클래스 연산 시간: " + myDoubleTime + " ns");
System.out.println("MyDouble vs double 성능 차이: " + (double) myDoubleTime / primitiveTime);
}
}
2. Chapter 2 - 4 : static - 클래스가 공유하는 공간
1. Static
- 모든 객체가 함께 사용하는 변수나 메서드를 만들 때 사용됨.
- 객체(인스턴스)를 만들지 않아도 클래스 이름만으로 바로 사용 가능.
- 모든 객체가 같은 값 공유.
- static 변수와 메서드는 실행 시점에 한 번만 생성되고 Method Area에 저장됨.
Static 활용
- static은 변수, 메서드에 붙일 수 있음.
- static 키워드로 선언된 변수와 메서드는 Method Area에 저장됨.
- 각 객체(인스턴스)는 클래스 영역에 저장된 데이터 활용 가능.
public class Person {
// static 변수
static int population = 0;
// static 메서드
static void printPopulation() {
System.out.println("현재 인구 수 : " + population);
}
}
public class Main {
public static void main(String[] args) {
// 객체(Person person = new Person()) 를 따로 생성할 필요 없이
// Class 레벨을 통해 접근하여 바로 사용 가능.
// 프로그램 시작 시점에 Method Area에 올라가 있기 때문에 가능함.
System.out.println("static 변수 활용 : " + Person.population);
Person.printPopulation();
}
}
- 객체( Person person = new Person( ) )를 따로 생성할 필요 없이 Class 레벨을 통해 접근하여 바로 사용 가능.
- 프로그램 시작 시점에 Method Area에 올라가 있기 때문에 가능함.
2. 인스턴스 멤버
- 객체를 만들 때마다 생성되는 변수와 메서드.
- 객체(인스턴스)를 생성한 후에만 사용 가능.
- 각 객체가 개별적으로 값을 가짐(공유되지 않음!!)
- 인스턴스는 Heap Area 에 위치함.
1. 인스턴스 변수
- 객체가 생성될 때마다 따로 만들어지는 변수.
- 객체를 생성한 후 접근할 수 있음.
- name 변수는 각 객체마다 별도로 저장됨.
2. 인스턴스 메서드
- 객체의 속성을 활용하는 메서드.
- 객체가 생성된 후에만 사용 가능.
3. 클래스 멤버
- 클래스 자체에 속하는 변수와 메서드.
- static 키워드를 사용하여 선언.
1. 클래스 변수
- 클래스가 로드될 때 한 번만 생성됨.
- 모든 객체가 공유하는 변수.
- Heap이 아니라 Method Area에 저장됨.
- 객체를 만들지 않아도 클래스명.변수명 으로 접근 가능.
2. 클래스 메서드
- 클래스에 속하는 메서드.
- 객체 없이 사용 가능.
- 클래스 변수만 사용할 수 있고 인스턴스 변수는 사용할 수 없음.
[Static 사용 시 주의사항]
클래스 변수 사용 시 주의 사항
- Static은 공유가 필요한 곳에 사용해야함
→ 모든 객체가 동일한 이름을 공유하게 됨. 나중에 선언된 이름으로 덮어씌워져 공용으로 활용됨.
Static 메서드에서 인스턴스 변수에 접근.
- Static 메서드에서는 인스턴스 변수에 접근할 수 없음.
- 인스턴스 멤버를 사용하기 위해서는 먼저 객체가 생성되어야 함.
- 객체 없이 사용할 수 없음. 접근도 안됨!!
public class Person {
// 인스턴스 변수
String name;
// static 변수
static int population = 0;
Person(){
population++;
}
// 인스턴스 메서드
void printName(){
System.out.println("나의 이름은 " + this.name + "입니다.");
}
// static 메서드
static void printPopulation() {
Person p3 = new Person();
System.out.println(p3.name);
System.out.println("현재 인구 수 : " + population);
}
}
- Static 메서드에 Person p3 = new Person() 처럼 객체 생성을 해줘야함!!!
‼️Static은 꼭 필요할 때만 사용해야함!!
- Static 변수와 메모리는 프로그램이 종료될 때까지 메모리에 유지됨.
→ Static 변수는 Method Area에 올라가는데
Method Area는 프로그램 시작 시점에 메모리에 탑재되어 종료될 때까지 유지되기 때문.
- 모든 변수의 static을 활용하게 되면 메모리가 많이 필요한 프로그램이 되어버림.
→ 너무 많은 static을 남용하면 메모리 낭비로 이어짐.
'스파르타 내일배움캠프 > TIL(Today I learned)' 카테고리의 다른 글
25.03.05 TIL - 캡슐화, 상속, 추상화 (2) | 2025.03.05 |
---|---|
25.03.04 TIL - final, interface, Lv2. 계산기 과제 (3) | 2025.03.04 |
25.02.27 TIL - 클래스, JVM 메모리, 계산기 과제 (2) | 2025.02.27 |
25.02.26 TIL - 조건문, 반복문, 배열, 메서드 (3) | 2025.02.26 |
25.02.25 TIL - Java 변수, 입출력, 연산자 (4) | 2025.02.25 |