λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

빈 ꡬ멍 μ±„μš°κΈ°

[Java] μ œλ„€λ¦­μ˜ νƒ€μž… μ†Œκ±° Type Erasure

좜처

ChatGPT


νƒ€μž… μ†Œκ±°λž€? 

νƒ€μž… μ†Œκ±°λŠ” Java의 μ œλ„€λ¦­μ΄ 컴파일된 후에 λŸ°νƒ€μž„μ—μ„œ μ œλ„€λ¦­ νƒ€μž… λ§€κ°œλ³€μˆ˜κ°€ μ œκ³ λ˜λŠ” 과정이닀. μ œλ„€λ¦­ νƒ€μž…μ€ 컴파일 μ‹œμ μ—λ§Œ μœ νš¨ν•˜κ³ , λŸ°νƒ€μž„μ—λŠ” Object νƒ€μž…μœΌλ‘œ λŒ€μ²΄λ˜κ±°λ‚˜ μƒν•œ 경계λ₯Ό μ‚¬μš©ν•˜λŠ” 경우 μƒμœ„ 클래슀둜 λŒ€μ²΄λœλ‹€.

예λ₯Ό λ“€μ–΄, List<String>κ³Ό List<Integer>λŠ” 컴파일 νƒ€μž„μ—λŠ” μ„œλ‘œ λ‹€λ₯Έ νƒ€μž…μœΌλ‘œ κ°„μ£Όλ˜μ§€λ§Œ, 컴파일 ν›„μ—λŠ” λͺ¨λ‘ List νƒ€μž…μœΌλ‘œ λ™μΌν•˜κ²Œ μ²˜λ¦¬λœλ‹€. 이 λ•Œλ¬Έμ— μ œλ„€λ¦­ νƒ€μž… μ •λ³΄λŠ” λŸ°νƒ€μž„μ—λŠ” μ‘΄μž¬ν•˜μ§€ μ•ŠμœΌλ©°, 이λ₯Ό νƒ€μž… μ†Œκ±°λΌκ³  ν•œλ‹€.

 

νƒ€μž… μ†Œκ±°μ˜ λͺ©μ 

μžλ°”μ—μ„œ νƒ€μž… μ†Œκ±°κ°€ λ„μž…λœ μ£Όμš” μ΄μœ λŠ” ν›„λ°© ν˜Έν™˜μ„±μ„ μœ μ§€ν•˜λ©΄μ„œ μ œλ„€λ¦­μ„ λ„μž…ν•˜κΈ° μœ„ν•¨μ΄λ‹€. JDK 5 이전에 μ‘΄μž¬ν•˜λ˜ μ½”λ“œμ™€ ν˜Έν™˜λ˜λ„λ‘ ν•˜λ €λ©΄ μƒˆλ‘œμš΄ μ œλ„€λ¦­ κΈ°λŠ₯이 기쑴의 λΉ„μ œλ„€λ¦­ μ½”λ“œμ™€ 곡쑴할 수 μžˆμ–΄μ•Ό ν–ˆλ‹€.

κΈ°λŠ₯적으둜 ν•„μš”ν•΄μ„œ λ„μž…λœ 게 μ•„λ‹ˆκ³ , μžλ°” 1.4 이전 버전을 ν¬κΈ°ν•˜μ§€ μ•ŠκΈ° μœ„ν•΄μ„œ νƒ€μž… μ†Œκ±°λ₯Ό λ§Œλ“  κ²ƒμž„. πŸ₯Ή

  • ν›„λ°© λ³΄ν™˜μ„±μ΄λž€ 
    • μƒˆλ‘œμš΄ λ²„μ „μ˜ μ‹œμŠ€ν…œ, μ†Œν”„νŠΈμ›¨μ–΄ λ˜λŠ” 기술이 기쑴의 이전 버전과 ν˜Έν™˜λ˜μ–΄, 이전 λ²„μ „μ—μ„œ μ‚¬μš©λ˜λ˜ κΈ°λŠ₯μ΄λ‚˜ μ½”λ“œκ°€ μƒˆλ‘œμš΄ λ²„μ „μ—μ„œλ„ κ·ΈλŒ€λ‘œ λ™μž‘ν•  수 μžˆλŠ” λŠ₯λ ₯을 λ§ν•œλ‹€. 즉, μƒˆλ‘œμš΄ 버전이 λ‚˜μ˜€λ”λΌλ„ κΈ°μ‘΄ μ‚¬μš©μžλ“€μ΄ 이전 λ²„μ „μ—μ„œ μž‘μ„±ν•œ ν”„λ‘œκ·Έλž¨μ΄λ‚˜ 데이터λ₯Ό 계속 μ‚¬μš©ν•  수 μžˆλ„λ‘ μ§€μ›ν•˜λŠ” 것이닀.

 

