클래스 변수와 메소드

황상익·2023년 12월 15일

열혈 자바

목록 보기
9/30

클래스 변수와 메소드
Static 선언을 붙여서 선언하는 메소드
인스턴스 변수는 생성된 인스턴스 안에 존재하는 변수. But 클래스 변수, 인스턴스의 생성과 관계 없이 존재하는 변수

선언된 클래스의 모든 인스턴스가 공유하는 클래스 변수
클래스 내에 선언된 변수 앞에 static 선언이 붙으면 -> 클래스 변수가 된다.

public class Main1 {
    public static void main(String[] args) {
        AccessWay way = new AccessWay();
        way.num++;
        AccessWay.num++;
        System.out.println("num" + AccessWay.num);
    }
}

class AccessWay{
    static int num = 0;

    AccessWay(){
        intcrCnt();
    }

    void intcrCnt(){
        num++;
    }
}

static으로 선언된 변수는 변수가 선언된 클래스의 모든 인스턴스가 공유하는 변수
클래스 변수는 인스턴스 내에 존재하는 변수가 아니라, 어떠한 인스턴스에도 속하지 않는 상태로 메모리 공간에 딱 하나만 존재.

클래스 변수의 접근
클래스 내부 접근 -> 변수의 이름을 통해 직접 접근
클래스 외부 접근 -> 클래스 또는 인스턴스의 이름을 통해 접근
void intcrCnt(){
num++;
}
}
클래스 내부에서 이름을 통한 접근
way.num++;
AccessWay.num++;
외부에서 클래스 이름을 통한 접근
클래스 변수의 초기화 시점과 초기화 방법

public class Main2 {
    public static void main(String[] args) {
        InstCnt.num -= 15;
        System.out.println(InstCnt.num);
    }
}

class InstCnt{
    static int num = 100;

    InstCnt(){
        num++;
        System.out.println("인스턴스 생성" + num);
    }
}

클래스 변수는 인스턴스의 생성과 상관없다고 했다. 그렇다면 클래스 변수는 메모리 공간에 언제 할당되고 초기화 될까?
InstCnt.num -= 15;
인스턴스 생성 없이 num에 접근.
클래스 변수는 인스턴스 생성 이전에 메모리 공간에 존재. 해당 클래스 정보가 가상머신에 의해 읽히는 순간 메모리 공간에 할당되고 초기화. 할당과 초기화는 인스턴스 생성과 무관하게 이루어진다.
static int num = 100;
정상적인 초기화
//num = 0;
초기화 아님

클래스 변수를 언제 유용하게 사용?
인스턴스간 데이터 공유가 필요한 상황에서 클래스 변수를 선언. 생성된 인스턴스의 수를 관리하는 상황 -> 클래스 변수가 유용하게 사용 됨

public class Main3 {
    public static void main(String[] args) {
        Circle circle = new Circle(3.4);
        circle.showParameter();
        circle.showArea();
    }
}

class Circle{
    static final double PI = 3.14;
    private double radius;

    Circle(double rad){
        radius = rad;
    }

    void showParameter(){
        double peri = (radius * 2) * PI;
        System.out.println("둘레" + peri);
    }

    void showArea(){
        double area = (radius * radius) * PI;
        System.out.println("넓이" + area);
    }
}

static final double PI = 3.14;
PI는 인스턴스 변수가 아닌 클래스 변수로 사용됨. -> 모든 Circle이 참조해야 하는 값 이지만, 인스턴스가 각각 지녀야 하는 값은 아니기 때문이다.
참고로 참조 목적으로만 존재하는 값은 final 선언이 된 클래스 변수에 넣는다.

Statice 선언을 붙여서 선언하는 클래스 메소드
Static 선언을 하면, 클래스 메소드가 된다. 클래스 메소드는 클래스 변수와 유사. 또한 어느 인스턴스에도 속하지 않는 메소드라는 점도 동일
클래스 메소드의 정의와 호출.
 인스턴스 생성 이전부터 접근 가능
 어느 인스턴스에도 속하지 않는다.

public class Main4 {
    public static void main(String[] args) {
        NumberPointer.showInt(20);

        NumberPointer np = new NumberPointer();
        np.showDouble(3.15);
        np.setMyNum(75);
        np.showMyNum();
    }
}

class NumberPointer{
    private int myNum = 0;

    static void showInt(int n){
        System.out.println(n);
    }

    static void showDouble(double r){
        System.out.println(r);
    }

    void setMyNum(int n){
        showInt(myNum);
    }

    void showMyNum(){
        showInt(myNum);
    }
}

static void showInt(int n){
System.out.println(n);
}
 클래스 메소드
void setMyNum(int n){
showInt(myNum);
}
 인스턴스 메소드
showInt(myNum);
}
 클래스 내부에서 클래스 메소드 호출

NumberPointer.showInt(20);
 클래스 메소드가 어느 인스턴스에도 속하지 않는다.
