πŸ“‚ JAVA/μ΄νŽ™ν‹°λΈŒ μžλ°”

이왕이면 μ œλ„€λ¦­ λ©”μ„œλ“œλ‘œ λ§Œλ“€λΌ - [5μž₯. μ œλ„€λ¦­(μ•„μ΄ν…œ30)]

Amenable 2023. 5. 31. 10:53

  ν΄λž˜μŠ€μ™€ λ§ˆμ°¬κ°€μ§€λ‘œ, λ©”μ„œλ“œλ„ μ œλ„€λ¦­μœΌλ‘œ λ§Œλ“€ 수 μžˆλ‹€. μ œλ„€λ¦­ λ©”μ„œλ“œ 3κ°€μ§€λ₯Ό μ‚΄νŽ΄λ³΄λ©΄μ„œ μ–΄λ–»κ²Œ μ œλ„€λ¦­ λ©”μ„œλ“œλ₯Ό λ§Œλ“œλŠ”μ§€ μ•Œμ•„λ³΄μž.

 

1. λ§€κ°œλ³€μˆ˜ν™” νƒ€μž…μ„ λ°›λŠ” 정적 μœ ν‹Έλ¦¬ν‹° λ©”μ„œλ“œ 🌼

  λ§€κ°œλ³€μˆ˜ν™” νƒ€μž…μ„ λ°›λŠ” 정적 μœ ν‹Έλ¦¬ν‹° λ©”μ„œλ“œλŠ” 보톡 μ œλ„€λ¦­μ΄λ‹€. (Collections의 μ•Œκ³ λ¦¬μ¦˜ λ©”μ„œλ“œλŠ” λͺ¨λ‘ μ œλ„€λ¦­μ΄λ‹€.)

μš°μ„ , μ œλ„€λ¦­μ„ μ‚¬μš©ν•˜μ§€ μ•Šμ€ λ©”μ„œλ“œλ₯Ό μ‚΄νŽ΄λ³΄μž

public class Union {

    public static Set union(Set s1, Set s2) {
        Set result = new HashSet(s1);
        result.addAll(s2);
        return result;
    }
}

  ν•΄λ‹Ή λ©”μ„œλ“œλŠ” μ•„λž˜μ˜ μ˜ˆμ‹œμ—μ„œ μ‚΄νŽ΄λ³Ό 수 μžˆλŠ” κ²ƒμ²˜λŸΌ μ•ˆμ „ν•˜μ§€ μ•Šλ‹€.

public static void main(String[] args) {
    Set names = Set.of("amenable", "immortal", "choi");
    Set numbers = Set.of(1, 2, 3);

    Set all = union(names, numbers);

    for(Object o : all){
        System.out.println((String)o); // ClassCastException
    }
}

 

  κ·ΈλŸ¬λ―€λ‘œ 이것을 μ œλ„€λ¦­ λ©”μ„œλ“œλ‘œ λ°”κΏ”λ³΄μž. 방법은 λ‹€μŒκ³Ό κ°™λ‹€.

  1. μ›μ†Œ νƒ€μž…을 νƒ€μž… λ§€κ°œλ³€μˆ˜λ‘œ λͺ…μ‹œν•œλ‹€.
  2. λ©”μ„œλ“œ μ•ˆμ—μ„œλ„ μ΄ νƒ€μž… λ§€κ°œλ³€μˆ˜λ§Œ μ‚¬μš©ν•˜κ²Œ μˆ˜μ •ν•œλ‹€.
  3. νƒ€μž… λ§€κ°œλ³€μˆ˜λ“€μ„ μ„ μ–Έν•˜λŠ” νƒ€μž… λ§€κ°œλ³€μˆ˜ λͺ©λ‘μ€ λ©”μ„œλ“œμ˜ μ œν•œμžμ™€ λ°˜ν™˜ νƒ€μž… μ‚¬μ΄μ— λ„£λŠ”λ‹€.
public class Union {

