본문 바로가기
TIL/JAVA

23.04.20

by J1-H00N 2023. 4. 21.

문장들의 묶음

코드의 중복을 하나의 묶음으로 만들어 코드의 가독성 및 효율을코드의 중복을 하나의 묶음으로 만들어 코드의 가독성 및 효율을 높일 수 있다.

 

class Time5_1 {
    int hour;
    int minute;
    int second;
}

class Method5_3 {
    static void initObj(Time5_1 time, int hour, int minute, int second) {
        time.hour = hour;
        time.minute = minute;
        time.second = second;
    }
}

class Method5_3Main {
    public static void main(String[] args) {
        Time5_1 t1 = new Time5_1();
        t1.hour = 100;
        t1.minute = 20;
        t1.second = 43;

        Time5_1 t2 = new Time5_1();
        t2.hour = 22;
        t2.minute = 30;
        t2.second = 23;

        Time5_1 t3 = new Time5_1();
        t3.hour = 45;
        t3.minute = 40;
        t3.second = 52;

        System.out.println("t1.hour = " + t1.hour);
        System.out.println("t2.hour = " + t2.hour);
        System.out.println("t3.hour = " + t3.hour);
        System.out.println();

        // 하나하나 인스턴스를 만들고 위처럼 인스턴스 변수를 초기화 하려니 매우 귀찮지 않나요?
        // 물론 '생성자' 라는 개념이 뒤에 나오지만 일단은 메서드를 사용하여 코드의 수를 확 줄여 보겠습니다.

        Time5_1 t4 = new Time5_1();
        Time5_1 t5 = new Time5_1();
        Time5_1 t6 = new Time5_1();

        Method5_3.initObj(t4, 100, 20, 43);
        Method5_3.initObj(t5, 22, 30, 23);
        Method5_3.initObj(t6, 45, 40, 52);

        System.out.println("t4.hour = " + t4.hour);
        System.out.println("t5.hour = " + t5.hour);
        System.out.println("t6.hour = " + t6.hour);

        // 이처럼 메서드를 사용하니 코드의 수가 굉장히 많이 줄어 가독성이 좋아졌습니다.
    }
}

 

호출 스택

메서드의 작업에 필요한 메모리를 제공하는 공간이다. 메서드가 호출되면 호출 스택에서 메모리를 제공하고, 종료되면 반환한다.

스택 형식이기에 먼저 호출된 스택위에 스택이 쌓이는 구조로, 아래있는 스택이 위에 있는 스택을 호출한다.

위에 스택이 반환되기 전에는 아래 스택이 먼저 반환될 수 없다. 위에 있는 스택부터 차례대로 수행을 마치고 메모리를 반환한 뒤 제거된 후에야 아래 스택이 수행을 하는 것이다. 즉, 하나의 스택에서는 하나의 메서드만 실행할 수 있다.

또한 return이 있는 메서드는 종료되며 결과값을 자신을 호출한 메서드에게 반환하고, 아래 있던 메서드가 넘겨받아 수행을 계속한다.

class CallStack5_1 {

    static void firstMethod() {
        System.out.println("firstMethod()");
        secondMethod();
    }

    static void secondMethod() {
        System.out.println("secondMethod()");
        thirdMethod();
    }

    static void thirdMethod() {
        System.out.println("thirdMethod()");
        finalMethod();
    }

    static void finalMethod(){
        System.out.println("finalMethod()");
    }

    public static void main(String[] args) {
        firstMethod();
    }
}
//firstMethod()
//secondMethod()
//thirdMethod()
//finalMethod()

위 코드를 실행하면 main 호출 -> first 호출 -> println("firstMethod()")호출, 수행 -> println 반환 -> second 호출 -> println("secondMethod()") 호출, 수행 -> println 반환 -> third 호출 -> println("thirdMethod()") 호출, 수행 -> println 반환 ->  final 호출 -> println("finalMethod()") 호출, 수행 -> println 반환 ->  final 반환 -> third 반환 -> second 반환 -> first 반환 ->  main 반환 순으로 진행된다.

class CallStack5_2 {

    static void firstMethod() {
        secondMethod();
        System.out.println("firstMethod()");
    }

    static void secondMethod() {
        thirdMethod();
        System.out.println("secondMethod()");
    }

    static void thirdMethod() {
        finalMethod();
        System.out.println("thirdMethod()");
    }

    static void finalMethod(){
        System.out.println("finalMethod()");
    }

    public static void main(String[] args) {
        firstMethod();
    }
}
//finalMethod()
//thirdMethod()
//secondMethod()
//firstMethod()

반면, 위 코드를 실행하면 main 호출 -> first 호출 -> second 호출 -> third 호출 -> final 호출 -> println("finalMethod()") 호출, 수행 -> println 반환-> final 반환 -> println("thirdMethod()") 호출, 수행 -> println 반환-> third 반환 -> println("secondMethod()") 호출, 수행 -> println 반환-> second 반환 -> println("firstMethod()") 호출, 수행 -> println 반환-> first 반환 -> main 반환 순으로 진행된다.

 