νƒ€μž… μ†Œκ±°κ°€ μ΄ˆλž˜ν•˜λŠ” μ œμ•½

1. λŸ°νƒ€μž„ νƒ€μž… 체크 λΆˆκ°€λŠ₯

μ œλ„€λ¦­ νƒ€μž… 정보가 μ†Œκ±°λ˜λ―€λ‘œ, μ œλ„€λ¦­ νƒ€μž…μœΌλ‘œ μΊμŠ€νŒ…ν•˜κ±°λ‚˜ νƒ€μž… 체크λ₯Ό ν•  수 μ—†λ‹€.

2. μ œλ„€λ¦­ νƒ€μž…μ˜ λ°°μ—΄ 생성 λΆˆκ°€λŠ₯

μ œλ„€λ¦­ νƒ€μž…μ˜ 배열을 μƒμ„±ν•˜λŠ” 것은 νƒ€μž… μ•ˆμ „μ„±μ„ 보μž₯ν•  수 μ—†κΈ° λ•Œλ¬Έμ— κΈˆμ§€λœλ‹€.

3. μ˜€λ²„λ‘œλ”© λΆˆκ°€

νƒ€μž… μ†Œκ±° λ•Œλ¬Έμ— μ œλ„€λ¦­ λ©”μ„œλ“œλ₯Ό μ˜€λ²„λ‘œλ”©ν•˜λŠ” 것이 λΆˆκ°€λŠ₯ν•˜λ‹€. λ™μΌν•œ νƒ€μž… μ†Œκ±° κ²°κ³Όλ₯Ό κ°€μ§€λŠ” 두 λ©”μ„œλ“œλŠ” μ˜€λ²„λ‘œλ”©λ  수 μ—†λ‹€.

 

νƒ€μž… μ†Œκ±°μ™€ κ΄€λ ¨λœ μ˜ˆμ‹œ μ½”λ“œ

예제 1 : λŸ°νƒ€μž„ νƒ€μž… 체크와 νƒ€μž… μ†Œκ±°

import java.util.ArrayList;
import java.util.List;

public class TypeErasureExample {
    public static void main(String[] args) {
        List<String> stringList = new ArrayList<>();
        List<Integer> integerList = new ArrayList<>();
        
        System.out.println(stringList.getClass() == integerList.getClass()); // true
    }
}

 

κ²°κ³Ό : true

  • stringList와 integerListλŠ” μ„œλ‘œ λ‹€λ₯Έ μ œλ„€λ¦­ νƒ€μž…(List<String>κ³Ό List<Integer>)으둜 μ„ μ–Έλ˜μ—ˆμ§€λ§Œ, νƒ€μž… μ†Œκ±°λ‘œ 인해 컴파일된 ν›„μ—λŠ” λͺ¨λ‘ 같은 List νƒ€μž…μœΌλ‘œ κ°„μ£Όλœλ‹€. λ”°λΌμ„œ getClass() λ©”μ„œλ“œλ‘œ ν™•μΈν•˜λ©΄ λ‘˜μ€ λ™μΌν•œ 클래슀둜 μ·¨κΈ‰λœλ‹€.

예제 2: μ œλ„€λ¦­ λ°°μ—΄ 생성 λΆˆκ°€λŠ₯

public class GenericArrayExample<T> {
    // μ œλ„€λ¦­ νƒ€μž…μ˜ 배열을 μƒμ„±ν•˜λ €κ³  ν•˜λ©΄ 컴파일 였λ₯˜ λ°œμƒ
    // T[] array = new T[10]; // 컴파일 였λ₯˜

    public static void main(String[] args) {
        // λ‹€μŒκ³Ό 같은 λ°©μ‹μœΌλ‘œλŠ” κ°€λŠ₯
        List<String>[] stringLists;
        List<?>[] lists = new List<?>[10]; // OK
    }
}

 

  • new T[10]처럼 μ œλ„€λ¦­ νƒ€μž…μ˜ 배열을 직접 생성할 수 μ—†λ‹€. λŒ€μ‹  μ™€μΌλ“œμΉ΄λ“œ List<?>[]와 같은 ν˜•νƒœλ‘œ 배열을 μ„ μ–Έν•  μˆ˜λŠ” μžˆμ§€λ§Œ, 이 κ²½μš°μ—λ„ νƒ€μž… μ•ˆμ „μ„±μ„ μ™„μ „νžˆ 보μž₯ν•  수 μ—†λ‹€.

 

νƒ€μž… μ†Œκ±°κ°€ μ΄ˆλž˜ν•˜λŠ” λ¬Έμ œμ™€ 주의 사항

λŸ°νƒ€μž„ μΊμŠ€νŒ… μ˜ˆμ™Έ

