Java - 인스턴스 멤버, 정적 멤버

김민1·2023년 2월 8일
3

Java

목록 보기
2/8

클래스 = 객체의 설계도인데, 클래스 멤버는 당연히 객체에도 포함되어 있어야 함

하지만 이것이 효율적인가?

클래스로부터 객체는 하나가 아니라 여러 개가 만들어질 수 있음

이 경우 클래스 멤버들을 객체마다 모두 가지고 있을 필요가 있는가?

만약 객체마다 필드값이 달라야 한다면 해당 필드는 객체마다 가지고 있는 것이 맞음.

but 객체의 필드값이 모두 같아야 한다면 이 필드를 객체마다 가지고 있을 필요가 있는가?

오히려 이런 필드는 한 곳에 위치시키고 객체들이 공유하는 것이 좋을 수 있음
자바는 이런 경우를 위해 클래스 멤버를 인스턴스 멤버정적 멤버로 구분해서 선언할 수 있도록 함.

인스턴스 멤버 - 객체마다 가지고 있는 멤버
정적 멤버 - 클래스에 위치시키고 객체들이 공유하는 멤버


인스턴스 멤버와 this

인스턴스 멤버

//예시를 위한 인스턴스 멤버 선언

public class Book {
	int page; //필드
	
    void setPrice(int Price)  { ... } //메소드
}

page 필드와 setPrice() 메소드는 인스턴스 멤버이므로 외부 클래스에서 사용하기 위해선
Book 객체를 생성하고 참조 변수(book1, book2)로 접근해야 함

//외부 클래스

Book book1 = new Book();
book1.page = 352;
book1.setPrice(13000);

이렇게 되면 인스턴스 필드 page는 객체마다 존재, 인스턴스 메소드 setPrice()는 메소드영역에 저장,공유 됨

인스턴스 메소드는 객체에 소속된 멤번데 왜 객체 내부에 존재하지않고 메소드 영역에서 저장되고 공유되는가?

메소드는 코드 블록이므로 객체마다 동일한 코드블록을 가지고 있을 필요가 X

인스턴스라는 용어가 붙는 이유는?

메소드 블록 내부에 인스턴스 필드 등이 사용되는 경우가 있기 때문.
인스턴스 필드가 사용되면 메소드 또한 객체 없이 실행할 수 없음

this

객체 외부에서 인스턴스 멤버에 접근하기 위해 참조 변수를 사용하는 것과 마찬가지로 객체 내부에서도 인스턴스 멤버에 접근하기 위해 this를 사용할 수 있음

ex) book1.page -> this.page
여기서 this.page는 자신이 가지고 있는 page 필드라는 뜻임.

사용하는 이유?

주로 생성자와 메소드의 매개 변수 이름이 필드와 동일할 경우, 인스턴스 멤버인 필드임을 명시하고자 사용


정적 멤버와 static

static은 '고정된'이라는 의미임. 의미대로 정적 멤버는 클래스에 고정된 멤버를 뜻함.
-> 객체를 생성하지않고 사용할 수 있는 필드와 메소드(정적 필드와 정적 메소드)

선언하는 방법은 인스턴스 멤버 앞에 static 붙이면 되니까 생략.

정적 필드와 정적 메소드는 클래스에 고정된 멤버 -> 클래스 로더가 클래스를 로딩해서 메소드 메모리 영역에 적재할 때 클래스별로 관리됨. -> 클래스의 로딩이 끝나면 바로 사용가능

정적 메소드 선언 시 주의할 점

객체가 없어도 실행된다는 특징 때문에 이들 내부에 인스턴스 필드나 인스턴스 메소드를 사용할 수 없음.
또한 객체 자신의 참조인 this 키워드도 사용 불가
정적 메소드에서 인스턴스 멤버를 사용하고 싶다면 객체를 먼저 생성하고 참조 변수로 접근해야함


인스턴스 멤버? 정적 멤버?

