5. 참조타입

5.1 데이터 타입 분류

자바의 데이터 타입은 크게 기본타입과 참조타입으로 분류된다.
참조 타입이란 객체의 번지를 참조하는 타입으로 배열 열거 클래스 인터페이스 타입이 있다.

객체란? 객체(object)는 데이터와 메소드로 구성된 덩어리이다.
객체 = 데이터(필드) + 메소드
기본 타입으로 선언된 변수와 참조 타입으로 선언된 변수의 차이점은 저장되는 값이다.
기본 타입으로 선언된 변수는 값 자체를 저장하지만 참조 타입은 객체가 생성된 메모리의 번지를 저장함.

String = 참조타입 변수임. 직접 값을 가지고 있지 않음.
String name = "신용권" 일때 name이 신용권을 직접 가지고 있는게아님.

변수들은 스택이라는 메모리 영역에 생성된다. 참조타입 변수는 힙 메모리 영역의 String 객체 번지를 저장하고 이 번지를 통해 String 객체를 참조한다.
https://st-lab.tistory.com/198 메모리 구조
힙[Heap]
힙 영역은 쉽게 말해서 사용자에 의해 관리되는 영역이다. 동적으로 할당 한 변수들이 여기에 저장된다.
자바에서 new연산자로 생성하는 경우 또는 class 참조변수들도 이공간을 차지한다.
낮은 주소에서 높은 주소로 할당된다.

스택 [Stack]
스택 영역은 함수를 호출 할 때 지역변수, 매개변수들이 저장되는 공간이다.
메인(main) 함수안에서의 변수들도 당연 이에 포함된다.
함수가 종료되면 해당 함수에 할당된 변수들을 메모리에서 해제시킨다.
높은주소에서 낮은주소로 메모리에 할당된다.

5.2 메모리 사용영역

JVM이 구동되면 JVM이 운영체제에서 할당 받은 메모리 영역을 구분해서 사용한다.

5.2.1 메소드 영역

바이트코드 파일을 읽은 내용이 저장되는 영역 클래스별로 상수 정적필드 메소드코드 생성자 코드등이 저장
단순히 바이트코드파일의 내용이 저장되는 영역이라고 생각하면된다.

5.2.2 힙영역

힙영역은 객체가 생성되는 영역 객체의 번지는 메소드영역과 스택영역의 상수와 변수에서 참조할수 잇다.

5.2.3 스택영역

스택영역은 메소드를 호출할때마다 생성되는 프레임이 저장되는 영역 메소드 호출이 끝나면 프레임은 자동제거된다.
프레임 내부에는 로컬변수스택이 있다. 여기에서 기본타입변수와 참조타입변수가 생성되고 제거된다.

5.3 참조 타입 변수의 ==, != 연산

==, != 연산자는 변수의 값이 같은지 아닌지를 조사한다. 참조타입변수의 값은 객체의 번지이므로 참조타입변수의 ==, != 연산자는 번지를 비교하는 것이 된다.
번지가 같다면 동일한 객체를 참조하는 것이고 다르다면 다른 객체를 참조하는 것이다.

==, !=연산자로 객체를 비교하는 코드는 if문에서 많이 사용된다.

public class sec03 {
    public static void main(String[] args) {
        int[] arr1; //배열 변수 arr1선언
        int[] arr2; //배열 변수 arr2선언
        int[] arr3; //배열 변수 arr3선언

        arr1 = new int[] {1,2,3}; //배열{1,2,3}을 생성하고 arr1변수에 대입
        arr2 = new int[] {1,2,3}; //배열{1,2,3}을 생성하고 arr2 변수에 대입
        arr3 = arr2; //배열변수 arr2의 값을 배연 변수 arr3에 대입

        System.out.println(arr1 == arr2); //참조하는 객체가 다르므로 false
        System.out.println(arr2 == arr3); //참조하는 객체가 같아서 true
    }
}

5.4 null과 NullPointerException

참조타입 변수는 아직 번지를 저장하지 않다는 뜻으로 null값을 가질 수 있다.
null도 초기화값으로 사용할 수 있기 때문에 null로 초기화된 참조변수는 스택영역에 생성된다.

