import 같은 것만 class 밖에 존재 가능.
이런 걸 설정이라고 함.
자바는 객체지향언어 - 다루는 대상이 객체이기 때문에,
객체를 구성하는 두 가지 정보(상태/멤버변수, 행위/메서드)를 제대로 구현하는 건 매우 중요한 부분
지금 배우는 부분 = 기초 = 매우 중요
누군가 말하길, "static은 만악의 근원"이라더라
todo(){
int m = 3;
int n = 4;
}
- 필드 = 멤버 변수 + static 변수
(static은 객체의 구성요소가 아님에 주의 (멤버변수, (멤버)메서드 같은 객체의 멤버가 X))
우리가 지금까지 사용해온 static 메서드들
1. System.out.println(); // 객체 생성 없이 System 클래스에서 불러온 println 메서드 2. Math.random(); // 객체 생성 없이 Math 클래스에서 불러온 random 메서드
static 요소를 구분하여 알려주는 건 아주 중요한 요소!
객체 생성과 관계없이 '클래스명.static요소'로 불러줄 것!
static은 공유가 된다 -> 누군가의 소유물이 아니다 -> static은 객체의 구성요소가 아니다, 객체와 관계가 없다 -> 객체지향으로 설명할 수 없는 개념
자바는c, c++의 영향을 많이 받음
c는 전역변수, 함수 사용 => 자바의 static 변수, static 메서드
전역변수 : 전체에서 사용o 변수
함수 : 소유자x 메서드
static만 존재하는 c언어의 문제점
: 변수, 함수에 소유자가 없으므로, 문제가 생길 경우 소유자를 찾아갈 수 없다.
즉, 책임 소재가 불명확하다.
이는 절차지향에서 객체지향으로 바뀐 이유이기도 하다
절차지향이 잘못된 것은 x
하지만 대규모 프로젝트일수록 절차지향의 단점(책임소재 불명확)이 더 커진다.
멤버변수에 private을 붙이는 이유 또한
1. 객체 핵심 데이터 함부로 변형x 도 있지만
2. 책임 소재 명확화 목적도 크다는 것!!!
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말고 다르게 표현하는 법 나중에 배움.
c언어는 os 위에서 동작 -> main이 리턴할 때 = 프로그램이 끝날 때 -> 프로그램을 실행했던 os가 존재하므로 return을 던져주고 죽을 수 있다.
Java는 JVM 위에서 동작 -> 프로그램이 끝날 때 -> 프로그램을 실행한 JVM도 같이 죽으므로 값 던져주는 게 의미가 x
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());
}
}
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);
}
}
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라고 적을 수 있다
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) {
}
}
진짜 이유 : 누군지 지정하지 않으면 누구의 메서드인지 모르기 때문
-> 객체는 몇 개든 만들어질 수 있잖아. 메소드를 어느 객체에서 불러올지 모르잖아. (static은 하나만 존재하기에 고민x)
-> static은 객체의 내부자가 아니다 -> 객체 밖에서 부를 땐 메소드에 ‘객체명.’ 붙여주는 원리인 것
메모리에 먼저 올라가는 놈이(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();
}
}