Java/[inflearn] 자바 입문

[김영한_자바기본][2.기본형과 참조형] (보충) 기본형 / 참조형 - 메서드, 문제 풀이 해석 (p.11-20, p.30-34)

줌인. 2024. 2. 2. 10:51

▶ 기본형과 참조형 이해

https://zoooom-in.tistory.com/45

 

[김영한_자바기본][2.기본형과 참조형] 기본형 / 참조형 이해 (p.1-6)

참조값에 접근한다는 것은 설계도와 부지 위치에 접근해서 같이 공동 작업을 하는 것이다. 기본형은 실제 값이 저장되어 독립적으로 관리되지만, 참조형은 변수에는 객체 위치(참조값)가 저장

zoooom-in.tistory.com

 

1. 기본형 vs 참조형 - 메서드 호출

[p.11 / 기본형 메서드 호출] 각 스코프로 분리해서 보기 - void로 return받는 값이 없음

public static void main(String[] args) {
    int a = 10;
    System.out.println("메서드 호출 전 a = " + a);
    changePrimitive(a); //값을 돌려받지 않음 왜냐면 아래는 void - return할게 없음
    System.out.println("메서드 호출 후 a = " + a);
}

static void changePrimitive(int x) {
    x = 20;
}

 

[p.13 / 참조형 메서드 호출] dataA와 dataX로 생각하지말고, 참조값(위치)을 던진다고 생각해라 or 설계도 연산

public static void main(String[] args) {
    Data dataA = new Data();
    dataA.value = 10;
    System.out.println("메서드 호출 전 dataA.value = " + dataA.value);
    changeReference(dataA);
    System.out.println("메서드 호출 후 dataA.value = " + dataA.value);
}

static void changeReference(Data dataX) {
    dataX.value = 20;
}

메서드에서 `Data` 타입의 객체를 매개변수로 받는 이유는 Java에서는 객체를 참조로 전달하기 때문이다. 
따라서  `dataX`는 `dataA`가 참조하는 객체를 참조하게 됩니다. 
즉 해당 메서드는 같은 객체를 참조하는 참조 변수를 사용하여 해당 객체의 내용을 변경하는 역할을 한다. 

 

 

 

'void' 기준
기본형 : 값이 복사되어 전달되며, 메서드 내부에서 매개변수를 변경해도 호출 변수 값에는 영향이 없다.
참조형 : 참조값이 복사되어 전달되며, 메서드 내부에서 매개변수로 변경하면 호출자의 객체도 변경된다.

 

 


 

 

2. 참조형과 메서드 호출 - 활용

[p.17 / Method1] 메서드에 객체 전달

public static void main(String[] args) {
    Student student1 = new Student();
    inputData(student1, "학생1", 15, 90);

    Student student2 = new Student();
    inputData(student2, "학생2", 16, 80);

    printData(student1);
    printData(student2);
}

static void inputData(Student student, String name, int age, int grade) {
    student.name = name;
    student.age = age;
    student.grade = grade;
}

static void printData(Student student) {
    System.out.println("이름 : " + student.name + ", 나이 : " + student.age + ", 성적 : " + student.grade);
}

 

[p.17 / Method1_inputData 발췌] `(Student student, String name, int age, int grade)`: 메서드의 매개변수 목록

static void inputData(Student student, String name, int age, int grade) {
    student.name = name;
    student.age = age;
    student.grade = grade;
}

- 메서드에 객체 전달

- Student 클래스의 객체를 받아와서 해당 객체의 name, age, grade필드에 값을 설정하는 역할을 합니다.

   ex) name 호출자에서 받아온 것을 student 참조값 위치중 name에 해당하는 곳에 데이터를 입력한다.

 

 

[p.19 / Method2] 메서드에서 객체 반환

public static void main(String[] args) {
    Student student1 = inputData("학생1", 15, 90);
    Student student2 = inputData("학생2", 16, 80);

    printData(student1);
    printData(student2);
}

static Student inputData(String name, int age, int grade) {
    Student student = new Student();
    student.name = name;
    student.age = age;
    student.grade = grade;
    return student;
}

static void printData(Student student) {
    System.out.println("이름 : " + student.name + ", 나이 : " + student.age + ", 성적 : " + student.grade);
}

 

[p.19 / Method2_inputData 발췌] 메서드 & 객체 생성 함께 // 참조형 student 반환 (참조를 받을 수 있는 Student 타입)

static Student inputData(String name, int age, int grade) { //메서드 생성 영역
    Student student = new Student(); //객체(인스턴스)를 생성하는 영역
    student.name = name;
    student.age = age;
    student.grade = grade;
    return student;
}

- 메서드에서 객체 반환, 메서드에서 객체 생성과 초기값 세팅이 함께 이루어짐