νƒ€μž… μ†Œκ±°λ‘œ 인해 ClassCastException이 λ°œμƒν•  수 μžˆλ‹€. μ œλ„€λ¦­μ€ 컴파일 μ‹œμ μ— νƒ€μž… 체크λ₯Ό ν•˜μ§€λ§Œ, 잘λͺ»λœ νƒ€μž… μΊμŠ€νŒ…μ€ λŸ°νƒ€μž„μ— 발견될 수 μžˆλ‹€.

import java.util.ArrayList;
import java.util.List;

public class CastExceptionExample {
    public static void main(String[] args) {
        List rawList = new ArrayList();
        rawList.add("Hello");
        rawList.add(123); // κ²½κ³  μ—†μŒ

        List<String> stringList = rawList; // νƒ€μž… 뢈일치, ν•˜μ§€λ§Œ 경고만 λ°œμƒ

        // λŸ°νƒ€μž„ μ˜ˆμ™Έ λ°œμƒ
        for (String s : stringList) { 
            System.out.println(s); // ClassCastException: Integer cannot be cast to String
        }
    }
}

 

  • 이 μ˜ˆμ œμ—μ„œλŠ” μ›μ‹œ νƒ€μž…μ˜ 리슀트(List rawList)에 μ„œλ‘œ λ‹€λ₯Έ νƒ€μž…μ˜ 객체λ₯Ό μΆ”κ°€ν•œλ‹€. 그런 λ‹€μŒ 이 리슀트λ₯Ό μ œλ„€λ¦­ νƒ€μž…μ˜ List<String>으둜 μΊμŠ€νŒ…ν•˜κ³  λ¬Έμžμ—΄λ‘œ 좜λ ₯ν•˜λ €κ³  μ‹œλ„ν•  λ•Œ ClassCastException이 λ°œμƒν•œλ‹€.

 

νƒ€μž… μ†Œκ±°λ₯Ό μš°νšŒν•˜κ±°λ‚˜ κ·Ήλ³΅ν•˜λŠ” 방법

λ°”μš΄λ“œ νƒ€μž…μ„ μ‚¬μš©ν•΄ μ œλ„€λ¦­ νƒ€μž…μ„ μ œν•œ

예λ₯Ό λ“€μ–΄, List<? extends Number>와 같이 μ œν•œλœ μ œλ„€λ¦­ νƒ€μž…μ„ μ‚¬μš©ν•˜λ©΄ λŸ°νƒ€μž„ μ•ˆμ „μ„±μ„ 높일 수 μžˆλ‹€.

μ™€μΌλ“œμΉ΄λ“œ μ‚¬μš©

'? extends' λ˜λŠ” '? super'와 같은 μ™€μΌλ“œμΉ΄λ“œλ₯Ό μ‚¬μš©ν•΄ νƒ€μž… μ•ˆμ „μ„±μ„ κ°•ν™”ν•œλ‹€.

컴파일 κ²½κ³ λ₯Ό ν™•μΈν•˜κ³  처리

unchecked κ²½κ³ λ₯Ό λ¬΄μ‹œν•˜μ§€ 말고 μ½”λ“œμ—μ„œ λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆλŠ” 지점을 μ² μ €νžˆ ν™•μΈν•œλ‹€.

 

νƒ€μž… μ†Œκ±°μ˜ μž₯점과 단점

μž₯점

  • μ œλ„€λ¦­μ„ μ‚¬μš©ν•˜λ©΄ νƒ€μž… μ•ˆμ „μ„±μ„ μœ μ§€ν•˜λ©΄μ„œ μ½”λ“œ μž¬μ‚¬μš©μ„±μ„ 높일 수 μžˆλ‹€.
  • νƒ€μž… μ†Œκ±°λ‘œ 인해 컴파일된 λ°”μ΄νŠΈμ½”λ“œκ°€ 더 κ°„λ‹¨ν•˜κ³  더 μž‘μ•„μ§ˆ 수 μžˆλ‹€.

단점

  • λŸ°νƒ€μž„μ—λŠ” μ œλ„€λ¦­ νƒ€μž… 정보가 사라지기 λ•Œλ¬Έμ—, νŠΉμ • μƒν™©μ—μ„œλŠ” νƒ€μž… μ•ˆμ •μ„±μ„ 보μž₯ν•˜μ§€ λͺ»ν•  수 μžˆλ‹€.
  • μ œλ„€λ¦­ νƒ€μž…μ˜ λ°°μ—΄ 생성이 λΆˆκ°€λŠ₯ν•˜κ³ , μ œλ„€λ¦­ λ©”μ„œλ“œ μ˜€λ²„λ‘œλ”©λ„ μ œν•œλœλ‹€.