[JAVA기초] Static

포키·2022년 10월 20일
0

국비과정

목록 보기
20/73

static이란
inner static class 참고


import 같은 것만 class 밖에 존재 가능.
이런 걸 설정이라고 함.

자바는 객체지향언어 - 다루는 대상이 객체이기 때문에,
객체를 구성하는 두 가지 정보(상태/멤버변수, 행위/메서드)를 제대로 구현하는 건 매우 중요한 부분
지금 배우는 부분 = 기초 = 매우 중요


static ★★★★★

누군가 말하길, "static은 만악의 근원"이라더라

정적 static 의 의미

  • static 키워드는 프로그램이 시작되기도 전에 데이터가 먼저 메모리에 올라가도록 만든다 (= 사용할 준비 끝!)
  • 기준 : 메모리 상주 시점 (메모리에 올라가는 시점)
    지금까지 우리가 배운 것은 모두 동적 변수, 동적 메서드, 동적 클래스 ...
todo(){
	int m = 3;
    int n = 4;
}
  • 메모리에 올리는 순서를 바꿀 수 있다 -> m, n은 동적이다
  • 필드 = 멤버 변수 + static 변수
    (static은 객체의 구성요소가 아님에 주의 (멤버변수, (멤버)메서드 같은 객체의 멤버가 X))

static 사용법

  • static은 객체 생성 없이 프로그램 시작 시점부터 바로 사용 가능
  • static 키워드 : 정적 변수, 정적 메서드, (정적 블록), 정적 클래스
  • static 변수, static 메서드를 구분하는 법 : '클래스.멤버변수', '클래스.메서드' 형태로 호출

우리가 지금까지 사용해온 static 메서드들

1. System.out.println();		// 객체 생성 없이 System 클래스에서 불러온 println 메서드
2. Math.random();				// 객체 생성 없이 Math 클래스에서 불러온 random 메서드
  • static이라도 같은 클래스 안에 있을 때는 클래스 이름 붙여 호출하지 않아도 되지만,
    static을 구분하기 위해 가급적 붙여준다.

static 요소를 구분하여 알려주는 건 아주 중요한 요소!
객체 생성과 관계없이 '클래스명.static요소'로 불러줄 것!

static의 목적

static은 공유가 된다 -> 누군가의 소유물이 아니다 -> static은 객체의 구성요소가 아니다, 객체와 관계가 없다 -> 객체지향으로 설명할 수 없는 개념

  • 자바는c, c++의 영향을 많이 받음
    c는 전역변수, 함수 사용 => 자바의 static 변수, static 메서드

    전역변수 : 전체에서 사용o 변수
    함수 : 소유자x 메서드

  • static만 존재하는 c언어의 문제점
    : 변수, 함수에 소유자가 없으므로, 문제가 생길 경우 소유자를 찾아갈 수 없다.
    즉, 책임 소재가 불명확하다.

이는 절차지향에서 객체지향으로 바뀐 이유이기도 하다
절차지향이 잘못된 것은 x
하지만 대규모 프로젝트일수록 절차지향의 단점(책임소재 불명확)이 더 커진다.

멤버변수에 private을 붙이는 이유 또한
1. 객체 핵심 데이터 함부로 변형x 도 있지만
2. 책임 소재 명확화 목적도 크다는 것!!!

  • 그러니 static 변수는 쓰지 말자!
    만약 사용할 거라면 적어도 private로 최대한 엄격하게 접근을 막자
class Pizza {
	private String toppings;
	private int radius;
	static final double PI = 3.141592;
	static int count = 0;
	public Pizza(String toppings){
		this.toppings = toppings;
		Pizza.count++;
	}
}
public class PizzaTest {
	public static void main(String[] args) {
		Pizza p1 = new Pizza("Super Supreme");
		Pizza p2 = new Pizza("Cheese");
		Pizza p3 = new Pizza("Pepperoni");
		int n = Pizza.count;
		System.out.println("지금까지 판매된 피자 개수 = " + n);
	}
}
  • 판매된 피자 개수는 피자 객체의 정보가 아님. 하지만 기록하기 위해 static을 통해 모든 객체가 공유하는, 객체를 포괄하는 값 저장.

  • 객체끼리 공유해야 하는 값, 기능이 있는 경우
    (메서드는 필요하면 사용할 수 있지만, 변수는 아주아주 엄격하게 사용.. 가급적 쓰지않기)