자바는 프로그램 실행 도중에 발생하는 오류를 예외라고 부른다.
참조 변수를 사용하면서 가장 많이 발생하는 예외중 하나는 NullPointerException이다.

변수가 null인상태에서 객체의 데이터나 메소드를 사용하려할때 이예외가 발생한다.

public class NullPointerExceptionExample {
    public static void main(String[] args) {
        int[] intArray = null;
        intArray[0] = 10; //NullPointerException

        String str = null;
        System.out.println("총 문자 수: " + str.length()); //NullPointerException
    }
}

앞으로 NullPointerException가 발생하면 예외가 발생된 곳에서 null인 상태의 참조변수가 사용되고 있음을 알아야한다.
이것을 해결하려면 참조변수가 객체를 정확히 참조하도록 번지를 대입해야한다.
경우에 따라서는 참조변수에 일부러 null을 대입하기도 한다. 프로그램에서 객체를 사용하려 하면 해당 객체를 참조하는 변수를 이용해야하는데 변수에 null을 대입하면 번지를 잃어 더이상 객체를 사용못하게 된다.
어떤 변수에서도 객체를 참조하지 않으면 해당 객체는 프로그램에서 사용할 수 없는 객체가 된다.
즉 힙 메모리에는 있지만 위치 정보를 모르기 때문에 사용할 수 없게 된다.
자바는 이러한 객체를 쓰레기로 취급하고 쓰레기 수집기(garbage collector)를 실행시켜 자동으로 제거한다.

자바는 코드를 이용해서 객체를 직접 제거하는 방법을 제거하지 않는다. 객체를 제거하는 유일한 방법은 객체의 모든 참조를 없애는 것이다.
다음 코드에서 String객체의 번지에 다른게 대입되면 번지를 잃어버리게 된다.

public class GarbageObjectExample {
    public static void main(String[] args) {
        String hobby = "여행";
        hobby = null; // '여행"에 해당되는 String의 객체를 쓰레기로 만듦

        String kind1 = "자동차";
        String kind2 = kind1; // kind1변수에 저장되어 있는 번지를 kind2변수에 대입
        kind1 = null; // 자동차에 해당하는 String객체는 쓰레가 아님
        System.out.println("kind2: " + kind2);
    }
}

"자동차" <-------이게 하나의 객체임.

5.5 문자열(String) 타입

자바의 문자열은 String객체로 생성된다.
다음 두개는 String변수 name과 hobby를 선언하고 문자열 리터럴을 대입한 것이다.
name 변수와 hobby변수에 문자열 리터럴이 대입되면 문자열은 String객체로 생성되고 객체의 번지가 각각 대입된다.

String name; //String 타입 변수 name선언
name = "홍길동"; //name 변수에 문자열 대입
String hobby = "여행"; //String 타입 변수 hobby를 선언하고 문자열 대입

5.5.1 문자열 비교

자바는 문자열 리터럴이 동일하다면 String객체를 공유하도로 설계되어 있다.(자스성질과 비슷함.)
String name1 = "홍길동";
String name2 = "홍길동";
이러면 번지가 서로 같다.

String은 문자열 리터럴을 그냥 대입하는게 일반적인데 new 연산자로 직접 String객체를 생성하고 대입할수도 있다.
String name1 = new String("홍길동");
String name2 = new String("홍길동");
이러면 각자 서로다른 번지를 가지게 된다.
배열 new로생성하면 각자 다른 번지라는 것을 생각하면 될듯 하다.
String이 단순 문자열을 저장하는 기본타입이 아니라 참조타입이라는 것을 인지하자.