필드를 선언할 때는 인스턴스 필드로 선언할 것인가
정적 필드로 선언할 것인가의 판단 기준이 필요함

객체마다 가지고 있어야 할 데이터라면 인스턴스 필드로 선언
객체마다 가지고 있을 필요가 없는 공용 데이터라면 정적 멤버로 선언

메소드 또한 인스턴스 메소드로 선언할 것인가
정적 메소드로 선언할 것인가의 판단 기준이 필요함

인스턴스 필드를 포함하고 있다면 인스턴스 메소드로 선언
인스턴스 필드를 포함하고 있지 않다면 정적 메소드로 선언


싱글톤(Singleton)

가끔 전체 프로그램에서 단 하나의 객체만 만들도록 보장해야 하는 경우가 있는데
단 하나만 생성된다고 해서 이 객체를 싱글톤이라고 함

싱글톤을 만들려면?

  1. 클래스 외부에서 new 연산자로 생성자를 호출할 수 없도록 막아야 함
    (생성자를 호출한 만큼 객체가 생성되기 때문)
    생성자를 외부에서 호출할 수 없도록 하려면 생성자 앞에 private 접근 제한자를 붙여주면 됨

  2. 자신의 타입인 정적 필드를 하나 선언하고 자신의 객체를 생성해 초기화
    (클래스 내부에서는 new 연산자로 생성자 호출이 가능)

  3. 외부에서 호출할 수 있는 정적 메소드인 getInstance()를 선언하고 정적 필드에서 참조하고 있는 자신의 객체를 리턴

//예시

public class 클래스 {

	private static 클래스 singleton = new 클래스();
    
    private 클래스 () {}
    
    static 클래스 getInstance() {
    	return singleton;
    }
}

final 필드와 상수

final 필드

final은 '최종적'이라는 의미임. 의미대로 final 필드는 최종적인 필드란 뜻인데,
final 필드는 초기값이 저장되면 이것이 최종적인 값이 되어 프로그램 실행 도중에 수정할 수 없다는 것. 약간 C에서 #define과 비슷한 느낌이 없지않아 있다.

final 필드 선언

final 타입 필드 [= 초기값];
//저장된 초기값이 최종값, 즉 수정할 수 없음

final 필드의 초기값을 주는 방법은 두 가지가 있음
1. 필드 선언 시에 주는 방법
2. 생성자에서 주는 방법

단순 값이라면 필드 선언 시에 주는 것이 제일 간단함
but 복잡한 초기화 코드가 필요하거나 객체 생성 시에 외부 데이터로 초기화 해야 한다면
생성자에서 초기값을 지정해야 함

또한 생성자는 final 필드의 최종 초기화를 마쳐야 하는데,
만약 초기화되지 않은 final 필드를 그대로 남겨두면 컴파일 에러 발생

상수

일반적으로 불변의 값을 상수(static final)라고 부름.
불변의 값은 수학의 파이(π)나 지구의 둘레등이 해당됨
이런 불변의 값을 저장하는 필드를 자바에서는 상수(constant)라고 함

상수와 final의 차이점

불변의 값은 객체마다 저장할 필요가 없는 공용성을 띠고 있으며 여러 가지 값으로 초기화 될 수 없음
final 필드는 객체마다 저장되고 생성자의 매개값을 통해 여러 가지 값을 가질 수 있음

객체마다 저장할 필요가 없는 공용성을 띤다 -> static이면서 final이어야 함
static final 필드는 객체마다 존재하지 않고 클래스에만 존재하고 한 번 초기값이 저장되면 변경 X


마치며

접근제한자에 관한 내용은 추후에 게시할 예정입니다.
수정할 사항이 있으면 댓글이나 이메일로 연락주세요.

profile
https://kimmin1kk.github.io/ 로 블로그 옮겼습니다

1개의 댓글

comment-user-thumbnail
2023년 2월 8일

👍👍

답글 달기