왜냐하면, 인스턴스 생성 이전에 호출, 클래스 변수에 접근하는 방법과 차이가 없다.

클래스 메소드로 정의하는 것이 더 좋은 경우

class SimpleCalculator{
    static final double PI = 3.141592;

    static double add(double n1, double n2){
        return n1 + n2;
    }

    static double min(double n1, double n2){
        return n1 - n2;
    }

    static double calCircleArea(double r){
        return (r * r) * PI;
    }

    double calCirclePeri(double r){
        return (r * 2) * PI;
    }
}

public class Main5 {
    public static void main(String[] args) {
        SimpleCalculator cal = new SimpleCalculator();
        System.out.println("덧샘" + cal.add(3,4));
        System.out.println("반지름" + cal.calCircleArea(2.2));

        System.out.println("뺄셈" + cal.min(3,4));
        System.out.println("반지름, 원의둘레" + cal.calCirclePeri(5.0));
    }
}

 모두 외부 기능을 제공하기 위한 메소드
 인스턴스 변수의 값을 참조 또는 수정하지 않는다
 또한 static 선언을 추가함으로 인해 불필요한 인스턴스의 생성 과정을 생략
클래스 메소드에서 인스턴스 변수 접근 불가능?
우선 결론적으로는 불가능하다.
class AAA{
int num;
static void addNum(int n){
num += n;
}
}
인스턴스 변수는 인스턴스 속에 속한다. 인스턴스 생성이 되어야 메모리 공간 존재. 반면 클래스 메소드는 인스턴스 생성 이전부터 호출이 가능.
클래스 메소드는 인스턴스 속에 속하지 않으므로 변수에 접근이 불가능.
같은 이유로 클래스 메소드는 인스턴스 메소드의 호출도 불가능
같은 클레스에 정의되어 있는 다른 클래스 메소드나 성격이 동일한 클래스 변수에는 접근이 가능

System.out,println ( ); & public static void main ( );
Main 메소드를 정의할 때 static 선언을 붙였다. 그래서 인스턴스 생성 없이 println 메소드를 호출

System.out,println ( );
System은 java에서 제공, out은 System.out으로 접근하니, static으로 선언된 클래스 변수가 분명. Out은 System 클래스 내에 선언된 클래스 변수.
Println -> PrintStrem 클래스의 인스턴스 메소드이다.

Main 메소드가 public이 아니고 static인 이유는?
Main 메소드가 호출이 이루어지는 영역은 클래스 외부 영역. 따라서 public으로 선언하는 것이 타당.

class Car{
    void car(){
        System.out.println("자동차");
    }

    public static void main(String[] args) {
        Car c = new Car();
        c.car();

        Boat b = new Boat();
        b.boat();
    }
}

class Boat{
    void boat(){
        System.out.println("배");
    }
}

public class Main6 {
}

main 메소드 담을 준비는 끝났고, main 메소드를 담을 목적으로 별도의 클래스를 정의. 그러나 main 메소드는 static 메소드이기 때문에, 특정 인스턴스의 멤버로 존재하는 메소드는 아니다.
 Car 클래스와 static으로 선언된 main 메소드는 별개
 다만 Car 클래스가 main 메소드 공간에 제공

다른 용도의 static 선언

public class Main7 {
}

class DateExcution{
    static String date;

    static {
        LocalDate nDate = LocalDate.now();
        date = nDate.toString();
    }

    public static void main(String[] args) {
        System.out.println(date);
    }
}

Static 초기화 블록
static String date;
static {
LocalDate nDate = LocalDate.now();
date = nDate.toString();
}
참조만 목적으로 하므로 클래스 변수로 선언
클래스 변수 date 선언과 동시에 날짜 정보를 담고 있는 문자열로 초기화. 변수 date가 인스턴스 변수라면, 두 문장을 생성자에 넣으면 된다. -> static 초기화 블록으로 감싸면
static {
LocalDate nDate = LocalDate.now();
date = nDate.toString();
}
클래스 변수를 선언과 동시에, 초기화 가능. & 로딩 시 단 한 번 실행

Static Import 선언

public class Main8 {
    public static void main(String[] args) {
        System.out.println(Math.E);
        System.out.println(Math.PI);
        System.out.println(Math.abs(-55));
        System.out.println(Math.max(77, 88));
        System.out.println(Math.min(33, 55));
    }
}
<문제>
1.
public class Main9 {
    public static void main(String[] args) {
        Accumulation accumulation = new Accumulation();
        for (int i = 0; i < 10; i++) {
            accumulation.add(i);
            accumulation.showResult();
        }
    }
}

class Accumulation {
    static int sum = 0;

    public void add(int num) {
        sum += num;
    }

    public void showResult(){
        System.out.println("sum = " + sum);
    }
}
profile
개발자를 향해 가는 중입니다~! 항상 겸손

0개의 댓글