동일한 Stirng객체든 다른 String객체든 상관 없이 내부 문자열만을 비교할 경우에는 String객체의 equals()메소드를 사용한다.

  public class EqualsExample {
      public static void main(String[] args) {
          String strVar1 = "홍길동";
          String strVar2 = "홍길동";

          if (strVar1 == strVar2) {
              System.out.println("strVar1과 strVar2는 참조가 같음");
          } else {
              System.out.println("strVar1과 strVar2는 참조가 다름");
          }

          if(strVar1.equals(strVar2)) {
              System.out.println("strVar1과 strVar2는 문자열이 같음");
          }

          String strVar3 = new String("홍길동");
          String strVar4 = new String("홍길동");

          if (strVar3 == strVar4) {
              System.out.println("strVar3과 strVar4는 참조가 같음");
          } else {
              System.out.println("strVar3과 strVar4는 참조가 다름");
          }

          if(strVar3.equals(strVar4)) {
              System.out.println("strVar1과 strVar2는 문자열이 같음");
          }

          //결과 : 같다 / 같다 / 다르다 / 같다
      }
  }

String변수에 빈문자열 "" 을 대입할 수도 있다. 빈문자열도 String객체로 생성되기때문에 변수가 빈 문자열을 참조하는지 조사하려면 equals()메소드를 사용해야한다.

5.5.2 문자추출

문자열에서 특정위치의 무나즐 얻고 싶다면 charAt()메소드를 이용할 수 있다.
charAt()메소드는 매개값으로 주어진 인덱스의 문자를 리턴한다.
인덱스는 0부터 시작, 띄어쓰기포함한다.
String subject = "자바 프로래밍";
char charValue = subject.charAt(3); //프

public class CharAtExample {
    public static void main(String[] args) {
        String ssn = "9506211230123";
        char sex = ssn.charAt(6);

        switch (sex) {
        case 1:
        case 2:
            System.out.println("남자입니다.");
            break;
        case 3:
        case 4:
            System.out.println("여자입니다.");
            break;
        }
    }
}

주민등록번호에서 성별에 해당하는 7번째 문자를 읽고 남자 또는 여자인지를 출력하는 코드이다.

5.5.3 문자열 길이

문자열에서 문자의 개수를 얻고 싶다면 length() 메소드를 사용한다.
공백을 포함해서 길이를 센다.

public class LengthExample {
    public static void main(String[] args) {
        String ssn = "9506211230123";
        int length = ssn.length();

        if (length == 13) {
            System.out.println("주민등록번호 자릿수가 맞습니다.");
        } else {
            System.out.println("주민등록번호 자릿수가 틀립니다.");
        }
    }
}

5.5.4 문자열 대체

문자열에서 특정 문자열을 다른 문자열로 대체하고 싶다면 replace()메소드를 사용한다.
기존 문자열은 그대로 두고 대체한 새로운 문자열을 리턴한다.
String객체의 문자열은 변경이 불가한 특성을 가지고 있어서 replace()메소드가 리턴하는 문자열은 원래 문자열의 수정본이 아니라 완전히 새로운 문자열이다.
따라서 newStr변수는 새로 생성된 문자열을 참조한다.

  public class ReplaceExample {
      public static void main(String[] args) {
          String oldStr = "자바 문자열은 불변입니다. 자바 문자열은 String입니다.";
          String newStr = oldStr.replace("자바", "JAVA");

          System.out.println(oldStr);
          System.out.println(newStr);
      }
  }

5.5.5 문자열 잘라내기

문자열의 특정위치에서 문자열을 잘라내어 가져오고 싶다면 substring()메소들르 사용한다.
substring(int beginIndex) beginIndex에서 끝까지 잘라내기
substring(int beginIndex, int endIndex) beginIndex에서 endIndex '앞'까지잘라내기

  public class SubStringExample {
      public static void main(String[] args) {
          String ssn = "880815-1234567";

          String firstNum = ssn.substring(0, 6);
          System.out.println(firstNum); //880815

          String secondNum = ssn.substring(7);
          System.out.println(secondNum); //1234567
      }
  }

5.5.6 문자열 찾기

문자열에서 특정 문장려의 위치를 찾고자 할때는 indexOf()메소드를 사용한다.
주어진 문자열이 시작되는 인덱스를 리턴한다.
단순히 포함되어 있는지를 조사하고 싶다면 contains()메소드르 사용하면 편리하다. 포함되어있다면 true리턴한다.

