[Java] 자바를 공부하며 깨달은 것들

Updated:

잡다한 Java 지식

Java를 공부하던 중 궁금한 것들을 여기저기 물어보고 얻은 지식들이 휘발되지 않게 정리한 글이다

1. Java의 toString()

의문점의 시작은 아래의 코드로부터 시작되었다. 간단한 코드니 한번 읽어보자

public class CharArrMain {
    public static void main(String[] args) {
        char[] charArr = {'h', 'e', 'l', 'l', 'o'};
        System.out.println("charArr = " + charArr);
        System.out.println(charArr);
    }
}
  • 보다시피 charArr라는 char형 배열이 존재하고 이를 2가지 방식으로 출력해보았다
  • 하나는 문자열 + char형 배열의 구조이고 다른 하나는 그냥 char형 배열이다

아직은 실력이 부족해 같은 charArr 값이 출력될거라고 예상했지만 실제 출력 값은 아래와 같다

charArr = [C@a09ee92
hello
  • 문자열 + 배열이 합쳐지면 Object의 toString()이 호출되어 배열의 해시값과 문자열이 합해진다
  • 예외적으로 char형 배열은 오버로딩된 println(char[] x)이 호출되어 해당 배열에 든 실제 문자열이 출력된다
    • 실제로 char형 배열을 제외한 다른 배열들은 println() 내부에 해당 배열값만 전달되어도 해시값이 출력된다

위와 같은 이유로 서로 다른 출력값이 발생하였음을 확인하였다. 하지만 이것으로는 부족하다고 생각하여 다른 케이스에 대해서도 살펴보았다. 추가적인 궁금점은 아래와 같았다

  • char형 배열이 아닌 다른 배열 혹은 객체와 문자열이 합쳐지면 어떻게 동작하는가?

결론부터 말하자면 아래와 같다

  1. 문자열 + Primitive Type
    • 각 기본 데이터 타입마다의 오버로딩된 String.valueOf() 메서드에 의해 해당 값을 문자열로 변환
    • 문자열 + 변환된 문자열의 결과로 최종 문자열이 출력
  2. 문자열 + 객체(배열 포함)
    • 객체의 toString() 메서드를 호출하여 문자열로 변환
    • 객체의 경우 오버라이딩된 toString()이 존재한다면 해당 메서드로 아닐경우 Object의 toString() 메서드 호출
    • 배열의 경우 무조건 Object의 toString() 메서드 호출

즉, System.out.println("charArr = " + charArr)문자열 + 객체 케이스로 toString()이 호출되어 최종적으로 해시값이 담긴 문자열이 출력된 것이고 System.out.println(charArr)는 애초부터 println()에서 해당 값을 char형 배열로 인지하여 오버로딩된 println(char[] x)이 호출되어 실제 문자열이 출력된 것이라 이해하면 된다

2. Java의 메모리구조

언젠가는 한번 정리하고 가야하는 Java의 메모리 구조이다

java1

  • Java의 메모리 구조는 크게 메서드, 스택, 힙 3가지로 구성된다

아래 코드를 살펴보며 각각의 변수 및 메서드가 어디에 저장되는지 살펴보자

public class MemoryExample {
  
    static int staticVar = 10;
    int instanceVar = 20;

    public static void staticMethod() {
        int localVar = 30;
        MemoryExample obj = new MemoryExample();
        obj.instanceMethod();
    }

    public void instanceMethod() {
        int localVar = 40;
        System.out.println("Instance Method");
    }

    public static void main(String[] args) {
        staticMethod();
    }
}
  1. 메서드 영역

    • 클래스 정보(클래스의 바이트코드, 메서드 및 필드) 및 static 변수, static 메서드가 저장되는 공간
    • JVM이 동작하고 클래스가 로딩될때 생성되며 모든 스레드에 공유되어 어디서나 접근 가능하다
    • 위의 코드에서 staticVar, staticMethod(), instanceMethod(), main()이 이 영역이 저장된다
  2. 힙 영역

    • new 키워드를 통해 생성된 객체들 및 인스턴스 변수가 저장되는 공간
    • 위의 코드에서 instanceVarnew MemoryExample()을 통해서 생성된 데이터가 이 영역에 저장된다
  3. 스택 영역

    • 지역변수 및 매개변수가 저장되는 공간
      • 각 메서드 호출 시마다 스택 프레임이 생성되고 메서드 내의 지역변수, 매개변수들이 해당 스택 프레임에 저장된다
    • 추가적으로 new MemoryExample()을 통해 생성된 인스턴스는 힙영역에 저장되지만 해당 인스턴스값인 obj는 이 영역에 저장된다

Tags:

Categories:

Updated:

Leave a comment