- 메서드 밖에서 사용할 수 있도록 돌려주어야 함

 

* 객체 전달 : 메서드 매개변수로 객체를 전달해 메서드 내부에서 객체의 상태를 변경/활용할 수 있다.
   이는 객체 참조를 전달하므로, 메서드에서의 변경이 호출자에게 영향을 미친다.

* 객체 반환 : 메서드에서
생성 or 초기화한 객체를 반환하며,
이는 호출자가 변수에 할당하거나 직접 활용할 수 있다.

 

 


 

 

3. 기본형과 참조형 - 문제 풀이

[p.30 / ProductOrder_멤버변수] 상품명 / 가격 / 주문수량 : 멤버변수 포함

public class ProductOrder {
    String productName;
    int price;
    int quantity;
}

 

[p.30 / ProductOrderMain] 원본 코드

public static void main(String[] args) {
    ProductOrder[] orders = new ProductOrder[3];

    ProductOrder order1 = new ProductOrder();
    order1.productName = "두부";
    order1.price = 2000;
    order1.quantity = 2;
    orders[0] = order1;

    ProductOrder order2 = new ProductOrder();
    order2.productName = "김치";
    order2.price = 5000;
    order2.quantity = 1;
    orders[1] = order2;

    ProductOrder order3 = new ProductOrder();
    order3.productName = "콜라";
    order3.price = 1500;
    order3.quantity = 2;
    orders[2] = order3;

    int sum = 0;
    for (ProductOrder order : orders) {
        System.out.println("상품명 : " + order.productName + ", 가격 : " + order.price + ", 수량 : " + order.quantity);
        sum += (order.quantity * order.price);
    }
    System.out.println("총 결제 금액 : " + sum);
}

 

[p.31 / ProductOrderMain2] 상품 주문 정보 배열로 관리, 정보 출력 및 최종 결제 금액 계산 출력

public static void main(String[] args) {
    // 여러 상품의 주문 정보를 담는 배열 생성
    // createOrder()를 여러번 사용해서 상품 주문 정보들을 생성하고 배열에 저장
    // printOrders()를 사용해서 상품 주문 정보 출력
    // getTotalAmount()를 사용해서 총 결제 금액 계산
    // 총 결제 금액 출력
}

- 매개변수로 초기값 생성, productorder 반환

- 배열을 받아 상품명/가격/수량 출력

- 배열을 받아 총 결제 금액을 계산하고 계산 결과 반환

 

[p.31 / ProductOrderMain2 _출력 예시]

상품명: 두부, 가격: 2000, 수량: 2
상품명: 김치, 가격: 5000, 수량: 1
상품명: 콜라, 가격: 1500, 수량: 2
총 결제 금액: 12000

 

↓ (원본 코드와 비교) ↓

 

참조형의 기본/본래 코드를 보면 메서드 매개변수에 무엇을 대입해야하는지 알 수 있다

 

 

 

[p.32 / ProductOrderMain2_(1)] 매개변수로 초기값 생성, productorder 반환

public static void main(String[] args) {
    ProductOrder[] orders = new ProductOrder[3];

    ProductOrder order1 = createOrder("두부", 2000, 2);
    orders[0] = order1;

    ProductOrder order2 = createOrder("김치",5000, 1);
    orders[1] = order2;

    ProductOrder order3 = createOrder("콜라", 1500, 2);
    orders[2] = order3;
}

static ProductOrder createOrder(String productName, int price, int quantity) {
    ProductOrder order = new ProductOrder();
    order.productName = productName;
    order.price = price;
    order.quantity = quantity;
    return order;
}

1) 매개변수로 초기값 생성 : (String productName, int price, int quantity) 파라미터 이용

    ⇒ 각 위치에 맞게 파라미터 변수를 모두 대입

   ex) order 설계도 위치의 프로덕트에 값이 들어가는 것 == 초기값 생성

 

2) ProductOrder반환 : return을 통해 ProductOrder형 변수를 반환한다. 

    ⇒ 따라서 ProductOrder형 변수를 통한 객체 생성을 이룬다. // 그리고 createorder엔 위치를 반환하며 배열에 넣는다.

        (코드의 효율적 관리화 간결화를 위해 객체 생성과 초기화를 동시에 진행한다.)

 

 

[p. 30 / ProductOrderMain1] 원본 코드 (응용)

for (ProductOrder order : orders) {
    System.out.println("상품명 : " + order.productName + ", 가격 : " + order.price + ", 수량 : " + order.quantity);
    sum += (order.quantity * order.price);
}

 

[p.32 / ProductOrderMain2_(2)] 배열을 받아 상품명/가격/수량 출력 : for의 기능을 보면 이해(묶음 순회)할 수 있다.

