Language/Java

β˜• μžλ°” κ°€λ³€ 인수(VarArgs) - λ§€κ°œλ³€μˆ˜λ₯Ό λ™μ μœΌλ‘œ

인파_ 2022. 11. 29. 09:18

java-varargs

κ°€λ³€ 인수 (Variable Arguments)

κ°€λ³€ 인수(varargs)λž€, λ§€κ°œλ³€μˆ˜λ‘œ λ“€μ–΄μ˜€λŠ” κ°’μ˜ κ°œμˆ˜μ™€ 상관 없이 λ™μ μœΌλ‘œ 인수λ₯Ό λ°›μ•„ κΈ°λŠ₯ν•˜λ„λ‘ ν•΄μ£ΌλŠ” 문법을 μ§€μΉ­ν•œλ‹€.

예λ₯Όλ“€μ–΄ λ‹€μŒκ³Ό 같이 λ§€κ°œλ³€μˆ˜ κ°―μˆ˜κ°€ μΌμ •μΉ˜ μ•Šμ€ print() λ©”μ„œλ“œκ°€ μžˆλ‹€κ³  κ°€μ •ν•˜μž.

print("홍길동");
print("홍길동", "μ΄μˆœμ‹ ");
print("홍길동", "μ΄μˆœμ‹ ", "μœ μ„±λ£‘");
print("홍길동", "μ΄μˆœμ‹ ", "μœ μ„±λ£‘", "강감찬");
print("홍길동", "μ΄μˆœμ‹ ", "μœ μ„±λ£‘", "강감찬", "이도");

μ—¬λŸ¬κ°œμ˜ νŒŒλΌλ―Έν„°κ°€ λ“€μ–΄μ˜¬ 수 μžˆλŠ” λ©”μ„œλ“œλ₯Ό κ΅¬μ„±ν•˜λŠ” 방법은 λŒ€ν‘œμ μœΌλ‘œ λ©”μ„œλ“œ μ˜€λ²„λ‘œλ”©(overloading)으둜 μ²˜λ¦¬κ°€ κ°€λŠ₯ν•˜λ‹€.

ν•˜μ§€λ§Œ 전달할 λ§€κ°œλ³€μˆ˜κ°€ λͺ‡κ°œμΈμ§€ μΌμ •μΉ˜ μ•Šμ„λ•Œ 일일히 λ©”μ„œλ“œλ₯Ό μ˜€λ²„λ‘œλ”©ν•˜μ—¬ κ΅¬ν˜„ν•˜λŠ” 것은 λ³€κ±°λ‘œμš°λ©° λ³„λ‘œ νš¨μœ¨μ μ΄μ§€ λͺ»ν•˜λ‹€λΌκ³  ν•  수 μžˆλŠ”λ°, μ—¬κΈ°μ„œ κ°€λ³€ 인자(varargs)κ°€ νž˜μ„ λ°œν•œλ‹€.

κ°€λ³€ μΈμˆ˜λŠ” νŒŒλΌλ―Έν„°λ“€μ„ ν†΅μ§Έλ‘œ λ°°μ—΄λ‘œ λ°›μ•„λ“€μ—¬ μ²˜λ¦¬ν•˜κΈ° λ•Œλ¬Έμ— λ™μ μœΌλ‘œ λ§€κ°œλ³€μˆ˜λ₯Ό 받을 수 있게 λœλ‹€. 덕뢄에 λ©”μ„œλ“œλ₯Ό n번 μ˜€λ²„λ‘œλ”© ν•˜μ§€μ•Šκ³  ν•œλ²ˆμ— μ²˜λ¦¬κ°€ κ°€λŠ₯ν•˜λ‹€.

κ°€λ³€ μΈμˆ˜λŠ” JDK 1.5λΆ€ν„° μΆ”κ°€λ˜μ—ˆμœΌλ©°, μžλ°”μ—μ„œλŠ” System.out.printf() λ©”μ„œλ“œκ°€  κ°€λ³€ 인자λ₯Ό μ‚¬μš©ν•œ λŒ€ν‘œμ μΈ λ©”μ„œλ“œλΌκ³  ν•  수 μžˆλ‹€.

