인스턴스 멤버, 정적 멤버
1. 용어정리
- 인스턴스 멤버 : 객체를 생성한 후 사용할 수 있는 필드와 메서드 (인스턴스 필드와 인스턴스 메서드)
- this : 객체 내부에서도 인스턴스 멤버에 접근하기 위해 this를 사용할 수 있습니다.
- 주로 생성자와 메서드의 매개변수 이름이 필드와 동일한 경우, 인스턴스 멤버인 필드임을 명시하기 위해 사용합니다.
- 정적 멤버 : 클래스에 고정된 멤버로서 객체를 생성하지 않고 사용할 수 있는 필드와 메서드입니다.
- static : 정적 멤버를 선언할 때마다 사용하는 키워드입니다.
- 싱글톤 : 전체 프로그램에서 단 하나의 객체만 만들도록 보장해야 하는 경우 사용하는 코드 패턴입니다.
- final 필드 : 초기값이 저장되면 이것이 최종값이 되어 프로그램 실행 도중 수정할 수 없는 필드입니다.
- 상수 : 불변의 값을 저장하는 정적 필드, final static 키워드로 선언입니다.
2. 인스턴스 멤버와 정적 멤버
- 인스턴스 멤버 : 객체마다 가지고 있는 멤버
- 인스턴스 필드 : 힙 영역의 객체마다 가지고 있는 멤버, 객체마다 다른 데이터를 저장합니다.
- 인스턴스 메서드 : 객체가 있어야 호출 가능한 메서드, 클래스 코드(메서드 영역)에 위치하지만, 이해하기 쉽도록 객체마다 가지고 있는 메서드라고 생각해도 됩니다.
- 정적 멤버 : 객체와 상관없이 클래스당 하나씩 생기는 멤버입니다. -> 동일한 클래스의 모든 객체들에 의해 공유됩니다.
- 정적 필드 및 상수 : 객체 없이 클래스만으로도 사용 가능한 필드입니다.
- 정적 메서드 : 객체 없이 클래스만으로도 호출 가능한 메서드입니다.
3. 인스턴스 멤버 및 정적 멤버와 static 실습
- 인스턴스 멤버 : 객체를 생성한 후 사용할 수 있는 필드와 메서드
-
// 인스턴스 멤버 예시 public class Member { // 필드 int InstanceMember; // 메서드 String setInstanceMember (String instanceMember) { return instanceMember; } } public class Main { public static void main(String[] args) { Member member = new Member(); System.out.println(member.InstanceMember = 10); System.out.println(member.setInstanceMember("인스턴스 멤버")); } } // 출력 : 10 // 출력 : 인스턴스 멤버
-
- 정적 멤버와 static
- 클래스에 고정된 멤버로서 객체 생성하지 않고, 사용할 수 있는 필드와 메서드입니다.
- static과 함께 선언합니다.
- 메인 실행 파일에서 객체 생성 없이 도트연산자로 접근하여 사용합니다.
- 인스턴스 필드가 있는 클래스의 객체를 생성하면 객체마다 인스턴스 필드에 새로운 메모리를 할당합니다.
하지만 static 정적 필드의 경우 클래스 자체에 붙어 있는 것으로 아무리 객체를 많이 생성하더라도 메모리는 한 번만 할당됩니다.
즉, 정적 필드의 경우 해당 클래스의 모든 객체는 단 하나의 메모리를 참조하고 있는 것입니다. - static 메서드는 객체 없이도 존재하기 때문에 this 사용이 불가능하고 static 멤버에만 접근할 수 있습니다.
이러한 문제는 static 메서드, 필드가 객체 없이도 사용할 수 있어야만 하기 때문에 생기는 문제입니다. -
// 정적 (static) 멤버 public class Member { // 정적 필드 static int staticMember; // 정적 메서드 static String setStaticMember (String staticMember) { return staticMember; } } public class Main { public static void main(String[] args) { System.out.println(Member.staticMember = 100); System.out.println(Member.setStaticMember("정적 멤버")); } } // 출력 : 100 // 출력 : 정적 멤버
4. 멤버 선택 기준
- 객체마다 다를 수 있는 필드값 -> 인스턴스 필드로 선언합니다.
- 객체마다 다른 필요 없는 값 -> 정적 필드로 선언합니다.
- 메서드 블록에 인스턴스 필드 또는 인스턴스 메서드를 사용할 경우 -> 인스턴스 메서드로 선언합니다.
- 메서드 블록에 인스턴스 멤버 (필드, 메서드)를 사용하지 않을 경우 (매개변수, 메서드 내 변수만 사용) -> 정적 메서드로 선언합니다.
5. 정적 메서드 선언 시 주의점
- 정적 메서드 선언 시 그 내부에 인스턴스 필드 및 메서드 사용 불가합니다.
- 정적 메서드 선언 시 그 객체 자신 참조인 this 키워드 사용 불가합니다.
- 정적 메서드에서 인스턴스 멤버를 사용하려는 경우 -> 객체 우선 생성 후 참조 변수로 접근합니다.
-
public class Member { static class InstanceClass { // 인스턴스 필드와 메서드 int instanceMember; void instaceMethod() {} } // 정적 필드와 메서드 static int staticMember; static void staticMethod() { } // 정적 메서드 static void Method1 () { // this.instanceMember = 10; // 컴파일 에러 // this.instaceMethod(); // 컴파일 에러 staticMember = 10; // 가능 staticMethod(); // 가능 } // 정적 메서드에서 인스턴스 멤버 사용 static void Method () { InstanceClass instanceClass = new InstanceClass(); instanceClass.instanceMember = 10; instanceClass.instaceMethod(); } }
-
6. 싱글톤
- 전체 프로그램에서 단 하나의 객체만 만들도록 보장하는 코딩 기법
- 작성법
- 클래스 외부에서 new 연산자를 통해 생성자를 호출하는 것을 불가하도록 private 접근 제어자 사용합니다.
- 자신의 타입인 정적 필드를 선언한 후 자신의 객체를 생성해 초기화합니다.
- 외부에서 호출할 수 있는 getInstance() 선언합니다.
- 정적 필드에서 참조하는 자신의 객체를 리턴합니다.
- 정리하자면, 싱글톤은 단 하나의 객체만 만들도록 하는 기법이므로 해당 클래스 파일에서 생성자는 private으로 해주고 정적 필드에 해당 생성자를 이용하여 객체를 만듭니다. 그러면 이제 객체는 단 하나만 있는 상황입니다.
이때 외부에서 이 객체를 호출할 수 있도록 정적 메서드 getInstance를 선언하여 리턴값으로 해당 객체를 줍니다. 결과적으로 해당 클래스에 해당하는 객체는 단 하나가 되는 것입니다.-
// 클래스 파일 public class SingletonClass { // 정적 필드 // 자기 자신의 타입의 필드를 정적으로 선언하고 자기 자신의 객체를 생성합니다. // class 내부에서는 private으로 선언된 생성자를 이용해서 객체를 만들 수 있습니다. private static final SingletonClass singletonClass = new SingletonClass(); // 생성자 private SingletonClass () { } // 정적 메서드 // 외부에서 호출할 수 있어야 하므로 private을 붙이면 안됩니다. // 자기 자신의 타입을 리턴타입으로 설정합니다. static SingletonClass getInstance() { return singletonClass; // 자기 자신의 타입을 리턴해야 하므로 위에 선언한 필드를 리턴합니다ㅣ. } } public class SingletonMain { public static void main(String[] args) { SingletonClass singletonClass = SingletonClass.getInstance(); } }
-
- 단 하나의 객체만 존재하므로 결국 같은 곳을 참조합니다.
- 작성법
7. final 필드와 상수
- 초기값이 저장되면 최종값이 되어 프로그램 실행 도중 수정이 불가능한 필드입니다.
- final 필드의 초기값 주는 방법
- 단순 값일 경우 필드 선언 시 초기화합니다. (주로 정적 필드 (상수)일 경우)
- 객체 생성 시 외부 데이터로 초기화 필요한 경우 생성자에서 초기화합니다. (주로 인스턴스 필드일 경우)
- 인스턴스 final 필드
- 객체에 한번 초기화된 데이터를 변경 불가로 만들 경우
- final 타입 필드;
- 정적 final 필드
- static final로 선언된 필드는 대부분 상수이기 때문에 불변의 상수 값을 저장하는 변수명은 관례적으로 대문자입니다.
- 불변의 값인 상수를 만들 경우
- static final 타입 상수 (변수명) = 초기값;
-
public class FinalClass { final String nation = "Korean"; final String phone; final String name; FinalClass(String phone, String name) { this.phone = phone; this.name = name; } } public class FinalClass2 { static final double EARTH_RADIUS = 6400; static final double EARTH_AREA = 4 * Math.PI * EARTH_RADIUS * EARTH_RADIUS; } public class FinalMain { public static void main(String[] args) { FinalClass finalClass = new FinalClass("010-1234-5678", "namji"); System.out.println(finalClass.nation); System.out.println(finalClass.phone); System.out.println(finalClass.nation); System.out.println(finalClass.nation + " : " + finalClass.name + ", " + finalClass.phone); // finalClass.nation = "USA" // 컴파일 에러 (final) // 출력 : Korean // 출력 : 010-1234-5678 // 출력 : namji // 출력 : Korean // 출력 : Korean : namji, 010-1234-5678 System.out.println("지구의 반지름 : " + FinalClass2.EARTH_RADIUS + "KM"); System.out.println("지구의 표면적 : " + FinalClass2.EARTH_AREA + "KM^2"); // 출력 : 지구의 반지름 : 6400.0KM // 출력 : 지구의 표면적 : 5.147185403641517E8KM^2 } }
'JAVA' 카테고리의 다른 글
[JAVA] - 진법 변환 정리 (0) | 2024.02.18 |
---|---|
[JAVA] - Object (equals, toString) 클래스 (0) | 2024.02.14 |
[JAVA] - 메서드란 (method) (0) | 2024.01.31 |
[JAVA] - 필드란 (Field) (0) | 2024.01.31 |
[JAVA] - 추상화 / 캡슐화 / 상속 / 다형성 (0) | 2024.01.30 |