728x90
용어정리
- 인스턴스 멤버 : 객체를 생성한 후 사용할 수 있는 필드와 메소드(인스턴스 필드와 인스턴스 메소드)
- this : 객체 내부에서도 인스턴스 멤버에 접근하기 위해 this를 사용할 수 있다.
- 주로 생성자와 메소드의 매개변수 이름이 필드와 동일한 경우, 인스턴스 멤버인 필드임을 명시하기 위해 사용
- 정적 멤버 : 클래스에 고정된 멤버로서 객체를 생성하지 않고 사용할 수 있는 필드와 메소드
- static : 정적 멤버를 선언할 때마다 사용하는 키워드
- 싱글톤 : 전체 프로그램에서 단 하나의 객체만 만들도록 보장해야 하는 경우 사용하는 코드 패턴
- final 필드 : 초기값이 저장되면 이것이 최종값이 되어 프로그램 실행 도중 수정할 수 없는 필드
- 상수 : 불변의 값을 저장하는 정적 필드, final static 키워드로 선언
인스턴스 멤버
- 객체 마다 가지고 있는 멤버
- 인스턴스 필드 : 힙 영역의 객체 마다 가지고 있는 멤버, 객체마다 다른 데이터를 저장
- 인스턴스 메소드 : 객체가 있어야 호출 가능한 메소드, 클래스 코드(메소드 영역)에 위치하지만, 이해하기 쉽도록 객체 마다 가지고 있는 메소드라고 생각해도 된다.
정적 멤버
- 객체와 상관없이 클래스당 하나씩 생기는 멤버 -> 동일한 클래스의 모든 객체들에 의해 공유
- 정적 필드 및 상수 : 객체 없이 클래스만으로도 사용 가능한 필드
- 정적 메소드 : 객체가 없이 클래스만으로도 호출 가능한 메소드
인스턴스 멤버
객체를 생성한 후 사용할 수 있는 필드와 메소드
// 클래스 파일
public class Car{
// 필드
int gas;
// 메소드
void setSpeed(int speed){
}
}
// 메인 파일
Car myCar = new Car(); // 객체 생성
myCar.gas = 10; // 인스턴스 필드 사용
myCar.setSpeed(60) // 인스턴스 메소드 사용
정적 멤버와 static
- 클래스에 고정된 멤버로서 객체 생성하지 않고, 사용할 수 있는 필드와 메소드
- static과 함께 선언
- 메인 실행 파일에서 객체 생성 없이 도트연산자로 접근하여 사용
인스턴스 필드가 있는 클래스의 객체를 생성하면 객체마다 인스턴스 필드에 새로운 메모리를 할당한다. 하지만 static 즉 정적 필드의 경우 클래스 자체에 붙어있는 것으로 아무리 객체를 많이 생성하더라도 메모리는 한 번만 할당된다. 즉, 정적 필드의 경우 해당 클래스의 모든 객체는 단 하나의 메모리를 참조하고 있는 것이다.
// 기본
// 클래스 파일
public class 클래스명{
// 정적 필드
static 타입 변수명;
// 정적 메소드
static 리턴타입 메소드명(매개변수,...){
}
}
// 예시
// 클래스 파일
public class Calculator{
static double pi = 3.14;
static int plus (int x, int y){
}
}
// 메인 파일
double result = 10 * 10 * Calculator.pi; // 객체 생성 없이 사용 가능
int result2 = Calculator.plus(10,5); // // 객체 생성 없이 사용 가능
static 활용
자바에는 어떤 변수나 함수도 클래스 바깥에 존재할 수가 없다. 자바의 캡슐화 원칙 때문이다. 따라서 모든 클래스에서 공유하는 전역 변수, 전역 함수에 대한 선언은 static을 이용한다.
public class Math{
public static int INF = (int)1e9;
public static int abs(int a);
}
// main에서 호출
Math.INF
Math.abs(5)
주의점
static 메서드는 객체 없이도 존재하기 때문에 this 사용이 불가능하고 static 멤버에만 접근할 수 있다. 이러한 문제는 static메서드, 필드가 객체 없이도 사용할 수가 있어야만 하기 때문에 생기는 문제다.
멤버 선택 기준
- 객체마다 다를 수 있는 필드값 -> 인스턴스 필드로 선언
- 객체마다 다를 필요 없는 값 -> 정적 필드로 선언
- 메소드 블록에 인스턴스 필드 또는 인스턴스 메소드를 사용할 경우 -> 인스턴스 메소드로 선언
- 메소드 블록에 인스턴스 멤버(필드,메소드)를 사용하지 않을 경우(매개인자, 메소드내 변수만 사용) -> 정적 메소드로 선언
정적 메소드 선언 시 주의점
- 정적 메소드 선언 시 그 내부에 인스턴스 필드 및 메소드 사용 불가
- 정적 메소드 선언 시 그 객체 자신 참조인 this 키워드 사용 불가
- 정적 메소드에서 인스턴스 멤버를 사용하려는 경우 -> 객체 우선 생성 후 참조 변수로 접근
public class ClassName{
// 인스턴스 필드와 메소드
int field1;
void method1(){
}
// 정적 필드와 메소드
static int field2;
static void method2(){
}
// 정적 메소드
static void method3{
this.field1 =10; // 컴파일 에러
this.method1(); // 컴파일 에러
field2=10; // 가능
method2(); // 가능
}
// 정적 메소드에서 인스턴스 멤버 사용
static void method3(){
ClassName obj = new ClassName(); // 객체 우선 생성
obj.field1 = 10; // 도트연산자로 접근해서 사용
obj.method1();
}
}
싱글톤
- 전체 프로그램에서 단 하나의 객체만 만들도록 보장하는 코딩 기법
- 작성법
- 클래스 외부에서 new 연산자를 통해 생성자를 호출하는 것을 불가하도록 private 접근 제한자 사용
- 자신의 타입인 정적 필드를 선언한 후 자신의 객체를 생성해 초기화
- 외부에서 호출할 수 있는 getInstance() 선언
- 정적 필드에서 참조하는 자신의 객체 리턴
- 정리하자면, 싱글톤은 단 하나의 객체만 만들도록 하는 기법이므로 해당 클래스 파일에서 생성자는 private으로 해주고 정적 필드에 해당 생성자를 이용하여 객체를 만든다. 그러면 이제 객체는 단 하나만 있는 상황이다. 이때 외부에서 이 객체를 호출할 수 있도록 정적 메소드 getInstance를 선언하여 리턴값으로 해당 객체를 준다. 결과적으로 해당 클래스에 해당하는 객체는 단 하나가 되는 것이다.
// 클래스 파일
public class 클래스명{
// 정적 필드
// 자기 자신의 타입의 필드를 정적으로 선언하고 자기 자신의 객체를 생성
// class 내부에서는 private으로 선언된 생성자를 이용해서 객체를 만들 수 있다. 밖에서 못 만든다는 것 기억
private static 클래스명 변수명 = new 클래스명();
// 생성자
private 클래스() {
}
// 정적 메소드
// 외부에서 호출할 수 있어야하므로 private을 붙이면 안됨
// 자기 자신의 타입을 리턴타입으로 설정
static 클래스명 getInstance(){
return 변수명 // 자기 자신의 타입을 리턴해야하므로 위에 선언한 필드를 리턴
}
}
// 메인 실행 파일
클래스명 변수1 = 클래스.getInstance();
클래스명 변수2 = 클래스.getInstance();
단 하나의 객체만 존재하므로 결국 같은 곳을 참조한다.
final 필드와 상수
- 초기값이 저장되면 최종값이 되어 프로그램 실행 도중 수정이 불가능한 필드
- final 필드의 초기값 주는 방법
- 단순 값일 경우 필드 선언 시 초기화(주로 정적 필드(상수)일 경우)
- 객체 생성 시 외부 데이터로 초기화 필요한 경우 생성자에서 초기화(주로 인스턴스 필드일 경우)
- 인스턴스 final 필드
- 객체에 한 번 초기화된 데이터를 변경 불가로 만들 경우 ex) 주민번호
- final 타입 필드; // 주민번호 같은 경우 사람마다 다르므로 생성자에서 초기화
- 정적 final 필드
- static final로 선언된 필드는 대부분 상수이기 때문에 불변의 상수값을 저장하는 변수명은 관례적으로 대문자
- 불변의 값인 상수를 만들 경우 ex) PI
- static final 타입 상수(변수명) = 초기값;
// 예시 1
// 클래스 파일
public class Person {
final String nation = "korean";
final String ssn;
final String name;
Person(String ssn,String name){
this.ssn = ssn;
this.name = name;
}
}
// 메인 실행 클래스
Person p1 = new Person("123-456","hong");
System.out.println(p1.nation);
System.out.println(p1.ssn);
p1.nation = "USA" // 컴파일에러(final)
// 예시 2
// 클래스 파일
public class Earth {
static final double EARTH_RADIUS = 6400;
static final double EARTH_AREA = 4 * Math.PI*EARTH_RADIUS*EARTH_RADIUS;
}
// 메인 실행 클래스
public static void main(String[] arg) {
System.out.println("지구의 반지름: "+ Earth.EARTH_RADIUS + " KM");
System.out.println("지구의 표면적: "+ Earth.EARTH_AREA + " KM^2");
}
728x90
'👨🏫Study > JAVA' 카테고리의 다른 글
[JAVA] 07 - 1 상속 (0) | 2021.08.11 |
---|---|
[JAVA] 06 - 6 패키지와 접근 제한자 (0) | 2021.08.06 |
[JAVA] 06 - 4 메소드 (0) | 2021.08.06 |
[JAVA] 06 - 1 객체 지향 프로그래밍, 06 - 2 필드, 06 - 3 생성자 (0) | 2021.08.05 |
[JAVA] 05 참조 타입 (0) | 2021.08.04 |
댓글