java-varargs
μžλ°” printf λ©”μ„œλ“œ μ‹œκ·Έλ‹ˆμ²˜


κ°€λ³€ 인수 μ‚¬μš©λ²•

λ©”μ„œλ“œ νŒŒλΌλ―Έν„° 뢀뢄에 νƒ€μž…... λ§€κ°œλ³€μˆ˜λͺ… 으둜 μ²˜λ¦¬ν•˜λ©΄ μ‚¬μš©μ΄ κ°€λŠ₯ν•˜λ‹€.

κ°€λ³€ μΈμˆ˜λŠ” 전달 인자λ₯Ό 0κ°œλΆ€ν„° nκ°œκΉŒμ§€ λ„£μ„μˆ˜ μžˆλ‹€. 그리고 νŒŒλΌλ―Έν„°λ‘œ λ„˜κ²¨μ§€λŠ” 값듀을 λͺ¨μ•„μ„œ μ»΄νŒŒμΌμ‹œ λ°°μ—΄λ‘œ μ²˜λ¦¬λœλ‹€. μ£Όμ˜ν• μ μ€ μΈμžλ“€μ˜ κ°―μˆ˜μ—λŠ” μ œν•œμ΄ μ—†μ§€λ§Œ, λ°°μ—΄ μžλ£Œν˜•μ€ λ§€κ°œλ³€μˆ˜ νƒ€μž…μœΌλ‘œ λͺ…μ‹œλœ 것에 λ”°λΌκ°„λ‹€λŠ” 점이닀.

public static void main(String[] args) {
    print("홍길동");
    print("홍길동", "μ΄μˆœμ‹ ");
    print("홍길동", "μ΄μˆœμ‹ ", "μœ μ„±λ£‘");
    print("홍길동", "μ΄μˆœμ‹ ", "μœ μ„±λ£‘", "강감찬");
    print("홍길동", "μ΄μˆœμ‹ ", "μœ μ„±λ£‘", "강감찬", "이도");
}

public static void print(String... str) {
    // κ°€λ³€ 인수인 str λ§€κ°œλ³€μˆ˜λŠ” String[] λ°°μ—΄ νƒ€μž…μœΌλ‘œ 받아듀인닀.
    for(String s : str) {
        System.out.print(s + ", ");
    }
    System.out.println();
}

java-varargs

 

만일 λ§€κ°œλ³€μˆ˜κ°€ κ°€λ³€ 인자 외에 λ‹€λ₯Έ 맀개 λ³€μˆ˜λ“€λ„ λ°›λŠ”λ‹€λ©΄, λ°˜λ“œμ‹œ κ°€λ³€ 인자λ₯Ό λ©”μ„œλ“œ νŒŒλΌλ―Έν„° κ°€μž₯ λ§ˆμ§€λ§‰μ— μœ„μΉ˜ν•˜λ„λ‘ μ •μ˜ν•΄μ•Ό ν•œλ‹€.

그리고 λ§€κ°œλ³€μˆ˜κ°€ λ„˜κ²¨μ§€λŠ” μˆœμ„œλŠ”, μΈμžλ“€μ΄ μ•žμ— μžˆλŠ” νŒŒλΌλ―Έν„° λΆ€ν„° μ°¨λ‘€λŒ€λ‘œ λ„˜κ²¨μ§€κ³  남은 λ‚˜λ¨Έμ§€ μΈμžλ“€μ΄ κ°€λ³€ 인자둜 λ„˜κ²¨μ§€κ²Œ λœλ‹€.

public static void main(String[] args) {
    print(1, true, "홍길동", "μ΄μˆœμ‹ ", "μœ μ„±λ£‘");
}