기본형 매개변수와 참조형 매개변수

기본형 매개변수 : 변수의 값을 읽기만 할 수 있다.

참조형 매개변수 : 변수의 값을 읽고 변경할 수 있다.

 

// 기본형 매개변수 예시 코드
class Data6_1 {
    int x; // 기본형
    int y; // 기본형
}

class Data6_1Main {
    public static void main(String[] args) {

        Data6_1 data  = new Data6_1(); // Data6_1()에 객체를 생성하고 data 인스턴스를 할당
        data.x = 10; // data 인스턴스 변수 x에 10 저장
        data.y = 20; // data 인스턴스 변수 y에 20 저장

        System.out.println("Data6_1 클래스로 만든 data 인스턴스의 인스턴스 변수 x, y 값 확인");
        System.out.println("data 인스턴스 변수 x = " + data.x);
        System.out.println("data 인스턴스 변수 y = " + data.y);
        System.out.println();
//  Data6_1 클래스로 만든 data 인스턴스의 인스턴스 변수 x, y 값 확인
//  data 인스턴스 변수 x = 10
//  data 인스턴스 변수 y = 20

        // changeParameter 메서드 의 매개변수에 Data 클래스의 인스턴스 변수를 입력한다.
        System.out.println("입력받은 매개변수의 값을 바꾸는 메서드 수행");
        changeParameter(data.x, data.y); // 이 때 changeParameter를 호출해 아래 결과가 나온다.
//
//  changeParameter 메서드 시작
//  입력 받은 매개변수 x 와 y의 값 확인
//  입력 받은 매개변수 x = 10
//  입력 받은 매개변수 y = 20
//
//  입력 받은 매개변수 x 와 y의 값을 변경 한 후 확인
//  변경 한 후 x = 100
//  변경 한 후 y = 200
//  changeParameter 메서드 끝

        System.out.println();

        // changeParameter(data.x, data.y); 여기서의 data.x 와 data.y 는
        // data 의 인스턴스 변수의 값 그자체가 복사되어 넘어갑니다.
        // 따라서 changeParameter 메서드에서 입력받은 매개변수의 값을 바꿔도
        // 영향을 받지 않습니다.
        System.out.println("Data6_1 클래스로 만든 data 인스턴스의 인스턴스 변수의 값이 변경되었는지 확인");
        System.out.println("changeParameter 메서드 수행 후 data 인스턴스 변수 x = " + data.x);
        System.out.println("changeParameter 메서드 수행 후 data 인스턴스 변수 y = " + data.y);
//  Data6_1 클래스로 만든 data 인스턴스의 인스턴스 변수의 값이 변경되었는지 확인
//  changeParameter 메서드 수행 후 data 인스턴스 변수 x = 10
//  changeParameter 메서드 수행 후 data 인스턴스 변수 y = 20
    }

    static void changeParameter(int x, int y) {   // 기본형
        System.out.println();
        System.out.println("changeParameter 메서드 시작");
        System.out.println("입력 받은 매개변수 x 와 y의 값 확인");
        System.out.println("입력 받은 매개변수 x = " + x);
        System.out.println("입력 받은 매개변수 y = " + y);

        System.out.println();
        System.out.println("입력 받은 매개변수 x 와 y의 값을 변경 한 후 확인");
        x = 100;
        y = 200;
        System.out.println("변경 한 후 x = " + x);
        System.out.println("변경 한 후 y = " + y);
        System.out.println("changeParameter 메서드 끝");
    }
}
class Data6_2 {
    Data6_3  data2 = new Data6_3(); // 참조형
}

class Data6_3 {
    int x; // 기본형
    int y; // 기본형
}

