인스턴스 변수와 클래스 변수

Agnes Park·2022년 2월 20일
0

JAVA

목록 보기
21/34

1. 인스턴스 변수와 클래스 변수

클래스에 선언된 멤버 변수/멤버 메소드는 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

2. 클래스 변수 / 메소드 특징 (static)

  1. 메모리의 '메소드 영역'에 클래스가 로드 될때(프로그램 시작될때) '한번만' 생긴다
  2. 인스턴스가 생성되지 않아도 사용할 수 있다. (인스턴스는 heap에 생김)
    - 클래스이름.static변수, 클래스이름.static메소드() <-- 요렇게 사용한다
  3. 모든 인스턴스는 하나의 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);
	}	
}

3. Singleton 디자인 패턴

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;
	}
	
}

4. final 멤버 변수

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

0개의 댓글