// λ§€κ°œλ³€μˆ˜κ°€ μ—¬λŸ¬κ°œ μžˆμ„ 경우, κ°€λ³€ 인자(varargs)λŠ” λ°˜λ“œμ‹œ λ§ˆμ§€λ§‰μ— μœ„μΉ˜
public static void print(int num, boolean bool, String... str) {
    System.out.println("number : " + num);
    System.out.println("bool : " + bool);
    System.out.println("rest parameters : " + Arrays.toString(str));
}

java-varargs
java-varargs

 

μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ κ°€λ³€ 인수

μžλ°”μŠ€ν¬λ¦½νŠΈ μ§„μ˜μ—λ„ κ°€λ³€ μΈμˆ˜κ°€ μ‘΄μž¬ν•œλ‹€.

μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„  κ°€λ³€ 인수λ₯Ό spread μ—°μ‚¬μž ν˜Ήμ€ λ‚˜λ¨Έμ§€ λ§€κ°œλ³€μˆ˜ 라고 μΉ­ν•œλ‹€.

function print(...data) {
    console.log(data);
}
print(1,2,3,4,5); // [1, 2, 3, 4, 5]

κ°€λ³€ 인수 주의점

 

1. κ°€λ³€ 인자 자체 μ„±λŠ₯ 문제점

κ°€λ³€ μΈμˆ˜λŠ” μœ„μ—μ„œ λ³΄λ‹€μ‹œν”Ό λ„˜κ²¨μ§€λŠ” 인수 κ°―μˆ˜κ°€ μ •ν•΄μ§€μ§€ μ•Šμ•˜μ„λ•Œ 유용히 μ‚¬μš© ν•  수 μžˆλ‹€.

ν•˜μ§€λ§Œ κ°€λ³€ 인수 λ©”μ„œλ“œλŠ” 호좜될 λ•Œ λ§ˆλ‹€ 배열을 μƒˆλ‘œ ν•˜λ‚˜ ν• λ‹Ήν•˜κ³  μ΄ˆκΈ°ν™” ν•˜λ―€λ‘œ, μ„±λŠ₯에 λ―Όκ°ν•œ μƒν™©μ—μ„œλŠ” λ§ˆμ΄λ„ˆμŠ€μ μΈ μš”μ†Œκ°€ 될 수 μžˆλ‹€.

ν•˜μ§€λ§Œ κΌ­ μžμ‹ μ˜ ν”„λ‘œκ·Έλž¨ νŠΉμ„±μƒ κ°€λ³€ 인수λ₯Ό 써야할 상황이라면, λ‹€μŒκ³Ό 같이 μœ μ—°μ μΈ μ˜€λ²„λ‘œλ”©μœΌλ‘œ μ²˜λ¦¬ν•˜λŠ” 것을 κΆŒν•œλ‹€.

예λ₯Όλ“€μ–΄ λ§Œμ•½ μ–΄λŠ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν• λ•Œ λŒ€λΆ€λΆ„μ˜ μƒν™©μ—μ„œ λ§€κ°œλ³€μˆ˜λ₯Ό 3개 μ΄ν•˜λ‘œ λ°›μ•„ μ‚¬μš©ν•œλ‹€λ©΄, 그리고 μ•„μ£Ό 가끔 4개 μ΄μƒμ˜ λ§€κ°œλ³€μˆ˜λ₯Ό λ°›μ•„μ•Όν•  λ•Œκ°€ μžˆλ‹€λ©΄, λ‹€μŒκ³Ό 같이 κ΅¬μ„±ν•˜λ©΄ λœλ‹€.

class Printer {

    public void print(int a1) { }

    public void print(int a1, int a2) { }

    public void print(int a1, int a2, int a3) { }

    public void print(int a1, int a2, int a3, int... rest) { }
}
μ‹€μ œλ‘œ EnumSet의 정적 νŒ©ν„°λ¦¬λ„ μœ„ 기법을 μ‚¬μš©ν•΄ μ—΄κ±° νƒ€μž…μ˜ μ§‘ν•© 생성 λΉ„μš©μ„ μ΅œμ ν™”ν•˜κ³  μžˆλ‹€.

 

