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 |