의문점 - static은 어떨 때 사용하는가?

  • 객체와 직접적 관련은 없고 근데 어딘가에 있어야 하는 것. -> static 표현.
    역으로, static이 붙어있으면 -> 관련 있는지 없는지 굳이 따질 필요 없다. 어차피 어느 객체랑도 큰 관계 없는 값이라 static 붙여서 '아무데서나 사용 가능하게' 만든 것.
  • 가급적 쓰지 않는 것이 좋다. 제한적으로 사용하니 그 경우만 외워서 쓰면 될 듯.
  • static말고 다르게 표현하는 법 나중에 배움.
  • public static void main(String[] args)의 의미
    시작할 때 어디에 있든 main을 바로 불러와야 함 -> static
    무조건 실행되야 하니까 -> public
    main 끝나면 다 끝이니까 -> void

    c언어는 os 위에서 동작 -> main이 리턴할 때 = 프로그램이 끝날 때 -> 프로그램을 실행했던 os가 존재하므로 return을 던져주고 죽을 수 있다.
    Java는 JVM 위에서 동작 -> 프로그램이 끝날 때 -> 프로그램을 실행한 JVM도 같이 죽으므로 값 던져주는 게 의미가 x

  • static 변수는 static 메서드로 불러온다
    (static 변수 가져와서 사용하는 거 말고, static을 가져오기 위한 목적만으로 메서드 만들지x)
    (그렇지 않으면 불필요한 객체를 생성하게 되고, static 변수가 객체와 불필요한 관계를 맺어 끌려오게 된다.)
    (class로 바로 불러올 때 static 변수는 비로소 누구도 책임지지 않아도 되는 자유변수가 되는 것이다.)
class Dummy {
	private static int num = 4;
	public static int getNum(){
		return num;
	}
}
class StaticEx3 {
	public static void main(String[] args) {
		System.out.println(Dummy.getNum());
	}
}

final 키워드 (상수화)

  • 객체가 생성되고 변하지 않을 값 = final 변수
  • 객체끼리 공유하는 상수값 = static final 변수
class Bar {	
	public final int NUM;	
	public final static int MAX = 3;
	public Bar(int num) {
		NUM = num;
	}
}
class StaticEx4 {
	public static void main(String[] args)	{
		new Bar(3);
		new Bar(2);
		new Bar(1);
		new Bar(0);

	}
}
  • public static final int 상수
class VendingMachine {
	public static final int COLA = 1;
	public static final int CIDER = 2;
	public static final int FANTA = 3;
	public void showMenu() {
		System.out.println("1. 콜라, 2. 사이다, 3. 환타");
	}
	public void choice(int what) {
		int price = 0;
		if(what == COLA) {
			price = 2000;
		} else if(what == CIDER) {
			price = 1800;
		} else if(what == FANTA) {
			price = 1900;
		}
	}
}
class UseVendingMachine {
	public static void main(String[] args)	{
		VendingMachine v = new VendingMachine();
		v.showMenu();
		v.choice(VendingMachine.FANTA);
	}
}

1은 콜라 번호입니다~ 라고 설명하지 않아도, COLA = 1 해두는 것으로 앞으로 콜라번호 자리에 COLA라고 적을 수 있다

  • ★ COLA, CIDER, FANTA의 구체적인 값을 알지 못해도 쓰는 사람이 사용 가능하다는 것이 장점
  • 사실 이 경우 제외하면 static은 가능하면 쓰지 않는게 좋다

static <-> non-static 관계

class StaticEx5 {
	public static void caller1(){
		target1();				// static이 static 호출
		target2();				// static이 non-static 호출
	}
	public void caller2(){
		target1();				// non-static이 static 호출
		target2();				// non-static이 non-static 호출
	}

	public static void target1(){
	}
	public void target2(){
	}
	public static void main(String[] args) {
		
	}
}
  1. 진짜 이유 : 누군지 지정하지 않으면 누구의 메서드인지 모르기 때문
    -> 객체는 몇 개든 만들어질 수 있잖아. 메소드를 어느 객체에서 불러올지 모르잖아. (static은 하나만 존재하기에 고민x)
    -> static은 객체의 내부자가 아니다 -> 객체 밖에서 부를 땐 메소드에 ‘객체명.’ 붙여주는 원리인 것

  2. 메모리에 먼저 올라가는 놈이(static) 나중에 올라가는 놈을(non-static)을 부르기 어렵다 - 는 방향도 있지만 정확한 설명은 아님.


정적 블록

class StaticEx6 {
	// 클래스를 사용할 때 실행된다.
	{
		System.out.println("non-static");
	}
	static {
		System.out.println("static");
	}
	public static void main(String[] args) {
		new StaticEx6();
		new StaticEx6();
		new StaticEx6();
		new StaticEx6();
		new StaticEx6();
	}
}
profile
welcome

0개의 댓글