2. κ°€λ³€ 인수 자체λ₯Ό μ˜€λ²„λ‘œλ”© X

ν•˜λ‚˜μ˜ ν΄λž˜μŠ€ λ‚΄μ— κ°€λ³€μΈμžλ₯Ό μ‚¬μš©ν•œ λ©”μ„œλ“œλ₯Ό μ˜€λ²„λ‘œλ”©ν•˜λŠ” κ²ƒμ€ κΆŒν•˜μ§€ μ•ŠλŠ”λ‹€. 

μ»΄νŒŒμΌλŸ¬κ°€ μ–΄λ–€ λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•΄μ•Ό ν•˜λŠ”μ§€ κ΅¬λΆ„ν•˜μ§€ λͺ»ν•˜κΈ° λ•Œλ¬Έμ— 컴파일 μ—λŸ¬κ°€ λ°œμƒν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.

class Printer {

    public void print(String c, String... str) {
        System.out.println("첫번째 λ©”μ„œλ“œ");
        System.out.println("rest parameters : " + Arrays.toString(str));
    }

    public void print(String... str) {
        System.out.println("λ‘λ²ˆμ§Έ λ©”μ„œλ“œ");
    }
}

public class Main2 {
    public static void main(String[] args) {
        Printer p = new Printer();
        
        // 이 λ©”μ„œλ“œλŠ” 첫번째 λ©”μ„œλ“œμ—λ„ λ‘λ²ˆμ§Έ λ©”μ„œλ“œμ—μ„œλ„ 싀행이 κ°€λŠ₯ν•˜κΈ° λ•Œλ¬Έμ— μ»΄νŒŒμΌλŸ¬κ°€ ν–‡κΉ”λ € 였λ₯˜λ₯Ό λ°œμƒν•˜κ²Œ λœλ‹€.
        p.print("-", "1", "2", "3");
    }
}

java-varargs

 

3. λ°°μ—΄ νƒ€μž… λ§€κ°œλ³€μˆ˜μ™€ 혼용 X

κ°€λ³€ μΈμžλŠ” λ‚΄λΆ€μ μœΌλ‘œ 배열을 μƒμ„±ν•΄μ„œ μ‚¬μš©ν•˜λŠ” 것 κ°™λ‹€.

λ”°λΌμ„œ λ‹€μŒκ³Ό 같이 λ°°μ—΄ νƒ€μž…μ˜ λ§€κ°œλ³€μˆ˜μ™€ λ™μ‹œμ— μ •μ˜ν•΄ μ‚¬μš©μ΄ λΆˆκ°€λŠ₯ν•˜λ‹€.

java-varargs

 

4. μ œλ„€λ¦­ νƒ€μž…κ³Ό ν•¨κ»˜ μ“Έλ•Œμ—λŠ” 신쀑해라

이 뢀뢄은 Effective Java에 λ‚˜μ˜€λŠ” κ³ κΈ‰ λ‚΄μš©μ΄λ‹€.

κ°€λ³€ μΈμˆ˜λŠ” νŒŒλΌλ―Έν„°μ˜ 개수λ₯Ό ν΄λΌμ΄μ–ΈνŠΈκ°€ μ‘°μ ˆν•  수 μžˆλ„λ‘ ν•΄μ£Όμ§€λ§Œ κ΅¬ν˜„ 방식에 ν—ˆμ μ΄ μ‘΄μž¬ν•œλ‹€.
μœ„μ—μ„œ λ§ν–ˆλ“―μ΄, κ°€λ³€ 인수 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜κ²Œ 되면 κ°€λ³€ 인수λ₯Ό λ‹΄κΈ° μœ„ν•œ 배열이 μžλ™μœΌλ‘œ ν•˜λ‚˜ λ§Œλ“€μ–΄μ§€λŠ”λ°, μ΄λ•Œ μ œλ„€λ¦­ νƒ€μž… νŒŒλΌλ―Έν„°μ™€ 같은 싀체화 λΆˆκ°€ νƒ€μž…μ€ λŸ°νƒ€μž„ μ‹œ νƒ€μž… 정보가 μ†Œκ±°λ˜κΈ° λ•Œλ¬Έμ—, κ°€λ³€ μΈμˆ˜μ— μ œλ„€λ¦­μ΄λ‚˜ λ§€κ°œλ³€μˆ˜ν™” νƒ€μž…(List<String>)이 ν¬ν•¨λ˜κ³  이λ₯Ό λ…ΈμΆœν•  경우 λ¬Έμ œκ°€ μΌμœΌν‚¬μˆ˜ μžˆλ‹€.

 