printData(orders);
static void printData(ProductOrder[] orders) {
    for (ProductOrder order : orders) {
        System.out.println("상품명 : " + order.productName + ", 가격 : " + order.price + ", 
                            수량 : " + order.quantity);
    }
}

 - 상기 코드를 보면 (향상된) for문은 그대로 복사하였다. >> 사용할 수 있는 파라미터 생각

 - `ProductOrder[] orders`를 파라미터로 넣는 이유는 해당 메서드가 주어진 `ProductOrder` 배열에 저장된 데이터를

    출력하기 위함이다. 이 메서드는 배열에 담긴 `ProductOrder` 객체들의 정보를 순회하며 출력하는 역할을 수행한다.
    ∴ 배열 내의 각 `ProductOrder` 객체의 상품명, 가격, 수량을 출력하는 것이 목적이다.

    ⇒ 파라미터로 배열을 받으면 이 메서드는 어떤 `ProductOrder` 배열이든 받아서 출력할 수 있다.

 

 

[p.32 / ProductOrderMain2_(3)] 배열을 받아 총 결제 금액을 계산하고, 계산 결과를 반환

int sum = 0;
sum += totalData(orders);
System.out.println("총 결제 금액 : " + sum);
static int totalData(ProductOrder[] orders) {
    int sum = 0;
    for (ProductOrder order : orders) {
        sum += (order.quantity * order.price);
    }
    return sum;
}

 


[p.33 / ProductOrderMain] Scanner값 입력받기

- 주문 수량 입력받기 (ex. 입력할 주문의 개수를 입력하세요)

- 가격/수량/상품명 입력받기 (ex. n번째 주문 정보를 입력하세요)

- 입력이 끝나면 등록한 상품과 총 결제 금액 출력하기

 

[p.33 / ProductOrderMain3 _출력 예시]

입력할 주문의 개수를 입력하세요: 3

1번째 주문 정보를 입력하세요.
상품명: 두부
가격: 2000
수량: 2

2번째 주문 정보를 입력하세요.
상품명: 김치
가격: 5000
수량: 1

3번째 주문 정보를 입력하세요.
상품명: 콜라
가격: 1500
수량: 2
상품명: 두부, 가격: 2000, 수량: 2
상품명: 김치, 가격: 5000, 수량: 1
상품명: 콜라, 가격: 1500, 수량: 2

총 결제 금액: 12000

 

[p.33 / ProductOrderMain3_(1)] 주문 수량 입력받기 (ex. 입력할 주문의 개수를 입력하세요) - Scanner 부여

Scanner scanner = new Scanner(System.in);
System.out.print("입력할 주문의 개수를 입력하세요 : ");
int count = scanner.nextInt();
scanner.nextLine();

System.out.println();
ProductOrder[] orders = new ProductOrder[count];

 

 

[p. 33 / ProductOrderMain3] 원본 코드 (응용)

ProductOrder[] orders = new ProductOrder[count];

ProductOrder order1 = createOrder("두부", 2000, 2);
orders[0] = order1;

 

[p.33 / ProductOrderMain3_(2)] 가격/수량/상품명 입력받기 ⇒ 배열 출력과 데이터 입력을 생각하면 됨

ProductOrder[] orders = new ProductOrder[count];

//배열 orders 입력값을 배열화해서 데이터 입력 + 기존 createOrder활용
for (int i = 0; i < count ; i++) {
    System.out.println((i+1) + "번째 주문 정보를 입력하세요");

    System.out.print("상품명 : ");
    String productName = scanner.nextLine(); //기존 createOrder에 받을 입력값 변수

    System.out.print("가격 : ");
    int price = scanner.nextInt();

    System.out.print("수량 : ");
    int quantity = scanner.nextInt();
    scanner.nextLine();

    orders[i] = createOrder(productName, price, quantity); //create 메서드 동일 이용
    // 1) order1  , , 2) orders[0] = order1대입 , , 첫번째 주문이라고 생각 ((통합))
}

- createOrder의 의미가 각 order를 의미한다 (ex. orders1)

  즉 이는 orders[0] = orders1(참조값);을 내포하고 참조값 자체에 갑을 대입하는 구조로 이해하면 된다.

 

 

 

▶ 배열의 생성과 선언 이해

https://zoooom-in.tistory.com/44

 

[김영한_자바입문][9.배열] 배열의 선언과 생성 이해하기 (p.2-7)

배열 선언은 아파트 부지 확보, 생성은 몇 개의 아파트를 확보할 것인지 배열의 값 할당은 부지를 참조해 실제 준공일을 기입한다. 할당 전까지는 부지 주소만 참조되어 나타난다. [코드 읽기 전

zoooom-in.tistory.com

 

728x90