자바(Java) - 클래스와 객체 2

Dec 30, 2023
자바(Java) - 클래스와 객체 2

객체의 생성과 소멸

객체의 소멸과 가비지 컬렉션

자바에는 객체를 생성하는 연산자는 있지만, 객체를 삭제하는 연산자는 없다.
 
객체들은 상당한 메모리를 차지하고 있기 때문에, 사용이 종료된 객체는 삭제해야 한다.
 
💡
자바에서는 자동 메모리 삭제 시스템을 사용하는데 이것을 가비지 컬렉션(garbage collection)이라고 한다.

인수 전달 방법

기초형 값이 전달되는 경우

💡
전달하는 인수가 int나 double같은 기초형 변수인 경우에는 호출자가 전달하는 인수의 값이 매개 변수로 복사된다.
 
즉 “값에 의한 호출” 방식으로 전달된다.
 
인수의 복사본이 만들어지고 매개 변수를 변경하여도 메소드 외부에 있는 인수에 영향을 주지 않는다.
 
void inc(int a) { a = a + 1; } int x = 10; obj.inc(x); System.out.println(x);
inc() 메소드 안에서 매개 변수 a의 값을 변경하여도 원본 변수 x에는 영향을 주지 않는다.
 
 

객체가 전달되는 경우

💡
객체를 메소드로 전달하게 되면 객체 자체가 복사되어 전달되는 것이 아니고 객체의 참조값만 복사되어서 전달된다.
 
참조 변수는 참조값(주소)을 가지고 있다.
 
참조값이 매개 변수로 복사되면 메소드의 매개 변수도 동일한 객체를 참조하게 된다.
 
따라서 매개 변수를 통하여 객체의 내용을 변경하게 되면 인수가 가리키는 객체도 변경된다.
 
void inc(Pizza c) { c.radius++; } Pizza obj = new Pizza(10); obj.inc(obj); System.out.println(obj.radius);
obj에 저장된 것은 객체가 아니라 객체의 참조값이다.
inc() 안에서 객체를 변경하면 원본 객체도 변경된다.
메소드가 객체를 반환할 때도 객체가 통째로 반환되는 것이 아니라 객체의 참조값만 반환된다.
 
 

배열이 전달되는 경우

💡
배열 원소가 메소드로 전달된다면 이것은 다른 변수들과 다르지 않다.
 
즉 값이 복사되어서 전달된다.
 
그러나 배열 전체가 전달된다면 상황은 달라진다.
 
배열도 객체이기 때문에 배열을 전달하는 것은 배열 참조 변수를 복사하는 것이다.
 
void inc(int[] array) { ... for(int i = 0; i < array.length; i++) { array[i] = array[i] + 1; } } int[] list = {1, 2, 3, 4, 5}; ArrayProc obj = new ArrayProc(); obj.inc(list); ...
자바에서는 배열도 객체이다. 따라서 배열이 전달되는 경우에도 객체가 전달되는 것과 동일하게 처리된다.
 
즉, 배열이 전달되는 것이 아니라 배열을 가리키는 참조값이 복사되고 메소드에서 매개 변수를 통하여 배열을 변경하면 원본 배열이 변경된다.

정적 멤버

💡
프로그램을 작성하다보면 여러 개의 객체가 하나의 변수를 공유해야 되는 경우가 있다.
 
이러한 멤버를 정적 멤버(static member) 또는 클래스 멤버(class member)라고 한다.
 
필드를 정의할 때 앞에 static을 붙이면 정적 멤버가 된다.
 
메소드 앞에 static을 붙이면 정적 메소드가 된다.
 
 

인스턴스 멤버 vs 정적 멤버

💡
프로그램에서도 객체들마다 개별적으로 소유해야 하는 멤버들도 있고, 객체들이 공유하는 멤버도 있다.
 
이제까지의 멤버들은 모두 객체마다 별도로 소유하였다. 이것을 인스턴스 멤버라고 한다.
 
반면에 객체들은 하나의 멤버를 다른 객체와 공유할 수도 있다. 이것을 정적 멤버라고 한다.
 
정적 변수(class variable)클래스당 하나만 생성되는 변수이다.
 
정적 변수를 만들려면 변수를 정의할 때 앞에 static을 붙이면 된다.
 
 

정적 메소드

💡
변수와 마찬가지로 메소드도 정적 메소드로 만들 수 있다.
 
static 수식자를 메소드 앞에 붙여서 만든다.
 
 

정적 변수의 활용

정적 메소드에서는 인스턴스 멤버를 사용하면 안 된다.
정적 메소드에서 정적 메소드를 호출하는 것은 가능하다.
class Test { int a; // 인스턴스 변수 static int b; // 정적 변수 void sub1() { // OK! a = 0; } static void sub2() { // 오류! a = 0; } }
 
다음과 같이 정적 메소드에서 인스턴스 메소드를 호출하는 것은 컴파일 오류가 된다.
main() 메소드정적 메소드임을 잊지말자.
public class Test { public static void main(String args[]) { add(10, 20); // 오류! 정적 메소드 안에서 인스턴스 메소드 호출 } int add(int x, int y) { return x + y; } }
 
이 경우에 add를 정적 메소드로 만들면 컴파일 오류를 막을 수 있다.
public class Test { public static void main(String args[]) { add(10, 20); // 클래스 메소드에서 클래스 메소드는 호출 가능 } static int add(int x, int y) { return x + y; } }
 
정적 메소드this를 사용할 수 없다 - this현재 객체를 가리키는 참조 변수이다.
정적 메소드객체가 없을 때도 호출될 수 있기 때문에 현재 객체라는 개념이 없다.
class Test { static int a; // 인스턴스 변수 static void sub(int x) { this.a = x; // 오류 ! 정적 메소드에서는 this 사용 안 됨 } }
 
 

정적 블록

💡
자바 클래스에서 정적 블록(static block)클래스가 메모리에 로드될 때 한 번만 실행되는 문장들의 집합이다.
 
정적 블록정적 초기화 블록이라고도 한다.
 
일반적으로 정적 변수들을 초기화하는 용도로 많이 사용된다.
 
public class Test { static int number; static String s; static { // 이 부분이 정적 블록입니다. System.out.println("정적 블록이 실행되었습니다."); number = 23; s = "Hello World"; } }
 

정적 블록과 생성자의 차이점

💡
정적 블록클래스가 로드될 때 한 번만 실행되고, 생성자객체가 생성될 때마다 실행된다.
 
이 둘의 주요 차이점은 그들이 실행되는 시점과 횟수, 그리고 그들이 주로 사용되는 용도에 있다.
 
Share article

stwin755