class Data6_2Main {
    public static void main(String[] args) {

        Data6_2 data  = new Data6_2();
        data.data2.x = 10;
        data.data2.y = 20;

        System.out.println("Data6_2 클래스로 만든 data 인스턴스의 data2인스턴스의 인스턴스 변수 값 확인");
        System.out.println("참조변수 data2의 인스턴스 변수 x = " + data.data2.x);
        System.out.println("참조변수 data2의 인스턴스 변수 y = " + data.data2.y);
        System.out.println(); // 여기까진 동일

        // changeParameter 메서드 의 매개변수에 Data6_2 클래스의 참조형 변수인 data2 를 입력
        System.out.println("입력받은 매개변수의 값을 바꾸는 메서드 수행");
        changeParameter(data.data2); // changeParameter가 입력받은 변수의주소를 알기에 이 메서드에서 실행된 결과가 그대로 반영됨.
//        
//        changeParameter(data.data2);
//        changeParameter 메서드 시작
//        입력 받은 매개변수 data2의 인스턴스 x 와 y의 값 확인
//        입력 받은 매개변수 data2의 인스턴스 x = 10
//        입력 받은 매개변수 data2의 인스턴스 y = 20
//
//        입력 받은 매개변수 data2의 인스턴스 x 와 y의 값을 변경 한 후 확인
//        변경 한 후 data2의 인스턴스 x = 100
//        변경 한 후 data2의 인스턴스 y = 200
//        changeParameter 메서드 끝
//
        System.out.println();

        // changeParameter(Data6_3 data2); 여기서 data.data2 는
        // data 인스턴스의 참조형 변수 data2의 주소값이 넘어 갑니다.
        // 따라서 changeParameter 메서드에서 입력받은 data2의 주소값을 통해
        // data2 의 인스턴스에 접근하여 인스턴스 변수를 바꾸기 때문에 영향을 받습니다.
        System.out.println("Data6_3 클래스로 만든 data 인스턴스의 참조변수 data2의 인스턴스 변수 값이 변경되었는지 확인");
        System.out.println("changeParameter 메서드 수행 후 data2의 인스턴스 변수 x = " + data.data2.x);
        System.out.println("changeParameter 메서드 수행 후 data2의 인스턴스 변수 y = " + data.data2.y);
//        Data6_3 클래스로 만든 data 인스턴스의 참조변수 data2의 인스턴스 변수 값이 변경되었는지 확인
//        changeParameter 메서드 수행 후 data2의 인스턴스 변수 x = 100
//        changeParameter 메서드 수행 후 data2의 인스턴스 변수 y = 200
    }

    static void changeParameter(Data6_3 data2) {
        System.out.println();
        System.out.println("changeParameter 메서드 시작");
        System.out.println("입력 받은 매개변수 data2의 인스턴스 x 와 y의 값 확인");
        System.out.println("입력 받은 매개변수 data2의 인스턴스 x = " + data2.x);
        System.out.println("입력 받은 매개변수 data2의 인스턴스 y = " + data2.y);

        System.out.println();
        System.out.println("입력 받은 매개변수 data2의 인스턴스 x 와 y의 값을 변경 한 후 확인");
        data2.x = 100;
        data2.y = 200;
        System.out.println("변경 한 후 data2의 인스턴스 x = " + data2.x);
        System.out.println("변경 한 후 data2의 인스턴스 y = " + data2.y);
        System.out.println("changeParameter 메서드 끝");
    }
}

간단히 말하면, 기본형 매개변수를 불러오면 같은 이름의 새로운 파일을 만든 뒤 그 파일 안에서만 작업하는 것이고, 참조형 매개변수를 불러오면 해당 파일을 열어서 작업하는 것이라 보면 된다.

 

참조형 반환타입

매개변수 뿐만 아니라 반환값도 참조형이 될 수 있다. 모든 참조형 타입의 값은 '객체의 주소'라는 점만 기억하면 크게 다를 것 없다.

class Data3 { int x; }

class Ex6_8 {
    public static void main(String[] args) {
        Data3 d = new Data3(); // Data3에 d라는 인스턴스를 생성하고 Data3에 객체를 생성한 후 주소를 d에 저장
        d.x = 10; // 변수 x의 값을 10으로 한다.

        Data3 d2 = copy(d); // copy를 호출하고 d의 주소를 넘김, copy가 반환한 주소를 d2에 저장
        System.out.println("d.x ="+d.x);
        System.out.println("d2.x ="+d2.x);
//        d.x =10
//        d2.x =10
    }

    static Data3 copy(Data3 d) { // 이 d는 copy메서드에 새로 만든 인스턴스로 이름만 같을 뿐 main에 있는 d와는 별개(주소를 넘겨받아서 주소는 같음)
        Data3 tmp = new Data3(); // Data3에 tmp라는 인스턴스를 생성하고 Data3에 객체를 생성한 후 주소를 tmp에 저장
        tmp.x = d.x; // d가 가리키는 x의 값을 tmp가 가리키는 x에 저장(tmp가 가리키는 x는 copy에서 생성한 x라 기본값 0이였음)
        return tmp; // 복사한 객체의 주소를 반환
    }
}

 

static 메서드(클래스 메서드)

객체 생성 없이 '클래스이름.메서드이름()'으로 호출 : ex) Math.random()
인스턴스 멤버(인스턴스 변수, 인스턴스 메서드) 와 관련없는 작업을 하는 메서드
메서드 내에서 인스턴스 변수 사용 불가능
 
스태틱 메서드 공부중 핸드북에 오류가 있어 공부 중지

'TIL > JAVA' 카테고리의 다른 글

23.04.21  (0) 2023.04.21
23.04.21  (0) 2023.04.21
23.04.14  (0) 2023.04.17
23.04.12  (0) 2023.04.12
23.04.11  (0) 2023.04.11