public class IndexOfContainesExample {
    public static void main(String[] args) {
        String subject = "자바 프로그래밍";

        int location = subject.indexOf("프로그래밍");
        System.out.println(location); // 3
        String substring = subject.substring(location); // subject.substring(3);
        System.out.println(substring); // 프로그래밍

        location = subject.indexOf("자바");
        if (location != -1) {
            System.out.println("자바와 관련된 책이군요."); //관련있군요
        } else {
            System.out.println("자바와 관련 없는 책이군요.");
        }

        boolean result = subject.contains("자바");
        if (result) {
            System.out.println("자바와 관련된 책이군요."); //관련있군요
        } else {
            System.out.println("자바와 관련 없는 책이군요.");
        }
    }
}

5.5.7 문자열 분리

문자열이 구분자를 사용하여 여러 개의 문자열로 구성되어있을 경우 이를따로 분리해서 얻고 싶을때 split()메소드를 사용한다.
String board = "번호,제목,내용,성명";
String[] arr = board.split(",");
board가 쉼표로 구분된 문자열을 가지고 있늗네 split()메소드를 호출할때 매개변수로 ','를 제공하면 분리된 문자열로 구성된 배열을 얻을 수 있다.

  public class SpiltExmple {
      public static void main(String[] args) {
          String board = "1,자바 학습,참조타입 String을 학습합니다.,홍길동";

          // 문자열 분리
          String[] tokens = board.split(",");

          // 인덱스 별로 읽기
          System.out.println("번호: " + tokens[0]); //1
          System.out.println("제목: " + tokens[1]); //자바 학습
          System.out.println("내용: " + tokens[2]); //참조타입 String을 학습합니다.
          System.out.println("성명: " + tokens[3]); //홍길동
          System.out.println();

          //for문을 이용한 읽기
          for (int i = 0; i < tokens.length; i++) {
              System.out.println(tokens[i]);
          }
      }
  }

5.6 배열(Array) 타입

변수는 하나의 값만 저장할 수 있다. 따라서 저장해야할 값의 수가 많아지면 그만큼 많은 변수가 필요하다.
예를들어 30명의 학생 성적의 평균을 저장하려면
1.먼저 30개의 변수를 만들어야한다.
2.30개의 변수를 모두 더 하고 나눠야한다.
이게 수백개 수천개 수만개가 되면 매우 비효율적이다.

따라서 많은 양의 값을 다루는 좀 더 효율적인 방버이 필요한데 이것이 배열이다.
배열은 연속된 공간에 값을 나열시키고 각 값에 인덱스를 부여해놓은 자료구조이다.
인덱스는 대괄호 [] 와 함께 사용하여 각 항목의 값을 읽거나 저장하는데 사용된다.
score[0]이런식으로 사용된다.
for문을 활용하면 반복자를 사용해서 score[i]로 쉽게 조회할 수 있다.

배열은 다음과 같은 특징을 가지고 있다.
1.배열은 같은 타입의 값만 관리한다.
2.배열의 길이는 늘리거나 줄일 수 없다.

int배열은 int타입 값만관리하고 String배열은 문자열만 관리한다. 배열은 생성과 동시에 길이가 결정되고 늘리거나 줄일 수 없다.

5.6.1 배열 변수 선언

배열을 사용하기위해서는 배열 변수를 선언해야 한다.
타입[] 변수; 타입 변수[];의 두가지 방법을 사용할 수 있지만 관례적으로 전자를 주로 사용한다.
타입은 배열에 저장될 값의 타입이다.

배열 변수는 참조 변수이다. 배열도 객체이므로 힙 영역에 생성되고 배열 변수는 힙 영역의 배열에 주소를 저장한다.
참조할 배열이 없다면 null로 초기화할 수 있다.
타입[] 변수 = null;

5.6.2 값 목록으로 배열생성

배열에 저장될 값의 목록이 있다면 다음과 같이 간단하게 배열을 생성할 수 있다.
타입[] 변수 = {값0, 값1, 값2, 값3 ...};

중괄호 {}는 나열된 값들을 항목으로 가지는 배열을 힙에 생성하고 번지를 리턴한다. 배열변수는 리턴된 번지를 저장함으로써 참조가 이루어진다.