예λ₯Όλ“€μ–΄ λ‹€μŒ toArray() λ©”μ„œλ“œλŠ” μ œλ„€λ¦­ νƒ€μž…μœΌλ‘œ κ°€λ³€ 인수 배열을 λ°›κ³  이λ₯Ό κ·ΈλŒ€λ‘œ λ°˜ν™˜ν•œλ‹€.

μ΄λ•Œ νƒ€μž…μ„ 단언할 수 μ—†κΈ° λ•Œλ¬Έμ— λͺ¨λ“  νƒ€μž…μ„ 받을 수 μžˆλŠ” Object[] νƒ€μž… λ°°μ—΄λ‘œ λ§Œλ“€μ–΄ λ°˜ν™˜ν•˜κ²Œ λ˜λŠ”λ°, κ²°κ΅­ 메인 λ©”μ„œλ“œμ—μ„œ μ˜³μ§€ μ•Šμ€ λ‹€μš΄μΊμŠ€νŒ…μ΄ μΌμ–΄λ‚˜μ„œ ClassCastException μ˜ˆμ™Έκ°€ λ°œμƒν•˜κ²Œ λœλ‹€.

class Printer {

    // μ œλ„€λ¦­ νƒ€μž…μœΌλ‘œ λ°›λŠ” κ°€λ³€ 인수
    public <T> T[] toArray(T... args) {
        return args; // κ°€λ³€ μΈμžλ“€μ„ λ¬Έμ œμ—†μ΄ λ‹΄κΈ° μœ„ν•΄ μ–΄λ–€ νƒ€μž…λ„ 담을 수 μžˆλŠ” κ°€μž₯ μƒμœ„ νƒ€μž…μΈ Object 배열을 λ§Œλ“€μ–΄ λ°˜ν™˜
    }

    public <T> T[] pick(T a, T b, T c) {
        T[] arr = toArray(a, b, c); // Object[] νƒ€μž… λ°°μ—΄λ‘œ λ¦¬ν„΄λœλ‹€.
        return arr;
    }
}

public class Main {
    public static void main(String[] args) {
        Printer p =new Printer();
		
        // μ œλ„€λ¦­ λ©”μ„œλ“œμ— String νƒ€μž…μœΌλ‘œ 전달
        String[] s = p.pick("1","2","3"); // ! ERROR - Object[] νƒ€μž…μ„ String[] νƒ€μž…μœΌλ‘œ λ‹€μš΄μΊμŠ€νŒ…μ΄ λΆˆκ°€λŠ₯ν•˜λ‹€.
    }
}

java-varargs

λ”°λΌμ„œ μ œλ„€λ¦­κ³Ό κ°€λ³€ 인수λ₯Ό 같이 μ‚¬μš©ν•  일이 μžˆμ„ 경우, λ°°μ—΄ λŒ€μ‹  리슀트 μ œλ„€λ¦­μœΌλ‘œ νƒ€μž…μ„ μ œν•œ(extends / super)ν•˜λŠ” μ‹μœΌλ‘œ λ©”μ„œλ“œλ₯Ό μ„€κ³„ν•˜κ±°λ‚˜, μ œλ„€λ¦­ κ°€λ³€ 인수 배열에 λ‹€λ₯Έ λ©”μ„œλ“œκ°€ μ ‘κ·Όν•˜λ„λ‘ ν•˜μ§€ μ•Šκ²Œ ν•˜λŠ” 것이 μ’‹λ‹€.