Stack heap(동적메모리영역) static(정적메모리영역)

- codeArray : 작성한 코드(클래스)
- static 변수 : Full클래스명으로 명시
- 모든 메소드 접근 가능
- 모든 객체들이 공유해서 사용하는 변수
- num : new 연산자를 사용해서 생성되고 참조가 끝나면 GC에 의해 소멸된다.
Life cycle
- Stack : 메소드가 호출되었을때 생성되고, 메소드가 끝나면 소멸된다.
- heap : num은 new 연사자를 통해 객체가 생성되고 참조가 끝나게 되면 GC를 통해서 소멸된다.
- static : size는 프로그램이 시작되면 할당받고 프로그램이 종료되면 소멸된다.

public class Variable { public static int size; private int num; public void test(){ int num = 100; } }
변수의 종류
- 변수들은 선언하는 위치에 따라 종류가 달라진다.
- 클래스 영역내부에 작성하는 변수
- = 맴버변수 (클래스가 가지는 맴버)
- = 인스턴스 변수 (heap에 할당했을때 생성되는 객체를 인스턴스라고 한다.)
- = 전역변수 (grobal variable)
- = 필드
- 클래스 변수 중 static 키워드가 붙으면
- = 클래스 변수
- = static 필드
- = 정적 필드
- 클래스 변수 중 static 키워드가 붙으면
- 메소드 영역내에 있는 변수
- = 지역변수
- 괄호 안에 있는 변수
- - 매개변수
- = 지역변수 (스택을 사용)
package com.kh.chap03.field.part01_kindsOfVariable; //변수 선언 위치에 따른 구분 public class kindsOfVariable { //클래스 영역의 시작 //클래스 영역에 작성하는 변수를 필드라고 한다. //필드 == 맴버변수 (클래스가 가지는 맴버라는 의미) // == 전역변수 (클래스가 전역에서 사용할 수 있는 변수라는 의미) // == 인스턴스변수 (인스턴수 생성 시 할당받는 변수라는 의미) private int globalNum; //접근제한자 자료형 변수명 public void testMethod(int num) { //메소드 영역의 시작 //메소드 영역에서 작성하는 변수를 지역변수라고 한다. //메소드의 괄호 안에 작성하는 변수를 매개변수라고 한다. //매개변수도 일종의 지역변수로 생각하면 된다. int localNum; //지역 변수는 선언 외에 다시 사용하기 위해서는 반드시 초기화가 되어 있어야 한다. /*System.out.println(localNum);*/ //에러발생 //매개변수는 호출 시 값이 넘어와서 변경되기 때문에 초기화가 필요 없다. System.out.println(num);//메소드 호출할때 인자를 줘야하기때문에(강제적) 보장이 되어있어서 에러가 나지 않는다. //전역변수는 클래스 전역에서 사용 가능하다. System.out.println(globalNum); } //메소드 영역의 끝 public void testMethod2() { //지역변수는 해당 지역(블럭 내)에서만 사용 가능하다. /*System.out.println(localNum);*/ //전역변수는 다른 메소드에서도 사용 가능하다. System.out.println(globalNum); } } //클래스 영역의 끝
클래스 필드 예약어
- static : 여러 객체가 공유할 목적의 필드에 사용하며, 프로그램 시작시 정적(static) 메모리영역에 자동 할당되는 멤버에 적용한다. (필드 영역에 붙을 수 있다.)
→ static자체가 캡슐화 원칙에 위배(특수한목적이 아닌이상 사용 x) - final : 하나의 값만 계속 저장해야 하는 변수에 사용한다.
- final을 할땐 반드시 초기값을 선언#화해줘야한다. (필드에 final이 붙으면 값을 변경하지 못한다.)
--> new라는 연산자를통해 heap에 할당되는데 빈공간으로는 생성이 안되므로 JVM이 정한 기본값으로 설정되는데 후에 변경하지 못하기 때문에 반드시 선언과 동시에 초기화 해줘야한다
- final을 할땐 반드시 초기값을 선언#화해줘야한다. (필드에 final이 붙으면 값을 변경하지 못한다.)
- static final : 상수 필드이다. (변경은 못하고 불러서 사용할 수 있는것)
- 상수이면서 정적 영역에 보관하여 여러 객체가 공유할 목적으로 사용한다.
=>반드시 초기값을 지정하며 선언. - public static fianl 접근제한자 (예 : Math.PI)
- public인 상수필드 => 공유할목적으로 사용. 값을 바꾸지못하고, 어디서나 사용할 수 있다.
- static영역에 올라와있기 때문에 new를 사용하지않고 Math.PI라는 이름으로 공간에 접근할수있다.
- 상수이면서 정적 영역에 보관하여 여러 객체가 공유할 목적으로 사용한다.
package com.kh.chap03.field.part01_kindsOfVariable; //static 키워드에 대한 구분 public class kindsOfVariable2 { //전역변수에서 static 키워드 사용 가능하다. //전역변수 테스트 public static int staticNum; //public 접근제한자에 static과 final 키워드를 함꼐 사용하는 것을 //'상수필드' 라고 한다. //상수필드는 반드시 선언과 동시에 초기화가 되어야 한다. //프로그램 실행 시 static 키워드가 붙은 맴버는 전부 클래스영역(static area)에 //저장되기 때문이다. //프로그램 시작 시 값이 저장되면 변경되지 않고 사용할 목적으로 사용한다. /*public static final int STATIC_NUM;*/ //static 영역은 모든 객체가 공유할 목적으로 사용되기 때문에 //캡슐화 원칙에 위배된다. //따라서 static 키워드는 특별하게 명확한 목적이 있을 경우만 사용한다. public static final int STATIC_NUM1 = 1; //static과 final은 순서를 바꿔도 상관 없다. public final static int STATIC_NUM2 = 1; public void methodTest() { //지역변수에서는 static 키워드 사용이 불가능하다. //non-static 메소드는 객체가 만들어지고 호출해야만 실행하기 때문이다 //static 키워드를 변수에 불일 수 없다. /*static int localStaticNum;*/ } public static void staticMethodTest() { //static 메소드 내에서도 static 변수 사용이 불가능하다. //static 메소드 내의 변수도 지역변수 이고, //메소드 호출 시 stack에 할당을 받는 변수이기 때문에 //static 영역에 할당을 하라는 키워드는 사용 불가능하다. /*static int localStaticNum;*/ } }
클래스 필드 접근제한자