public class ArrayCreateByValueListExample1 {

    public static void main(String[] args) {
        // 배열 변수 선언과 배열 생성
        String[] season = { "Spring", "Summer", "Fall", "Winter" };

        // 배열의 항목값 얻기
        System.out.println("season[0] : " + season[0]); // Spring
        System.out.println("season[1] : " + season[1]); // Summer
        System.out.println("season[2] : " + season[2]); // Fall
        System.out.println("season[3] : " + season[3]); // Winter

        // 인덱스 1번 항목의 값 변경
        season[1] = "여름";
        System.out.println("season[1] : " + season[1]); // 여름
        System.out.println();

        // 배열 변수 선언과 배열 생성
        int[] scores = { 83, 90, 87 };

        // 총합과 평균 구하기
        int sum = 0;
        for (int i = 0; i < 3; i++) {
            sum += scores[i];
        }
        System.out.println("총합: " + sum); // 260
        double avg = (double) sum / 3;
        System.out.println("평균: " + avg); // 86.666666
    }
}

!!!중괄호 {}로 감싼 값의 목록을 배열 변수에 대입할 때 주의할점!!!
배열 변수를 미리 선언한 후에는 값 목록을 변수에 대입할 수 없다.
int[] arr;
arr = {1,2,3,4,5}; //컴파일 에러

배열 변수를 선언한 시점과 값 목록이 대입되는 시점이 다르다면 new 타입[] 연산자를 사용해야한다.
int[] arr = new int[] {1,2,3,4,5};

메소드의 매개변수가 배열 타입일경우에도 마찬가지이다.
void print(int[] scores){...}
->
print({95,85,90});// 컴파일 에러 발생

매개변수가 이미 선언되어 있고 호출 값목록을 제공하면
print(new int[] {95,85,90});이 되어야 한다.

public class ArrayCreateByValueListExample2 {

    public static void main(String[] args) {
        // 배열 변수 선언
        int[] scores;
        // 배열 변수에 배열을 대입
        scores = new int[] { 83, 90, 87 };
        // 배열 항목의 총합을 구하고 출력
        int sum1 = 0;
        for (int i = 0; i < 3; i++) {
            sum1 += scores[i];
        }
        System.out.println("총합: " + sum1);

        // 배열을 매개값으로 주고 printIten()메소드 호출
        printItem(new int[] { 83, 90, 87 });
    }

    // printItem() 메소드 선언
    public static void printItem(int[] scores) {
        // 매개변수가 참조하는 배열의 항목을 출력
        for (int i = 0; i < 3; i++) {
            System.out.println("score[" + i + "]" + scores[i]);
        }
    }
}

5.6.3 new 연산자로 배열 생성

값의 목록은 없지만 향후 값들을 저장할 목적으로 배열을 미리 생성할 수도 있다. new 연산자를 다음과 같이 사용하면 뱅려 객체를 생성시킨다.
타입[] 변수 = new 타입[길이];
new 연산자는 해당 길이의 배열을 생성하고 배열의 번지를 리턴하기 때문에 배열 변수에 따라 대입할 수 있다.

new 연산자로 배열을 처음생성하면 배열 항목은 기본값으로 초기화 된다.
기본타입
정수 : byte[] short[] int[] = 0 char[] = '\u0000' long[] = 0L
실수 : float[] = 0.0F double[] = 0.0
논리 : boolean[] = false
참조타입
클래스[] 인터페이스[] String[] = null

public class ArrayCreateByNewExample {

