백엔드 수업 #06 클래스 - 10.정적 멤버와 static

sookyoung.k·2022년 11월 22일
0

정적(static): '고정된' 이라는 뜻으로 클래스에 고정된 멤버로서 객체를 생성하지 않고 사용할 수 있는 필드와 메소드를 말한다.

  • 정적 필드, 정적 메소드
  • 정적 멤버는 객체(인스턴스)에 소속된 멤버가 아니라 클래스에 소속된 멤버이다. (= 클래스 멤버)
  • static이 붙으면 static 영역에 따로 저장된다. 클래스 안에 있지만 클래스에 귀속된 것이 아님!
  • 클래스 안에 있지만 여기저기에서 가져다 쓸 수 있다는 점이 가장 큰 특징!

정적 멤버 선언

static 키워드만 붙여주면 된다!

  • 인스턴스 필드로 선언할 때: 객체마다 가지고 있어야 할 데이터 일 때

  • 정적 필드로 선언할 때: 객체마다 가지고 있어야 할 필요성이 없는 공용적인 데이터일 때

  • 인스턴스 메소드를 사용할 때: 인스턴스 필드를 이용해서 실행해야 할 때

  • 정적 메소드를 사용할 때: 인스턴스 필드를 이용하지 않을 때

★static은 인스턴스에 접근이 불가하다!

  • 인스턴스 멤버는 내가 생성한 인스턴스를 통해서만 접근할 수 있다.
  • 정적 멤버는 인스턴스(객체)를 생성하지 않아도 클래스를 통해서 접근할 수 있는 것이 장점.

정적 멤버 사용

클래스 이름과 함께 도트(.) 연산자로 접근

public class Calculator2 { 
	// 정적 필드 선언 (static 데이터타입 변수명)
	static double pi = 3.13159; 
    
    // 정적 메소드 선언 (static 데이터타입 (매개 변수)
	static int plus(int x, int y) {
		return x + y;
	}
	static int minus(int x, int y) {
		return x - y;
	}
}
public class Calculator2EX {

	public static void main(String[] args) {
    	// 정적 메소드 호출 (클래스 이름.변수명) 
		double result1 = 10 * 10 * Calculator.pi; 
        int result2 = Calculator.plus(10, 5);
        int result3 = Calculator.minus(10, 5);

		System.out.println(result1); // 314.159
        System.out.println(result2); // 15
        System.out.println(result3); // 5
	}

}

원칙적으로는 클래스이름으로 접근하는 것이 맞지만 아래처럼 객체 참조 변수로도 접근이 가능하다. 하지만 클래스 이름으로 접근하는 것이 좋음!
(인스턴스 멤버는 무조건 객체를 통해서만 접근이 가능하다! 주의!)

public class Car2 {
	// ★ 메모리 구조 !!!! static은 instance 접근 불가 !!! 이거 두 개 중요 !!!!!!!
	// 인스턴스 필드	
	int speed;
	
	// 인스턴스 메소드
	void run() { 
		System.out.println(this.speed + "으로 달립니다.");
	}
	
	void run2() { 
		this.run(); // 인스턴스 메소드는 메소드 간에도 호출 가능 
		System.out.println(this.speed + "으로 달립니다."); 
	}
	
	/*
	static { // static에는 인스턴스에 관련된 모든 것 필드/메소드 모두 접근이 불가능하다! 
		this.speed = 200; // 에러. 
  		this.run();
	}
	*/
	
	// 정적(static) 메소드 
	static void simulate() {
//		this.speed = 200; 
//		this.run(); 
// 		정적 메소드는 인스턴스 접근 불가. 아래 방식과 같이 객체를 따로 생성해서 접근해야 한다. 
		
		Car2 myCar = new Car2();
		// myCar에 Car2라는 객체가 들어온 것임 (simulate 메소드는 myCar라는 객체 생성) 
		
		myCar.speed = 200; // 객체 참조 변수를 통해서 인스턴스 필드에 접근 가능해짐!
		myCar.run();
	}
	
	public static void main(String[] args) { // 실행 메소드 
		simulate(); 
		
		Car2 myCar = new Car2(); // 위의 객체와 변수명은 같지만 다른 객체임. (출력 결과 다름)
		
		myCar.speed = 60;
		myCar.run();
		
	}
}

[출력 결과]
200으로 달립니다.
60으로 달립니다.

정적 초기화 블록

정적 필드는 필드 선언과 동시에 초기값을 주는 것이 보통이다.

정적 필드는 객체 없이도 사용해야 하기 때문에 생성자에서 초기화 작업이 불가하다. (객체가 없기 때문에 생성자 실행 x) 때문에 정적 필드 초기화는 정적 블록을 통해서 해야 한다.

public class Television { 
	// static 필드
	static String company = "Samsung";
	static String model = "1";
	static String info;	
	
	// static 블록: static 필드에 대한 초기화 작업이 필요할 때 사용 
	static { // 정적 블록에 대한 초기화 작업 
		info = company + "_" + number; // 요청 수행 (인포에 이름을 넣어달라!): calc_1 ( 이 값이 info에 들어감)
	}

public class TelevisionEx {

	public static void main(String[] args) {
		System.out.println(Television.info);
	}

}

[출력 결과]
Samsung-LCD

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

객체가 없어도 실행이 되기 때문에 이들 내부에는 인스턴스 필드나 인스턴스 메소드를 사용할 수 없다. 당연히 객체가 자신을 참조하는 this 키워드도 사용이 불가하다.
정적 메소드와 정적 블록에서 인스턴스 멤버를 사용하고 싶다면 객체를 먼저 생성하고 참조 변수로 접근해야 한다.

main() 메소드도 정적(static) 메소드이기 때문에! 객체 생성 없이 인스턴스 필드와 인스턴스 메소드를 바로 사용하지 못한다!

싱글톤

음... 이건 안 한 것 같은데... 일단 넘어갑니다... ㅠ 공부 어려워잉... 하루하루... 벽에 부딪히는군...

profile
영차영차 😎

0개의 댓글