    public static <E> Set<E> union(Set<E> s1, Set<E> s2) {
        Set<E> result = new HashSet<>(s1);
        result.addAll(s2);
        return result;
    }
}

  μ œλ„€λ¦­ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ λ¬Έμ œκ°€ 되던 상황(λŸ°νƒ€μž„ μ—λŸ¬κ°€ λ°œμƒν•˜λŠ” 것)을 컴파일 νƒ€μž„μ— μ•Œ 수 μžˆλ‹€.

public static void main(String[] args) {
    Set<String> names = Set.of("amenable", "immortal", "choi");
    Set<Integer> numbers = Set.of(1, 2, 3);

    Set all = union(names, numbers); // 컴파일 μ—λŸ¬
}

  λ˜ν•œ, 직접 ν˜•λ³€ν™˜ν•˜μ§€ μ•Šμ•„λ„ μ–΄λ–€ 였λ₯˜λ‚˜ κ²½κ³  없이 μ»΄νŒŒμΌλœλ‹€.

public static void main(String[] args) {
    Set<String> groupA = Set.of("amenable", "immortal", "choi");
    Set<String> groupB = Set.of("perseverance", "sunny");

    Set<String> all = union(groupA, groupB);

    for(String o : all){
        System.out.println(o);
    }
}

  ν•œμ •μ  μ™€μΌλ“œμΉ΄λ“œ νƒ€μž…μ„ μ‚¬μš©ν•˜λ©΄ 더 μœ μ—°ν•˜κ²Œ κ°œμ„ ν•  수 μžˆλŠ”λ°, 이것은 λ‹€μŒ μ•„μ΄ν…œμΈ μ•„μ΄ν…œ 31μ—μ„œ μ‚΄νŽ΄λ³΄λ„λ‘ ν•˜μž. 

 

 

2. μ œλ„€λ¦­ μ‹±κΈ€ν„΄ νŒ©ν„°λ¦¬ 🌻

  λ•Œλ•Œλ‘œ λΆˆλ³€ 객체λ₯Ό μ—¬λŸ¬ νƒ€μž…μœΌλ‘œ ν™œμš©ν•  수 있게 λ§Œλ“€μ–΄μ•Ό ν•  λ•Œκ°€ μžˆλ‹€.

  μ˜¬λ°”λ₯΄μ§€ μ•Šμ€ μ½”λ“œ(μ—¬λŸ¬ νƒ€μž…μ„ ν™œμš©ν•  수 μžˆλŠ” 것이 μ•„λ‹Œ 경우)λŠ” λ‹€μŒκ³Ό κ°™λ‹€. (μ˜ˆμ œλŠ” λͺ¨λ“  μ›μ†Œλ₯Ό 자기 μžμ‹ μœΌλ‘œ λŒ€μ‘μ‹œν‚€λŠ” ν•¨μˆ˜μΈ ν•­λ“±ν•¨μˆ˜λ₯Ό μ΄μš©ν•œ μ½”λ“œλ‹€.)

public class GenericSingletonFactory {

    public static Function<String, String> stringIdentityFunction() {
        return (t) -> t;
    }

    public static Function<Number, Number> integerIdentityFunction() {
        return (t) -> t;
    }
}

----------

public static void main(String[] args) {
    String[] names = {"amenable", "immortal", "choi"};
    Function<String, String> sameNames = stringIdentityFunction();
    for (String s : names) {
        System.out.println(sameNames.apply(s));
    }

    Number[] numbers = { 1, 2.0, 3L };
    Function<Number, Number> sameNumbers = integerIdentityFunction();
    for(Number n : numbers){
        System.out.println(sameNumbers.apply(n));
    }
}

 

  ν•˜μ§€λ§Œ, μžλ°”μ˜ μ œλ„€λ¦­μ΄ μ‹€μ²΄ν™”λ˜λŠ” 게 μ•„λ‹ˆλΌ μ†Œκ±°λ˜κΈ° λ•Œλ¬Έμ— λΆˆλ³€ 객체 ν•˜λ‚˜λ₯Ό μ–΄λ–€ νƒ€μž…μœΌλ‘œλ“  λ§€κ°œλ³€μˆ˜ν™” ν•  수 μžˆλ‹€.

  μš”μ²­ν•œ νƒ€μž… 맀개 λ³€μˆ˜μ— 맞게 맀번 κ·Έ 객체 νƒ€μž…μ„ λ°”κΏ”μ£ΌλŠ” 정적 νŒ©ν„°λ¦¬λ₯Ό μ΄μš©ν•˜λ©΄ λœλ‹€. 이 νŒ¨ν„΄μ„ μ œλ„€λ¦­ μ‹±κΈ€ν„΄ νŒ©ν„°λ¦¬ νŒ¨ν„΄μ΄λΌκ³  ν•œλ‹€.