    public static void main(String[] args) {
        //배열 변수 선언과 배열 생성
        int[] arr1 = new int[3];
        //배열 항복의 초기값 출력
        for (int i = 0; i < 3; i++) {
            System.out.print("arr1[" + i + "] : " + arr1[i] + ", ");
        }
        System.out.println();
        //배열 항목의 값 변경
        arr1[0] = 10;
        arr1[1] = 20;
        arr1[2] = 30;
        //배열 항목의 변경값 출력
        for (int i = 0; i < 3; i++) {
            System.out.print("arr1[" + i + "] : " + arr1[i] + ", ");
        }
        System.out.println();
        //배열 변수 선언과 배열 생성
        double[] arr2 = new double[3];
        for (int i = 0; i < 3; i++) {
            System.out.print("arr2[" + i + "] : " + arr2[i] + ", ");
        }
        System.out.println();
        String[] arr3 = new String[3];
        for (int i = 0; i < 3; i++) {
            System.out.print("arr3[" + i + "] : " + arr3[i] + ", ");
        }
        //각각 초기값
        //0, 0, 0
        //0.0, 0.0, 0.0
        //null, null, null
    }
}

5.6.4 배열 길이

배열의 길이란 배열에 저장할 수 있는 항목 수를 말한다. 코드에서 배열의 길이를 얻으려면 도트(.)엿난자를 사용해서 배열의 length필드를 읽으면된다.
--> String.length() 이고 array.length인 이유를 알게 된듯하다. String의 길이는 객체의 메소드를 이용하는 것이고 array는 필드값을 읽는 것이다!!!

배열 길이는 for문을 사용해서 전체 배열 항목을 반복할때 많이 사용된다.

  public class ArrayLengthExample {

      public static void main(String[] args) {
          // 배열 변수 선언과 배열대입;
          int[] scores = { 84, 90, 96 };

          // 배열 ㅎ아목의 총합 구하기
          int sum = 0;
          for (int i = 0; i < scores.length; i++) {
              sum += scores[i];
          }
          System.out.println("총합: " + sum);

          //배열 항목의 평균 구하기
          double avg = (double) sum / scores.length;
          System.out.println("평균: " + avg);
      }
  }

for문의 조건식에서 < 연산자를 사용한 이유는 배열의 마지막 인덱스는 배열길이보다 1이 적기때문이다.
인덱스를 초과해서 사용하면 예외가 발생한다.

5.7 다차원배열

배열 항목에는 또 다른 배열이 대입될 수있는데 이러한 배열을 다차원 배열이라고 부른다.
1차원배열을 서로 연결한 것이라고 볼 수 있다.각 차원의 항목에 접근하는 방법은 변수[1차원인덱스][2차원인덱스]...[N차원인덱스]이다.

5.7.1 값목록으로 다차원배열생성

값목록으로 다차원배열을 생성하려면 배열 변수 선언시 타입뒤에 대괄호[]를 차원의 수만큼 붙이고 값목록도 마찬가지로 차원수만큼 중괄호를 중첩시킨다.
타입[][] 변수 = {
{값1,값2,...}
{값3,값4,...}
}
배열의 length필드로 반의 갯수와 학생수를 알 수 있다.
scores.length 반의수
scores[0].length 1반의 학생수

public class MultidimensionalArrayByValueListExample {

public static void main(String[] args) {
    //2차원 배열 생성
    int[][] scores = {
            {80,90,96},
            {76,88}
    };

    //배열의 길이
    System.out.println("1차원 배열 길이(반의 수): " + scores.length);
    System.out.println("2차원 배열 길이(첫 번째 반의 학생 수): " + scores[0].length);
    System.out.println("2차원 배열 길이(두 번째 반의 학생 수): " + scores[1].length);

    //첫 번째 반의 세 번째 학생의 점수 읽기
    System.out.println("scores[0][2]: " + scores[0][2]);

    //두 번째 반의 두 번째 학생 점수 읽기
    System.out.println("scores[1][1]: " + scores[1][1]);

    //첫번째 반의 평균 점수 구하기
    int class1Sum = 0;
    for (int i = 0; i < scores[0].length; i++) {
        class1Sum += scores[0][i];
    }
    double class1Avg = (double) class1Sum / scores[0].length;
    System.out.println("첫 번째 반의 평균 점수: " + class1Avg);

    //두번째 반의 평균 점수 구하기
    int class2Sum = 0;
    for (int i = 0; i < scores[1].length; i++) {
        class2Sum += scores[1][i];
    }
    double class2Avg = (double) class2Sum / scores[1].length;
    System.out.println("두 번째 반의 평균 점수: " + class2Avg);

    //전체 학생의 평균 점수 구하기
    int totalStudent = 0;
    int totalSum = 0;
    for (int i = 0; i < scores.length; i++) {
        totalStudent += scores[i].length;
        for (int j = 0; j < scores[i].length; j++) {
            totalSum += scores[i][j];
        }
    }
    double totalAvg = (double) totalSum / totalStudent;
    System.out.println("전체 학생의 평균 점수: " + totalAvg);
}
}

