이 포스팅은 공부 목적으로 작성된 포스팅입니다 왜곡된 내용이 포함되어 있을 수 있습니다.
이번 글은 특히 심합니다

자바공부 도중 이해되지 않는 메소드가 있어서 포스팅을 작성한다.
https://bluesparrow.tistory.com/60
[이펙티브 자바] 아이템 54, 55
이 포스팅은 공부 목적으로 작성된 포스팅입니다. 왜곡된 내용이 포함되어 있을 수 있습니다. 54 null이 아닌, 빈 컬렉션이나 배열을 반환하라다음 코드를 보자private final List ObjectInStock = new ArrayLi
bluesparrow.tistory.com
다음 코드를 보자
public Cheese[] getCheeses(){
return cheesesInStock.toArray(new Cheese[0]);
}
컬렉션을 배열로 반환할때 만약 컬렉션이 empty하다면 null이 아닌, 길이가 0인 배열을 반환하는 코드이다. 배열을 반환하기 위해 List의 toArray() 메소드를 사용하여 배열을 반환하였다.
코드만 보았을때는 길이 0인 배열로 변환하는 것으로 추측해볼 수 있는데 몇가지 이상한점이 있다.
- 길이가 0인지 확인하지 않는다.(길이가 0인경우와 그렇지 않은경우에도 문제 없이 진행된다고 느껴지긴 한다.)
- 파라미터가 이상하다.(타입도 아닌 인스턴스 형태이다)
- 파라미터의 인스턴스의 배열 길이가 0이다.(무조건 길이가 0인 배열을 반환한다고 느껴진다.)
- 네이밍이 어색하게 느껴진다.(toArray는 파라미터가 없는게 자연스럽다.)
toArray 함수를 자세히 보면서 살펴보자
toArray()
다음은 List에서 선언되어 있는 toArray()메소드 설명이다.
<T> T[] toArray(T[] a);
Lists that support this operation may place limitations on what elements may be added to this list. In particular, some lists will refuse to add null elements, and others will impose restrictions on the type of elements that may be added. List classes should clearly specify in their documentation any restrictions on what elements may be added.
리스트에 element를 추가하는 것에 대해서 제한을 두고 리스트에 element의 limitation을 정할 수 있다고 한다.
잘 이해되지 않는다. 실제 구현체를 보자
public <T> T[] toArray(T[] a) {
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
위 코드는 ArrayList에서의 toArray 구현이다.
- 리스트의 길이보다 파라미터 배열의 길이가 짧다면, 배열의 타입에 해당하는 배열을 copy하여(깊은 복사) 반환한다.(리스트를 작아서 )
- 리스트의 길이보다 파라미터 배열의 길이가 길다면, 리스트 값을 배열로 복사하고 리스트마지막 index + 1 값(size)을 null로 지정
- 리스트의 길이보다 파라미터의 배열의 길이가 같다면 배열 copy 후 반환



실제 구현내용이 예상했던 내용과 다르게 되어 있다. 요약하자면 리스트를 배열로 변환하고 파라미터 리스트의 타입에 해당하는 값으로 가져온다는 것이다. 처음에 생각했던 의구심을 하나씩 풀어보자
길이가 0인지 확인하지 않는다.
상관없다. 길이가 0이든 양수 값이든 로직에 문제가 생기지 않는다
파라미터가 이상하다.
파라미터에 배열을 넣는 것이 다소 이질적으로 느껴진다. 심지어 배열의 내부 값들을 사용하지 않는다.
구현함수를 보면 해당 파라미터에 해당하는 인스턴스에 값을 넣는 것을 확인할 수 있다.(조건 1의 경우는 예외)
배열을 내부적으로 생성하지 않고 파라미터값을 사용한다는 것은 아직 납득되지 않는 부분이다.
일단 타입은 반드시 알려줘야한다.
제네릭은 컴파일 타임에 타입이 정해지기 때문에 어떤 배열로 변환할 것인지 알려줘야 한다.
그렇다면 파라미터에서 배열을 String.class와 같이 클래스를 통해 알려주면 안됬을까?
일단 파라미터의 필요성은 느껴진다.
그래도 아직까지는 파라미터를 굳이 저렇게 선언해야했을까?
파라미터의 인스턴스의 배열 길이가 0이다.
이건 하기 나름이다. 어짜피 크면 새로 배열을 만들어서...
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
다만 주의해야하는 경우가 있는데 파라미터의 배열의 길이가 리스트의 길이보다 클경우 리스트 길이 인덱스는 null 값이고 뒤의 값들은 기존 값들을 가져간다
List<Integer> list = new ArrayList<>();
list.add(1);
Integer[] integers = new Integer[6];
for (int i = 0; i < 6; i++)
integers[i] = i;
Integer[] array = list.toArray(integers);
for (Integer integer : array) {
System.out.println("integer = " + integer);
}
네이밍이 어색하게 느껴진다.
사실 파라미터가 없으면 문제가 없다. 실제로도 toArray() 함수가 있다. 그러면 toArray(T[] a)가 도대체 왜 만들었을까?
toArray(T[] a)의 필요성 이전에 toArray(T[] a)의 구현체가 저럴 수 밖에 없는 이유에 대해 알아보자
결국 제네릭
이전에 배열의 타입에 대해 명시해야하는 필요성이 있었다. 그러면 배열의 타입만 넘기면 될거 같은데 Integer와 Integer[]는 서로 다른 타입이다. 그런데 integer[]임을 표시할 수 없는 것 같다.(적어도 런타임에 그렇다) 따라서 인스턴스를 넘겨 해당 인스턴스에 해당하는 타입의 배열을 만들 수 있게되는 것이다.(배열이 클래스 리터럴이 불가능하다고 알고 있는데 관련이 있는 것 같다.) 따라서 원하는 배열의 타입이 있다면 파라미터에 명세해야하는 것이다. 게다가 제네릭은 런타임에서 타입을 확인할 수 없다는 점을 생각해보면 인스턴스 자체를 넘겨야 한다는 것이 납득된다

사용성
그러면 파라미터가 없는 ToArray()는 타입을 어떻게 체크할까? ToArray() 는 Object로 반환된다. 그러면 ToArray(T[] a) 은 언제 사용할까? 타입 변환을 하고 싶은 경우이자 타입 변환이 가능한 경우-> 업캐스팅, 다운캐스팅!

'Java' 카테고리의 다른 글
[이펙티브 자바] 아이템 64, 65, 66, 67, 6 (0) | 2024.06.18 |
---|---|
[이펙티브 자바] 아이템 54, 55 (0) | 2024.05.20 |
[이펙티브 자바] 아이템 47, 48, 49 (2) | 2024.04.27 |
[이펙티브 자바] 아이템 39, 40, 41 (1) | 2024.03.24 |
[이펙티브 자바] 아이템 10, 11 (2) | 2024.01.14 |
이 포스팅은 공부 목적으로 작성된 포스팅입니다 왜곡된 내용이 포함되어 있을 수 있습니다.
이번 글은 특히 심합니다

자바공부 도중 이해되지 않는 메소드가 있어서 포스팅을 작성한다.
https://bluesparrow.tistory.com/60
[이펙티브 자바] 아이템 54, 55
이 포스팅은 공부 목적으로 작성된 포스팅입니다. 왜곡된 내용이 포함되어 있을 수 있습니다. 54 null이 아닌, 빈 컬렉션이나 배열을 반환하라다음 코드를 보자private final List ObjectInStock = new ArrayLi
bluesparrow.tistory.com
다음 코드를 보자
public Cheese[] getCheeses(){
return cheesesInStock.toArray(new Cheese[0]);
}
컬렉션을 배열로 반환할때 만약 컬렉션이 empty하다면 null이 아닌, 길이가 0인 배열을 반환하는 코드이다. 배열을 반환하기 위해 List의 toArray() 메소드를 사용하여 배열을 반환하였다.
코드만 보았을때는 길이 0인 배열로 변환하는 것으로 추측해볼 수 있는데 몇가지 이상한점이 있다.
- 길이가 0인지 확인하지 않는다.(길이가 0인경우와 그렇지 않은경우에도 문제 없이 진행된다고 느껴지긴 한다.)
- 파라미터가 이상하다.(타입도 아닌 인스턴스 형태이다)
- 파라미터의 인스턴스의 배열 길이가 0이다.(무조건 길이가 0인 배열을 반환한다고 느껴진다.)
- 네이밍이 어색하게 느껴진다.(toArray는 파라미터가 없는게 자연스럽다.)
toArray 함수를 자세히 보면서 살펴보자
toArray()
다음은 List에서 선언되어 있는 toArray()메소드 설명이다.
<T> T[] toArray(T[] a);
Lists that support this operation may place limitations on what elements may be added to this list. In particular, some lists will refuse to add null elements, and others will impose restrictions on the type of elements that may be added. List classes should clearly specify in their documentation any restrictions on what elements may be added.
리스트에 element를 추가하는 것에 대해서 제한을 두고 리스트에 element의 limitation을 정할 수 있다고 한다.
잘 이해되지 않는다. 실제 구현체를 보자
public <T> T[] toArray(T[] a) {
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
위 코드는 ArrayList에서의 toArray 구현이다.
- 리스트의 길이보다 파라미터 배열의 길이가 짧다면, 배열의 타입에 해당하는 배열을 copy하여(깊은 복사) 반환한다.(리스트를 작아서 )
- 리스트의 길이보다 파라미터 배열의 길이가 길다면, 리스트 값을 배열로 복사하고 리스트마지막 index + 1 값(size)을 null로 지정
- 리스트의 길이보다 파라미터의 배열의 길이가 같다면 배열 copy 후 반환



실제 구현내용이 예상했던 내용과 다르게 되어 있다. 요약하자면 리스트를 배열로 변환하고 파라미터 리스트의 타입에 해당하는 값으로 가져온다는 것이다. 처음에 생각했던 의구심을 하나씩 풀어보자
길이가 0인지 확인하지 않는다.
상관없다. 길이가 0이든 양수 값이든 로직에 문제가 생기지 않는다
파라미터가 이상하다.
파라미터에 배열을 넣는 것이 다소 이질적으로 느껴진다. 심지어 배열의 내부 값들을 사용하지 않는다.
구현함수를 보면 해당 파라미터에 해당하는 인스턴스에 값을 넣는 것을 확인할 수 있다.(조건 1의 경우는 예외)
배열을 내부적으로 생성하지 않고 파라미터값을 사용한다는 것은 아직 납득되지 않는 부분이다.
일단 타입은 반드시 알려줘야한다.
제네릭은 컴파일 타임에 타입이 정해지기 때문에 어떤 배열로 변환할 것인지 알려줘야 한다.
그렇다면 파라미터에서 배열을 String.class와 같이 클래스를 통해 알려주면 안됬을까?
일단 파라미터의 필요성은 느껴진다.
그래도 아직까지는 파라미터를 굳이 저렇게 선언해야했을까?
파라미터의 인스턴스의 배열 길이가 0이다.
이건 하기 나름이다. 어짜피 크면 새로 배열을 만들어서...
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
다만 주의해야하는 경우가 있는데 파라미터의 배열의 길이가 리스트의 길이보다 클경우 리스트 길이 인덱스는 null 값이고 뒤의 값들은 기존 값들을 가져간다
List<Integer> list = new ArrayList<>();
list.add(1);
Integer[] integers = new Integer[6];
for (int i = 0; i < 6; i++)
integers[i] = i;
Integer[] array = list.toArray(integers);
for (Integer integer : array) {
System.out.println("integer = " + integer);
}
네이밍이 어색하게 느껴진다.
사실 파라미터가 없으면 문제가 없다. 실제로도 toArray() 함수가 있다. 그러면 toArray(T[] a)가 도대체 왜 만들었을까?
toArray(T[] a)의 필요성 이전에 toArray(T[] a)의 구현체가 저럴 수 밖에 없는 이유에 대해 알아보자
결국 제네릭
이전에 배열의 타입에 대해 명시해야하는 필요성이 있었다. 그러면 배열의 타입만 넘기면 될거 같은데 Integer와 Integer[]는 서로 다른 타입이다. 그런데 integer[]임을 표시할 수 없는 것 같다.(적어도 런타임에 그렇다) 따라서 인스턴스를 넘겨 해당 인스턴스에 해당하는 타입의 배열을 만들 수 있게되는 것이다.(배열이 클래스 리터럴이 불가능하다고 알고 있는데 관련이 있는 것 같다.) 따라서 원하는 배열의 타입이 있다면 파라미터에 명세해야하는 것이다. 게다가 제네릭은 런타임에서 타입을 확인할 수 없다는 점을 생각해보면 인스턴스 자체를 넘겨야 한다는 것이 납득된다

사용성
그러면 파라미터가 없는 ToArray()는 타입을 어떻게 체크할까? ToArray() 는 Object로 반환된다. 그러면 ToArray(T[] a) 은 언제 사용할까? 타입 변환을 하고 싶은 경우이자 타입 변환이 가능한 경우-> 업캐스팅, 다운캐스팅!

'Java' 카테고리의 다른 글
[이펙티브 자바] 아이템 64, 65, 66, 67, 6 (0) | 2024.06.18 |
---|---|
[이펙티브 자바] 아이템 54, 55 (0) | 2024.05.20 |
[이펙티브 자바] 아이템 47, 48, 49 (2) | 2024.04.27 |
[이펙티브 자바] 아이템 39, 40, 41 (1) | 2024.03.24 |
[이펙티브 자바] 아이템 10, 11 (2) | 2024.01.14 |