실습문제2

package com.kh.silsub2.product.model.vo; public class Product { private String pName; //private 접근제한자는 해당 클래스 내부에서만 사용이 가능하기 때문에 외부에서 접근이 불가능 하다. public int price; String brand; protected static double taxRate; public Product() {} //setter public void setpName(String pName) { this.pName = pName; } public void setPrice(int price) { this.price = price; } public void setBrand(String brand) { this.brand = brand; } public static void setTaxRate(double taxRate) { Product.taxRate = taxRate; } //getter public String getpName() { return pName; } public int getPrice() { return price; } public String getBrand() { return brand; } public static double getTaxRate() { return /*Product.*/taxRate; } public void information() { System.out.println(pName + ", " + price + ", " + brand + ", " + taxRate); } }
package com.kh.silsub2.product.controller; import com.kh.silsub2.product.model.vo.Product; public class Run /*extends Product(상속)*/{ public static void main(String[] args) { Product p1 = new Product(); p1.setpName("아이뽕"); p1.setPrice(1000000); p1.setBrand("사과"); Product.setTaxRate(0.1); p1.information(); Product p2 = new Product(); /*p2.pName = "아이뽕";*/ //에러, private는 해당 클래스 내부 접근 가능 p2.price = 100000; /*p2.brand = "사과";*/ //에러, default는 해당 패키지 내부에서만 접근 가능 /*Product.taxRate = 0.1;*/ //에러, static이어도 접근제한자는 적용됨 p2.information(); } }
실습문제3

package com.kh.silsub3.circle.model.vo; public class Circle { private static double PI = 3.14; private static int radius = 1; public Circle() {} //getter public static double getPi(){ return PI; } public static int getRadius(){ return radius; } //setter //final 키워드가 붙은 필드는 setter 만들지 못함 /*public static void setPi(double pi) { Circle.PI = pi; }*/ public static void setRadius(int radius) { Circle.radius = radius; } //원의 지름을 1 증가시키는 메소드 public void incrementField() { radius++; } //원의 면적을 구하는 메소드 public void getAreaOfCircle() { double area = radius * radius * PI; System.out.println("원의 면적은 " + area + "입니다."); } //원의 둘레를 구하는 메소드 public void getSizeOfCircle() { double size = 2 * radius * PI; System.out.println("원의 둘레는 " + size + "입니다."); } }
package com.kh.silsub3.circle.controller; import com.kh.silsub3.circle.model.vo.Circle; public class Run { public static void main(String[] args) { Circle c = new Circle(); c.getAreaOfCircle(); c.getSizeOfCircle(); //지름 1 증가 c.incrementField(); //다시 둘레와 면적 구하기 c.getAreaOfCircle(); c.getSizeOfCircle(); } }
클래스 초기화블럭
- 맴버변수(필드)를 초기화시키는 블록
- static 블록 : static 필드 초기화, 프로그램 시작시 초기화
- 인스턴스 블록 : 인스턴스 변수 초기화, 객체 생성시 마다 초기화
private String pName = "갤럭시"; //JVM -> 명시적 초기화값으로 덮어쓰기 private int price = 100000; private static String brand = "삼송"; {//초기화 블럭값으로 덮어쓰기 pName = "사이언"; price = 900000; //인스턴스 초기화 블럭에서는 static 필드를 초기화 할 수 있다. //하지만 static 초기화 블럭은 프로그램 시작 시에 초기화를 하기 때문에 //객체 생성 이후 값을 초기화하는 인스턴스 초기화 블럭의 값으로 덮어쓰게 된다. brand = "사과"; } static { //static 초기화 블럭도 start시 같이 실행하기 때문에 static 필드만 초기화 //static 초기화블럭에서는 non-static 필드를 초기화하지 못한다. /*pName = "아이뽕"; price = 1000000;*/ brand = "헬지"; }
초기화 순서
- 클래스 변수

- 인스턴스 변수

실습문제4

package com.kh.silsub4.lotto.model.vo; import java.util.Random; public class Lotto { //배열 선언 private int lottoNums[]; { //배열 할당 lottoNums = new int[6]; //중복 없이 난수 값 대입 for(int i = 0; i < lottoNums.length; i++) { lottoNums[i] = new Random().nextInt(45) + 1; for(int j = 0; j < i; j++) if(lottoNums[i] == lottoNums[j]) { i--; break; } } //정렬 for(int i = 0; i < lottoNums.length; i++) { for(int j = 0; j < i; j++) { if(lottoNums[i] < lottoNums[j]) { int temp; temp = lottoNums[i]; lottoNums[i] = lottoNums[j]; lottoNums[j] = temp; } } } } public Lotto() {} //getter public int[] getLottoNums() { return lottoNums; } //setter public void setLottoNums(int[] lottoNums) { this.lottoNums = lottoNums; } public void information() { for(int i = 0; i < lottoNums.length; i++) { if(lottoNums[i] < 10) { System.out.print("0" + lottoNums[i] + " "); }else { System.out.print(lottoNums[i] + " "); } } System.out.println(); } }
package com.kh.silsub4.lotto.controller; import com.kh.silsub4.lotto.model.vo.Lotto; public class Run { public static void main(String[] args) { /*Lotto lotto = new Lotto(); lotto.information();*/ //로또 자동 5게임 구매 System.out.println("=== 이번주 당첨 예상 번호 ==="); for(int i = 0; i < 5; i++) { Lotto lotto = new Lotto(); lotto.information(); } } }
'JAVA > 이론 정리 및 예제' 카테고리의 다른 글
| [JAVA/자바] #6_5 메소드(method)/ 예제 (0) | 2021.09.14 |
|---|---|
| [JAVA/자바] #6_4 생성자(constructor) / 예제 (0) | 2021.09.14 |
| [JAVA/자바] #6_2 클래스 (0) | 2021.09.14 |
| [JAVA/자바] #6_1 객체지향언어 / 예제 (0) | 2021.09.14 |
| [JAVA/자바] #5_2 mainArgument (0) | 2021.09.14 |