5.7.2 new 연산자로 다차원 배열 생성

new연산자로 다차원배열을 생성하려면 배열 변수 선언시 타입뒤에 대괄호 []를 차원 수만큼 붙이고 new타입뒤에도 차원수만큼 대괄호를 작성하면된다.
타입[][] 변수 = new 타입[1차원개수][2차원개수]

5.8 객체를 참조하는 배열

기본타입 (byte, char, short, int, long, float, double, boolean)배열은 각 항목에 값을 직접 저장하지만
참조타입은 객체의 번지를 저장한다. String타입의 배열을 생성하고 각 항목에 문자열을 대입햇다고 가정해보자.
배열의 항목은 동일하게 참조타입 변수로 취급된다.

public class ArrayReferenceObjectExample {

    public static void main(String[] args) {
        String[] strArray = new String[3];
        strArray[0] = "Java";
        strArray[1] = "Java";
        strArray[2] = new String("Java");

        System.out.println(strArray[0] == strArray[1]); //true
        System.out.println(strArray[0] == strArray[2]); //false
        System.out.println(strArray[0].equals(strArray[2])); //true
    }
}

5.9 배열복사

배열은 한번 생성하면 길이를 변경할 수 없다. 더 많은 저장공간이 필요하다면 더 큰 길이의 배열을 만들고 이전배열롭터 항목들을 복사해야한다.

가장 기본적인 복사 방법은 for문을 이용해서 하나씩 읽고 새로운 배열에 저장하는 것이다.

public class ArrayCopyByForExample {

    public static void main(String[] args) {
        // 길이 3인 배열
        int[] oldIntArray = { 1, 2, 3 };
        //길이 5인 배열을 새로생성
        int[] newIntArray = new int[5];
        //배열항목 복사
        for (int i = 0; i < oldIntArray.length; i++) {
             newIntArray[i] = oldIntArray[i];
        }
        for (int i = 0; i < newIntArray.length; i++) {
            System.out.print(newIntArray[i] + ", ");
        }
    }
} // 1 , 2, 3, 0 , 0,

배열복사를 위해 좀 더 간단한 방법으로 System의 arraycopy()메소드가 있다.
System.arraycopy(원본배열, 원본배열 복사 시작인덱스, 새배열, 새배열 붙여넣기 사직인덱스, 복사 항목 수);

public class ArrayCopyByForExample {

    public static void main(String[] args) {
        // 길이 3인 배열
        String[] oldStrArray = { "java", "array", "copy" };
        //길이 5인 배열을 새로생성
        String[] newStrArray = new String[5];
        //배열항목 복사
        System.arraycopy(oldStrArray, 0, newStrArray, 0, oldStrArray.length);
        for (int i = 0; i < newStrArray.length; i++) {
            System.out.print(newStrArray[i] + ", ");
        }
    }
} //java, array, copy, null, null, 

5.10 베열 항목 반복을 위한 향상된 for문

자바는 배열 및 컬렉션을 좀 더 쉽게 처리할 목적으로 foreach문을 제공한다.
카운터 변수와 증감식을 사용하지 않고 항목의 개수만큼 반복한 후 자동으로 for문을 빠져나간다.
for (타입 변수 : 배열){실행문} 가져올항목이 없을때까지 실행한다.

public class AdvancedForExample {

    public static void main(String[] args) {
        // 배열 변수 선언과 배열생성
        int[] scores = { 95, 71, 84, 93, 87 };
        // 배열 항목 전체합 구하기
        int sum = 0;
        for (int score : scores) {
            sum += score;
        }
        System.out.println("점수 총합 =  " + sum);
        // 배열 항목 전체 평균 구하기
        double avg = (double) sum / scores.length;
        System.out.println("점수 평균 =  " + avg);
    }
}

