이롭게 현명하게
[JAVA] 자바 정적 멤버와 static 본문
목차
정적 멤버 선언
정적 초기화 블록
정적 메소드와 블록 선언 시 주의할 점
싱글톤
<정리>
[non-static 멤버(인스턴스 멤버)]
- 공간적 특성 : 멤버들은 객체마다 독립적으로 별도 존재
- 시간적 특성 : 필드와 멤소드는 객체 생성 후 비로소 사용 가능 (new 연산자 사용)
- 비공유 특성 : 멤버들은 다른 객체에 의해 공유되지 않음
[static 멤버(클래스 멤버,정적 멤버)]
- 객체마다 생기는 것이 아님
- 클래스당 하나만 생성됨
- 객체를 생성하지 않고 사용 가능
- 공간적 특성 : static 멤버들은 클래스 당 하나만 생성
- 시간적 특성 : static멤버들은 클래스가 로딩될 때 공간 할당
- 공유의 특성 : static 멤버들은 해당 클래스의 모든 객체에 의해 공유
[static의 활용]
1. 전역 변수와 전역 함수를 만들 때 활용
- 전역변수나 전역 함수는 static으로 클래스에 작성
2. 공유 멤버를 작성할 때 static 필드나 메소드는 하나만 생성. 클래스의 객체들에 의해 공유됨
[static 메소드의 제약 조건]
1. static 메소드는 non-static 멤버에 접근할 수 없다.
- 객체가 생성되지 않은 상황에서도 static 메소드는 실행될 수 있기 때문에 non-static 메소드와 필드 사용 불가
- non-static 메소드는 static 멤버 사용 가능
2. static 메소드는 this 사용 불가
- static 메소드는 객체가 생성되지 않은 상황에서도 호출이 가능하므로 , 현재 객체를 가리키는 this 레퍼런스를 사용할 수 없다.
[정적 멤버 선언]
정적 멤버 : 클래스에 고정된 멤버로서 객체를생성하지 않고 사용할 수 있는 필드와 메소드를 말한다.
객체(인스턴스)에 소속된 멤버가 아니라 클래스에 소속된 멤버이기 때문에 클래스 멤버라고도한다.
public class 클래스명{
// 정적 필드
static 데이터타입 필드 = 초기값;
// 정적 메소드
static 리턴타입 메소드명(매개변수선언,..){ ... }
}
<정적 필드로 선언할 것인가의 판단 기준>
객체마다 가지고 있어야 할 데이터 : 인스턴스 필드
객체마다 가지고 있을 필요성이 없는 공용적인 데이터 : 정적 필드
public class Calculator{
String color; //계산기 마다 색이 다를 수 있다.
static double pi = 3.14;// 계산기에서 사용하는 파이값은 동일하다.
}
Calculator 객체마다 pi값은 각 객체마다 가지고 있을 필요가 없는 변하지 않는 공용적인 데이터이므로 정적 필드로 선언하는 것이 좋다.
하지만 객체별로 색이 다르다면 색은 인스턴스 필드로 선언해야 한다.
<정적 메소드로 선언할 것인가의 판단 기준>
인스턴스 필드를 이용해서 실행해야 할 때 : 인스턴스 메소드
인스턴스 필드를 이용하지 않을 때 : 정적 메소드
// Calculator.java
public class Calculator {
String color; //인스턴스 필드
static double pi = 3.14;
void setColor(String color) { //인스턴스 메소드
this.color = color;
}
static int plus(int x,int y) { //정적 메소드
return x+y;
}
static int minus(int x,int y) { //정적 메소드
return x-y;
}
}
// Main.java
public class Main {
public static void main(String[] args) {
double result1 = 10*10*Calculator.pi;
int result2 = Calculator.plus(10, 5);
int result3 = Calculator.plus(10, 5);
System.out.println(result1);
System.out.println(result2);
System.out.println(result3);
}
}
[정적 초기화 블록]
인스턴스 필드는 생성자에서 초기화하지만, 정적 필드는 객체 생성 없이도 사용해야 하므로 생성자에서 초기화 작업을 할 수 없다.
생성자는 객체 생성 시에만 실행되기 때문이다.
자바는 정적 필드의 복잡한 초기화 작업을 위해 정적 블록을 제공한다.
정적 블록은 클래스가 메모리로 로딩될 때 자동적으로 실행된다.
정적 블록은 클래스 내부에 여러 개가 선언되어도 상관없다.
클래스가 메모리로 로딩될 때 선언된 순서대로 실행된다.
// Car.java
public class Car {
static String company = "Samsung";
static String model = "LCD";
static String info;
static {
info = company+'-'+model;
}
}
// Main.java
public class Main {
public static void main(String[] args) {
System.out.println(Car.info);
}
}
<정적 메소드와 블록 선언시 주의할 점>
정적 메소드와 정적 블록은 객체가 없어도 실행된다는 특징 때문에 내부에 인스턴스 필드나 인스턴스 메소드를사용할 수 없다.
또한 객체 자신의 참조인 this 키워드도 사용이 불가능하다.
// ClassName.java
public class ClassName {
// 인스턴스 필드와 메소드
int field1;
void method1(){ ... }
// 정적 필드와 메소드
static int field2;
static void method2() { ,,, }
// 정적 블록
static {
field1 = 10; // 컴파일 에러
method1(); //컴파일 에러
field2 = 10;
method2();
}
static void Method3 {
this.field1 = 10; //컴파일 에러
this.method1(); //컴파일 에러
field2 = 10;
method2();
}
}
정적 메소드와 정적 블록에서 인스턴스 멤버를 사용하고 싶다면 객체를 먼저 생성하고 참조변수로 접근해야 한다.
static void Method3(){
ClassName obj = new ClassName();
obj.field1 = 10;
obj.method1();
}
[싱글톤]
싱글톤(Singleton) : 프로그램에서 단 하나의 객체만 만들도록 보장해야 하는 경우 단 하나만 생성된 객체
클래스 외부에서 new 연산자로 생성자를 호출할 수 없도록 막아야 한다.
생성자를 호출한 만큼 객체가 생성되기 때문이다.
생성자를 외부에서 호출할 수 없도록 생성자 앞에 private 접근제한자를 붙여주면 된다.
private : 외부에서 생성자 호출을 막는다.
정적 필드도 private 접근 제한자를 붙여 외부에서 필드 값을 변경하지 못하도록 막는다.
public class 클래스{
//정적 필드
private static 클래스 singleton = new 클래스();
// 생성자
private 클래스(){}
// 정적 메소드
static 클래스 getInstance(){
return singleton;
}
}
getInstance() : 외부에서 객체를 얻는 유일한 방법
getInstance()메소드는 단 하나의 객체만 리턴하기 때문에 변수1과 변수2는 동일한 객체를 참조한다.
클래스 변수1 = 클래스.getInstance();
클래스 변수2 = 클래스.getInstance();
잘못된 정보는 댓글에 남겨주시면 감사하겠습니다!😊
댓글과 좋아요는 큰 힘이 됩니다!
[ 참고자료 ]
'JAVA' 카테고리의 다른 글
[JAVA] 자바 패키지 (0) | 2023.04.24 |
---|---|
[JAVA] 자바 final 필드와 상수 (0) | 2023.04.21 |
[JAVA] 자바 인스턴스 멤버와 this (0) | 2023.04.19 |
[JAVA] 자바 클래스 메소드 (0) | 2023.04.18 |
[JAVA] 자바 클래스 생성 (0) | 2023.04.14 |