클래스에 선언된 멤버 변수/멤버 메소드는 static 여부에 따라 아래와 같이 불려진다
인스턴스 변수:
- static 이 안붙은 변수
인스턴스를 생성한 다음에(new 생성자(); 호출된 다음에) 사용할 수 있는 변수
인스턴스 메소드:
static 이 안붙은 메소드
인스턴스를 생성한 다음에(new 생성자(); 호출된 다음에)
사용할 수 있는 메소드
클래스 변수(static 변수):
클래스의 멤버 변수들 중에서, 인스턴스를 생성하지 않아도 사용할 수 있는 변수
클래스 메소드(static 메소드):
인스턴스를 생성하지 않아도 사용할 수 있는 메소드
package com.lec.java.static01;
import java.util.Scanner;
public class Static01Main {
public static void test() {
System.out.println("Hello, Java!");
}
public void test2() {
System.out.println("안녕하세요~");
}
public static void main(String[] args) {
System.out.println("인스턴스 변수/메소드 vs 클래스 변수/메소드");
test();
// static 안에서는 static 이 아닌 것을 사용할 수 없다. // ERROR : cannot make a static reference to the non-static method
// test2();
// 인스턴스 변수/메소드 (non-static)
// 인스턴스 생성한 후에 사용가능
Static01Main tc = new Static01Main();
tc.test2();
} // end main()
} // end class Static01Main
- 메모리의 '메소드 영역'에 클래스가 로드 될때(프로그램 시작될때) '한번만' 생긴다
- 인스턴스가 생성되지 않아도 사용할 수 있다. (인스턴스는 heap에 생김)
- 클래스이름.static변수, 클래스이름.static메소드() <-- 요렇게 사용한다- 모든 인스턴스는 하나의 static 변수/메소드를 '공유'한다
package com.lec.java.static02;
public class Static02Main {
public static void main(String[] args) {
System.out.println("인스턴스 변수/메소드");
Test.show2(); // static 변수도 기본값으로 초기화 된다.
Test.sNum = 123;
Test.show2();
System.out.println();
Test.sNum = 10; // 에러 : cannot make a static reference to the non-static field Test.num
Test t = new Test();
t.num = 100;
t.show();
Test t2 = new Test();
t.show();
t2.sNum = 340; // 인스턴스변수로 static 멤버 접근은 가능하긴하나 바람직한 방법은 아님. 잠재적 에러 발생 가능
t.show();
Test.sNum = 100;
t.sNum = 500;
t2.sNum = 700;
// Test.sNum
// t.sNum
// t2.sNum
System.out.println(Test.sNum);
System.out.println(t.sNum);
System.out.println(t2.sNum);
} // end main()
} // end class Static02Main
package com.lec.java.static02;
public class Test {
// 멤버 변수
int num; // 인스턴스 변수
static int sNum; // 클래스 변수(static 변수) - 글씨체 기울어짐
// 메소드
// 인스턴스 메소드
public void show() {
System.out.println("인스턴스 num = " + num);
System.out.println("클래스(static) sNum = " + sNum);
}
// 클래스(static) 메소드
public static void show2() {
// System.out.println("인스턴스 num = " + num); // static 내에서 non-static 사용 불가
System.out.println("클래스(static) sNum = " + sNum);
}
}
package com.lec.java.static03;
import java.util.Calendar;
public class Static03Main {
public static void main(String[] args) {
System.out.println("Singleton 디자인 패턴");
// Singleton 객체는 인스턴스가 복수개 생성 불가.
// Test t1 = new Test();
// Test t2 = new Test();
Test t1 = Test.getInstance(); // 최초로 인스턴스 생성
System.out.println("t1: num = " + t1.getNum());
t1.setNum(123);
System.out.println("t2: num = " + t1.getNum());
System.out.println();
Test t2 = Test.getInstance(); // 기존에 먼저 만들어졌던 인스턴스를 리턴 받음.
System.out.println("t1: " + t1);
System.out.println("t2: " + t2);
t2.setNum(12345);
System.out.println("t1: num = " + t1.getNum()); // 둘다 12345
System.out.println("t2: num = " + t2.getNum()); // 둘다 12345
// Calendar c = new Calendar(); 생성자 제공 안됨
Calendar c = Calendar.getInstance();
} // end main()
} // end class Static03Main
package com.lec.java.static03;
public class Test {
private int num;
// 생성자
private Test() {
num = 100;
}
// singleton 디자인
private static Test instance = null;
public static Test getInstance() {
if(instance == null) { // 기존에 인스턴스가 없으면 새로 만들고,
instance = new Test();
}
// 있었으면 있던 인스턴스를 리턴
return instance;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
}
package com.lec.java.final01;
public class Final01Main {
// final 멤버변수
// (주의) final 멤버 변수는 반드시 선언과 동시에 초기화 (혹은 생성자에서 초기화) 해야 한다
final int NUM1 = 1;
// final int NUM2;
final int NUM3; // 생성자에서 초기화하면 OK
public Final01Main() {
// NUM1 = 1; // 이미 선언단계에서 초기화 했으면 초기화시 에러
NUM3 = 100;
}
public static void main(String[] args) {
System.out.println("final: 변경할 수 없는 상수");
// 변수:
int num1 = 1;
num1 = 10;
// 상수: 한번 값이 초기화되면 더이상 변경할 수 없다.
final int num2 = 1;
// num2 = 10;
final int num3;
num3 = 1;
// num3 = 12;
} // end main()
} // end class Final01Main
[연습문제]
package practice.cardcompany;
/*
* 카드회사가 있습니다. 카드회사는 '유일한 객체' 이고,
* 이 회사에서는 카드를 발급하면 항상 '고유번호' 가 자동으로 생성됩니다.
* 10001 부터 시작하여 카드가 생성될때마다 10002, 10003 식으로 증가됩니다.
* 다음 코드가 수행되도록 Card클래스와 Company 클래스를 구현하세요
*/
public class CardCompanyMain {
// ★ 아래 main() 코드는 손대지 마세요 ★
public static void main(String[] args) {
// Company co = new Company(); // Company의 어떠한 생성자도 동작하면 안된다
Company com = Company.getInstance(); // 싱글톤 패턴
Company company = Company.getInstance(); // 여러번 호출해도 동일 객체
// ↓ '동일객체' 라고 결과가 나와야 한다.
System.out.println((com == company) ? "동일객체" : "다른객체");
Card myCard = company.createCard(); // 첫번째 카드생성 고유번호 10001 부여
Card yourCard = company.createCard();
System.out.println(myCard.getCardNumber()); // 10001 출력
System.out.println(yourCard.getCardNumber()); // 10002출력
} // end main
} // end class
package practice.cardcompany;
public class Company {
// 필요한 변수, 메소드, 생성자 정의하기
private static int serialNum = 10000;
private static Company instance;
private Company() {}
public static Company getInstance() {
if (instance == null) {
instance = new Company();
}
return instance;
}
public Card createCard() {
return new Card(++serialNum);
}
} // end class
package practice.cardcompany;
public class Card {
// 필요한 변수, 메소드, 생성자 정의하기
// 멤버변수
private int cardNumber; // 카드 고유 번호
// 생성자
// 매개변수 있는 생성자
public Card(int cardNumber) {
super();
this.cardNumber = cardNumber;
}
// getter & setter
public int getCardNumber() {
return cardNumber;
}
public void setCardNumber(int cardNumber) {
this.cardNumber = cardNumber;
}
} // end class