public class GenericSingletonFactory {

    private static UnaryOperator<Object> IDENTITY_FN = (t) -> t;

    // μž…λ ₯ 값을 μˆ˜μ • 없이 κ·ΈλŒ€λ‘œ λ°˜ν™˜ν•˜λŠ” ν•­λ“±ν•¨μˆ˜μ΄λ―€λ‘œ,
    // Tκ°€ μ–΄λ–€ νƒ€μž…μ΄λ“  UnaryOperator<T>λ₯Ό μ‚¬μš©ν•΄λ„ νƒ€μž… μ•ˆμ „ν•˜λ‹€.
    @SuppressWarnings("unchecked")
    public static <T> UnaryOperator<T> identityFunction() {
        return (UnaryOperator<T>) IDENTITY_FN;
    }
}

----------

public static void main(String[] args) {
    String[] names = {"amenable", "immortal", "choi"};
    Function<String, String> sameNames = identityFunction();
    for (String s : names) {
        System.out.println(sameNames.apply(s));
    }

    Number[] numbers = { 1, 2.0, 3L };
    Function<Number, Number> sameNumbers = identityFunction();
    for(Number n : numbers){
        System.out.println(sameNumbers.apply(n));
    }
}

 

 

3. μž¬κ·€μ  νƒ€μž… ν•œμ • 🌷

  자기 μžμ‹ μ΄ λ“€μ–΄κ°„ ν‘œν˜„μ‹μ„ μ‚¬μš©ν•˜μ—¬ νƒ€μž… λ§€κ°œλ³€μˆ˜μ˜ ν—ˆμš© λ²”μœ„λ₯Ό ν•œμ •ν•  수 μžˆλŠ” 'μž¬κ·€μ  νƒ€μž… ν•œμ •(Recursive Type Bound)을 μ•Œμ•„λ³΄μž.

  μž¬κ·€μ  νƒ€μž… ν•œμ •μ€ 주둜 νƒ€μž…μ˜ μžμ—°μ  μˆœμ„œλ₯Ό μ •ν•˜λŠ” Comparable μΈν„°νŽ˜μ΄μŠ€μ™€ ν•¨κ»˜ 쓰인닀.

public class RecursiveTypeBound {

    public static <E extends Comparable<E>> E max(Collection<E> c) {
        if(c.isEmpty())
            throw new IllegalArgumentException("μ»¬λ ‰μ…˜μ΄ λΉ„μ–΄ μžˆμŠ΅λ‹ˆλ‹€.");

        E result = null;
        for(E e : c)
            if(result == null || e.compareTo(result) > 0)
                result = Objects.requireNonNull(e);

        return result;
    }
}

----------

public static void main(String[] args) {
    List<String> argList = Arrays.asList("amenable", "immortal");
    System.out.println(max(argList)); // immortal
}

  νƒ€μž… ν•œμ •μΈ <E extends Comparable<E>>λŠ” "λͺ¨λ“  νƒ€μž… EλŠ” μžμ‹ κ³Ό 비ꡐ할 수 μžˆλ‹€"라고 읽을 수 μžˆλ‹€. μƒν˜Έ λΉ„ꡐ κ°€λŠ₯ν•˜λ‹€λŠ” λœ»μ„ μ•„μ£Ό μ •ν™•ν•˜κ²Œ ν‘œν˜„ν•œ κ²ƒμ΄λ‹€.

 

ν•΄λ‹Ή 글은 λ°±κΈ°μ„  λ‹˜μ˜ 'μ΄νŽ™ν‹°λΈŒ μžλ°” μ™„λ²½ 곡랡'을 μ°Έκ³ ν•˜μ˜€μŠ΅λ‹ˆλ‹€.