향상되엇다고 해서 속도차이가 얼마나 나는지 궁금해서 찾아보니 인덱스가 있는 경우에는 별로 차이가 없다.
짧아서 편하게 사용하라고 만들어진 듯 하다.

5.11 main() 메소드의 String[] 매개변수 용도

자바 프로그램을 실행하기 위해 지금까지 main()메소드를 작성했는데 여기에서 문자열 배열 형태인 String[] args매개변수가 왜필요한지 알아보자.
cmd나 터미널에서 두 수를 입력받고 덧셈을 진행하는 프로그램을 만들어보면 공백으로 구분된 두 숫자는 문자열로 취급되어 String[]배열의 항목값으로 구성된다.
그리고 main()메소드 호출 시 매개 값으로 전달된다. 여긴 또봐도 모르겠다.

5.13 연습문제 성적관리프로그램

  public class No9 {

      public static void main(String[] args) {
          int stnum = 0;
          int[] arr = null;

          boolean bo = true;
          while(bo) {

              int menu = mainmenu();

              switch (menu) {

              case 1:
                  stnum = stnum();
                  arr = new int[stnum];
                  break;
              case 2:
                  input(arr);
                  break;
              case 3:
                  list(arr);
                  break;
              case 4: 
                  analyze(arr);
                  break;
              case 5:
                  System.out.println("프로그램 종료");
                  bo = false;
                  break;
              }
          }

      }

      public static void analyze(int[] arr) {
          int max = 0;
          int sum = 0;
          for (int i = 0; i < arr.length; i++) {
              sum += arr[i];
              if(arr[i]> max) {
                  max = arr[i];
              }
          }
          System.out.println("최고 점수: " + max);
          System.out.println("평균 점수: " + (double)sum / arr.length);
      }


      public static void list(int[] arr) {
          for (int i = 0; i < arr.length; i++) {
              System.out.println("arr["+ i + "]: " + arr[i]);
          }
      }


      public static int mainmenu() {
          System.out.println("---------------------------------------------------");
          System.out.println("1.학생수 |2.점수입력 |3.점수리스트 |4.분석 | 5.종료");
          System.out.println("---------------------------------------------------");
          Scanner sc = new Scanner(System.in);
          System.out.print("선택> ");
          int menu = Integer.parseInt(sc.nextLine());
          return menu;
      }


      public static void input(int[] arr) {
          Scanner sc = new Scanner(System.in);
          for (int i = 0; i < arr.length; i++) {
              System.out.print("arr[" +  i +"]" + "> ");
              arr[i]= Integer.parseInt(sc.nextLine());
          }
      }


      public static int stnum() {
          Scanner sc = new Scanner(System.in);
          System.out.print("학생수> ");
          int num = Integer.parseInt(sc.nextLine());

          return num;
      }
  }

2023.02.15 후기

수업시간에 진돌르 나가며 남은 시간 알아서 먼저 나가는 방법을 택하였다. 다시 보면서 느끼는 점은 두번이나 보면서 정말 다 봤다고 생각했는데 기억하지 못하는 부분이 참 많다는 것이었다.
자바의 기초를 다지는게 중요하다. 시간이 남을때 마다 알고리즘 문제를 같이 공부하고자 한다.

charAt 안배운줄알앗는데 배운거엿다.
System.arraycopy(원본배열, 원본배열 복사 시작인덱스, 새배열, 새배열 붙여넣기 사직인덱스, 복사 항목 수);
매우 편하다. 알아두었다가 사용할일이 있으면 사용하도록 하자.

'기초단계 > JAVA' 카테고리의 다른 글

2023.02.16-2 Java 복습  (1) 2023.02.16
2023.02.16-1 Java 복습  (0) 2023.02.16
2023.02.15-1 Java 복습  (0) 2023.02.15
2023.02.14 Java 복습  (0) 2023.02.14
2023.02.13 Java 복습  (0) 2023.02.13

+ Recent posts