Static , ( Feat. instance )
인스턴스(instance)필드와 정적(static)필드에 대해서 자바를 공부한 사람이라면 한번은 들어보았을 것이다.
오늘 나는 인스턴스 필드와 정적필드에 관하여 가볍게 알아보려고 한다.
인스턴스(객체)는 힙(heap) 영역에 생성이 된다. 그리고 새로운 객체를 만들면 새로운 힙 영역에 그 객체가 할당,
그 힙영역에 인스턴스멤버들 또한 할당이 된다.
class Product {
private String productName;
private int price;
public Product(String productName, int price) {
this.productName = productName;
this.price = price;
}
public String getProductName() {
return productName;
}
public int getPrice() {
return price;
}
void Estimation(){
System.out.println("구매하려는 상품 : " + productName);
System.out.println("해당상품의 가격 : " + price);
}
}
상품의 정보를 출력하기 위한 클래스를 만들었습니다. 이제 이 클래스의 인스턴스를 생성해보죠
public class StaticTest {
public static void main(String[] args) {
Product product1 = new Product("TV",100_000);
Product product2 = new Product("Mac", 3_000_000);
Product product3 = new Product("IPhone", 1_200_000);
product1.Estimation();
product2.Estimation();
product3.Estimation();
}
}
prodect1 , prodect2 , prodect3 힙영역에는 3개의 객체가 생성되었고 각각의 객체에는 각각의 인스턴스 멤버가 존재합
니다.
그리고 생성자를 통하여 각 객체에 인스턴스 멤버에 상품의 이름 , 가격을 넣어줍니다.
상품의 견적을 뽑기위한 메서드 Estimation() 또한 인스턴스 멤버로써 힙영역에 존재하고,
이 메서드를 사용하기 위해선 필히 객체가 생성되어야 합니다.
인스턴스 멤버들은 객체가 힙영역에 생성될때 같이 할당받습니다. 따라서 각각의 객체는 각각의 인스턴스 멤버를
가지고 있는것 입니다.
자 그럼 static 필드는 무엇이냐? , 그전에 우리는 한가지 상황을 생각해봅시다.
자 우리는 '상품넘버'를 만들어 상품들을 체계적으로 관리가 하고싶어졌습니다.
어떻게 해야할까요?
가장 먼저 떠오르는 방법은 생성자로 상품번호를 받아서 관리하는 겁니다.
productName과 price가 그랬던것처럼 말이죠 ( 프로그램 사용자가 직접 입력)
하지만, 인간은 완벽하지 않습니다.
제품의 번호가 중복되는 경우가 생길수가 있겠죠? 만약 제품이 들어온 순서를 알고싶어서 제품의 번호를 매겼더만
제품번호가 중복되어서 , 어떤 제품이 먼저 등록되었는지 알수가 없어 성가셔지는 상황이 온다면?
제품의 번호가 왜 중복되느냐 바로 인스턴스멤버로 제품의 번호를 등록했기때문입니다.
인스턴스멤버는 각 인스턴스에 소속된 멤버이기 때문에 다른 인스턴스 멤버의 값과 중복이 되든 안되든 상관이 없죠
이를 막기위해 생성된 모든 객체들이 공유하는 클래스멤버를 만들어 제품의 번호를 관리하겠습니다.
바로 정적(static)필드에 제품번호를 생성하겠습니다.
class Product {
private static int num = 0;
private String productName;
private int price;
public Product(String productName, int price) {
this.productName = productName;
this.price = price;
}
public String getProductName() {
return productName;
}
public int getPrice() {
return price;
}
public int getProductNum() {
return num;
}
void Estimation(){
System.out.println("구매하려는 상품 : " + productName);
System.out.println("해당상품의 가격 : " + price);
System.out.println("상품번호 : "+num);
}
}
public class StaticTest {
public static void main(String[] args) {
Product product1 = new Product("TV",100_000);
Product product2 = new Product("Mac", 3_000_000);
Product product3 = new Product("IPhone", 1_200_000);
product1.Estimation();
product2.Estimation();
product3.Estimation();
}
}
자 상품 번호를 static으로 설정했습니다. 이게 무슨차이일까? 한번 코드를 돌려봅니다.
구매하려는 상품 : TV
해당상품의 가격 : 100000
상품번호 : 0
구매하려는 상품 : Mac
해당상품의 가격 : 3000000
상품번호 : 0
구매하려는 상품 : IPhone
해당상품의 가격 : 1200000
상품번호 : 0
상품 번호가 출력되었습니다.
그런데 모든 상품번호가 0으로 출력이 되고 있습니다. 이러면 static을 붙이지 않은 클래스와 무슨차이일까요?..
차이가 없죠 ㅎㅎ.. 그렇다면 코드를 살짝 추가 및 변경해보겠습니다.
class Product {
private static int num = 0;
private String productName;
private int price;
private int productNum = ++num; <<--추가
public Product(String productName, int price) {
this.productName = productName;
this.price = price;
}
public String getProductName() {
return productName;
}
public int getPrice() {
return price;
}
public int getProductNum() {
return productNum;
}
void Estimation(){
System.out.println("구매하려는 상품 : " + productName);
System.out.println("해당상품의 가격 : " + price);
System.out.println("상품번호 : "+productNum);
}
}
public class StaticTest {
public static void main(String[] args) {
Product product1 = new Product("TV",100_000);
Product product2 = new Product("Mac", 3_000_000);
Product product3 = new Product("IPhone", 1_200_000);
product1.Estimation();
product2.Estimation();
product3.Estimation();
}
}
그럼 이 코드의 실행결과를 확인해봅시다.
구매하려는 상품 : TV
해당상품의 가격 : 100000
상품번호 : 1
구매하려는 상품 : Mac
해당상품의 가격 : 3000000
상품번호 : 2
구매하려는 상품 : IPhone
해당상품의 가격 : 1200000
상품번호 : 3
보이시나요? 상품번호가 1,2,3 객체의 생성 순서대로 매겨졌습니다.
어찌된 일일까..?
Static 이란 '정적인, 고정된' 이란 의미입니다. static 필드란 JVM메모리의 메서드(method)영역을 의미하며
static이 붙은 객체나 변수, 메서드는 이 메서드영역에 생성이 됩니다.
한 클래스안에 인스턴스변수와 static이 붙은 클래스변수는 공존하지만, 우리가 프로그램을 돌릴때
프로그램에 필요한 클래스가 jvm 메모리상에 로딩되는 과정을 거치는데, 이렇게 한번 로딩된 클래스는
객체의 생성을 위해서 메서드영역에 상주하게 됩니다.
다시말해 한번 자리를 잡게되면 프로그램이 끝날때까지 고정된 상태로 존재한다는것
이 메서드영역에 바로 클래스멤버들도 같이 상주하게되면서 , 이제 생성한 객체들은 이 클래스멤버를 공유합니다.
private static int num = 0;
private int productNum = ++num;
productNum 은 인스턴스멤버이고 객체를 생성할때마다 힙영역에 할당되면서 num값을 1씩 올려준다.
1씩 오른 메서드영역의 num값은 이제 프로그램이 초기화되기 전까진 초기화 될일이 없다.
따라서 객체를 하나씩 생성할때마다 1씩오른 num 값을 모든 객체들이 공유한다.
'Java > Java Study' 카테고리의 다른 글
[Thread] Thread 정리 Part 1 (0) | 2021.08.17 |
---|---|
[Collections Framework] Arrays.sort( ); - (Comparable & Comparator) (0) | 2021.06.03 |
[Collections Framework] Arrays (0) | 2021.06.03 |
[객체지향] Static 메서드는 언제 쓸까? (0) | 2021.06.02 |
[Collections Framework] LinkedList (vs Array) (0) | 2021.05.31 |