인프런 커뮤니티 질문&답변

잇택잇님의 프로필 이미지
잇택잇

작성한 질문수

자바 기초부터 마스터하기 with 은종쌤 (Do it 자바 프로그래밍 입문) - Part 2(마스터편)

여러 가지 자료구조에 대해 알아봅시다.

컬렉션 프레임워크에서 get()

작성

·

226

·

수정됨

0

ArrayList<String> a = new ArrayList<>();
a.add("1");
a.add("2");
a.add("3");

int[] arr = {1, 2, 3};

 arr[0] = 4; // 가능
 a.get(0) = "one"; // 불가능
  1. 위와 같이 배열도 ArrayList 객체도 모두 Reference type입니다. 배열에 대한 인덱스 접근은 r-value, l-value로 모두 기능할 수 있는데 ArrayList에 대한 get()은 r-value(값으로만 사용)로써만 기능하고 있습니다.

  • get()의 반환형이 E로 제네릭(객체)인데 read only로 취급되는건가요...?

  • get()으로 해당 위치를 참조하는게 아닌건가요?

  • 해당 메모리가 아닌 메모리의 값을 꺼내오는건가요?

 

HashMap<String, String> h1 = new HashMap<>();
h1.put("1", "one");
h1.get("1") = "하나"; // 불가능
  1. 다른 컬렉션 프레임워크지만 동일한 문제입니다.

    put(key, value)를 사용해 값을 저장하고 get(key)를 사용해 value를 가져올 때 get()으로 값을 바꿀 수는 없는 건가요?

     

HashMap<String, ArrayList<String>> hashMap = new HashMap<>();
hashMap.get(date).add(Obj); // 가능
  1. 이 경우에는 get()으로 참조한 메모리에 대해 다시 참조하여 메서드 사용이 가능했습니다. 이러한 동작이 get()으로 값을 반환하는 것이 아니라 객체 메모리에 접근한다고 생각했습니다.

 

  1. 위에 질문과 함께 조금 더 직관적인 질문 드립니다. 

    public static void main(String[] args) {
//        Calendar calendar = new Calendar();
//        calendar.run();
        HashMap<String, String> h = new HashMap<>();
        h.put("1", "before");
        System.out.println(h.get("1").equals("1")); // 참조하여 메서드 동작 확인
        h.get("1") = "after";   // 불가능 => 왜 안되는지?
        
        String str = "before";
        System.out.println(str.equals("before"));   // 참조하여 메서드 동작 확인
        System.out.println(str);
        str = "after"; // 변경 가능 => 왜 되는지?
        System.out.println(str);
    }

위 코드에서 각각 get()과 참조 변수 자체로 접근하였습니다.

get()으로는 메서드까지는 접근이 가능하나 값 변경이 안되었고

참조변수는 메서드 접근은 물론 값 변경(엄밀히 말하면 참조 변경)까지 되었습니다.

이유가 궁금합니다.

 

감사합니다.

답변 2

0

박은종님의 프로필 이미지
박은종
지식공유자

예... 객체의 경우 참조변수가 반환되는것이고, 그 경우 값을 넣는것은 허용되지 않습니다. C++ const 키워드를 생각하시면 되겠네요~

잇택잇님의 프로필 이미지
잇택잇
질문자

아! const 참조변수의 형태로 반환된다는 말씀이네요!

C++로 설명을 도와주시니 더 명확히 이해됐습니다! 감사합니다!

0

박은종님의 프로필 이미지
박은종
지식공유자

get() 메서드의 경우는 컬렉션 요소의 값을 가져오는 기능을 합니다. help를 보시면 반환값이 <E> 인것을 보실 수 있는데 이는 그 값을 반환하겠다는 의미입니다. 반환된 값은 객체나 기본 테이터인 경우 그 값인데, 그 값에 무언가를 넣은다는것은 가능하지 않습니다. 마치 1 = 3; 과 같은 결과가 되는 것입니다. 따라서 값을 넣을때는 해당 메모리에 값이 대입되는 메서드를 사용하는 것이 맞습니다. 말씀하신대로 변수인 경우는 l-value와 r-value가 모두 가능하지만, 상수인 경우는 l-value가 안되는것과 같은 경우입니다.

잇택잇님의 프로필 이미지
잇택잇
질문자

감사합니다!

말씀하신 "반환된 값은 객체나 기본 테이터인 경우 그 값인데"의 부분에서 객체의 경우 내부적인 값은 객체 메모리 주소의 형태로 참조가 반환되는 것이고 primitive type인 경우 stack에 저장된 값 그 자체가 반환된다로 이해해도 괜찮을까요?

 

즉 C/C++ 기준으로 reference type인 경우 주소 상수가 반환되고 prmitive인 경우 값이 반환됨로 생각해도 될까요?

잇택잇님의 프로필 이미지
잇택잇

작성한 질문수

질문하기