BackEnd🌱/Java

[Java] wrapper 클래슀의 μ •μ˜, λ©”λͺ¨λ¦¬, 캐싱

dkswnkk 2022. 4. 8. 17:16

μ„œλ‘ 

μžλ°”λ₯Ό κ³΅λΆ€ν•˜λ‹€ 보면 int, Integer 그리고 double, Double와 같이 첫 이름이 λŒ€λ¬Έμžλ‘œ μ„ μ–Έλœ 것을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€. 이번 κ²Œμ‹œκΈ€μ—μ„œλŠ” μ΄λŸ¬ν•œ 것듀이 무엇인지에 λŒ€ν•΄μ„œ 정리해 λ³΄κ² μŠ΅λ‹ˆλ‹€.

 

래퍼(Wrapper) 클래슀

객체지ν–₯ κ°œλ…μ—μ„œ λͺ¨λ“  것은 객체둜 닀루어져야 ν•©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ μžλ°”μ—μ„œλŠ” 8개의 κΈ°λ³Έν˜•(privitive type)을 객체둜 닀루지 μ•Šκ³  μžˆλŠ”λ° 높은 μ„±λŠ₯을 μ–»κΈ° μœ„ν•΄μ„œ κΈ°λ³Έν˜•μœΌλ‘œ 닀루고 μžˆμ—ˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ λ§€κ°œλ³€μˆ˜λ‘œ 객체λ₯Ό μš”κ΅¬ν•˜κ±°λ‚˜, κΈ°λ³Έν˜•μ΄ μ•„λ‹Œ 객체둜 값을 μ €μž₯ν•΄μ•Ό ν•  λ•Œ, 객체 κ°„μ˜ 비ꡐ가 ν•„μš”ν•  λ•Œ λ“±λ“±μ˜ κ²½μš°μ—μ„œ κΈ°λ³Έν˜• 값듀을 객체둜 λ°˜ν™˜ν•˜μ—¬ μž‘μ—…μ„ μˆ˜ν–‰ν•  λ•Œκ°€ μžˆμŠ΅λ‹ˆλ‹€.

μ΄λ•Œ μ‚¬μš©λ˜λŠ” 것이 래퍼(wrapper) ν΄λž˜μŠ€μž…λ‹ˆλ‹€. 8개의 κΈ°λ³Έν˜•μ„ λŒ€ν‘œν•˜λŠ” 8개의 wrapper ν΄λž˜μŠ€κ°€ μžˆλŠ”λ°, 이 ν΄λž˜μŠ€λ“€μ„ μ΄μš©ν•˜λ©΄ κΈ°λ³Έν˜• 값을 객체둜 λ‹€λ£° 수 μžˆμŠ΅λ‹ˆλ‹€.

κΈ°λ³Έν˜• 래퍼클래슀 μƒμ„±μž 예
boolean Boolean Boolean (boolean value)
Boolean (String s)
Boolean b = new Boolean(true);
Boolean b2 = new Boolean("true");
char Character Character (char value) Character c = new Character('a');
byte Byte Byte (byte value)
Byte (String s)
Byte b = new Byte(10);
Byte b2 = new Byte("10");
short Short Short (short value)
Short (short s)
Short s = new Short(10);
Short s2 = new Short("10");
int Integer Integer (int value)
Integer (String s)
Integer i = new Integer(100);
Integer 2 = new Integer("100");
long Long Long (long value)
Long (String s)
Long l = new Long(100);
Long l = new Long("100");
float Float Float (double value)
Float (float value)
Float (String s)
Float f = new Float(1.0);
Float f2 = new Float(1.0f);
Float f3 = new Float("1.0f");
double Double Double (double value)
Double (String s)
Double d = new Double(1.0);
Double d = new Double("1.0");

wrapper ν΄λž˜μŠ€λ“€μ€ λͺ¨λ‘ equals()κ°€ μ˜€λ²„λΌμ΄λ”© λ˜μ–΄μžˆκΈ° λ•Œλ¬Έμ— μ£Όμ†Œ 값이 μ•„λ‹Œ 객체가 가지고 μžˆλŠ” 값을 λΉ„κ΅ν•˜κ²Œ λ©λ‹ˆλ‹€. λ˜ν•œ wrapper ν΄λž˜μŠ€λ“€μ€ MAX_VALUE, MIN_VALUE, SIZE, TYPE λ“±μ˜ static 멀버λ₯Ό κ³΅ν†΅μ μœΌλ‘œ 가지고 μžˆμŠ΅λ‹ˆλ‹€.

 

Wrapper 클래슀의 λ©”λͺ¨λ¦¬ ν• λ‹Ή

Wrapper ν΄λž˜μŠ€λ“€μ€ μš°λ¦¬κ°€ 기쑴에 μ•Œλ˜ κΈ°λ³Έν˜•κ³ΌλŠ” λ‹€λ₯Έ 크기의 λ©”λͺ¨λ¦¬λ₯Ό ν• λ‹Ήν•©λ‹ˆλ‹€. 

int a = 4;
Integer b = 16;

μœ„ μ½”λ“œλ₯Ό μ˜ˆμ‹œλ‘œ 듀어보면 aλŠ” int의 크기인 4byteκ°€ ν• λ‹Ήλ˜μ§€λ§Œ, b 같은 경우 16byteκ°€ ν• λ‹Ήλ©λ‹ˆλ‹€. κ·Έ μ΄μœ λŠ” wrapperλŠ” 클래슀 포인터, ν”Œλž˜κ·Έ, 락(Lock), int κ°’ κΉŒμ§€ 총 4개의 valueλ₯Ό μ €μž₯ν•΄μ•Ό ν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

 

Wrapper 클래슀의 캐싱

Wrapper ν΄λž˜μŠ€λŠ” 일정 κ΅¬κ°„μ˜ κΈ°λ³Έ 값을 미리 생성해 놓고 μžˆμŠ΅λ‹ˆλ‹€. μ•„λž˜ μ½”λ“œλŠ” μ‹€μ œ Integer 클래슀의 μ½”λ“œμž…λ‹ˆλ‹€.

    /**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * jdk.internal.misc.VM class.
     */

    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

ν˜„μž¬ -128 ~ 127κΉŒμ§€μ˜ 값을 κ°€μ§€λŠ” Integer μΈμŠ€ν„΄μŠ€λ₯Ό 미리 μƒμ„±ν•˜κ³   μžˆλŠ” 것을 μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€.

    /**
     * Returns an {@code Integer} instance representing the specified
     * {@code int} value.  If a new {@code Integer} instance is not
     * required, this method should generally be used in preference to
     * the constructor {@link #Integer(int)}, as this method is likely
     * to yield significantly better space and time performance by
     * caching frequently requested values.
     *
     * This method will always cache values in the range -128 to 127,
     * inclusive, and may cache other values outside of this range.
     *
     * @param  i an {@code int} value.
     * @return an {@code Integer} instance representing {@code i}.
     * @since  1.5
     */
    @HotSpotIntrinsicCandidate
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

λ”°λΌμ„œ valueOf λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν–ˆμ„ λ•Œ -127 ~ 128 λ²”μœ„μ˜ 값이 λ“€μ–΄μ˜¨λ‹€λ©΄ μΊμ‹±λœ 값을 내보내고 λ²”μœ„ 밖이라면 μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€λ₯Ό ν• λ‹Ήν•©λ‹ˆλ‹€.

Integer 클래슀 뿐만 μ•„λ‹ˆλΌ, Byte, Short, Long, Character μ—­μ‹œ 자체적으둜 캐싱을 μ‚¬μš©ν•˜κ³  μžˆμ§€λ§Œ Float와 DoubleλŠ” μ‹€μˆ˜μ΄κΈ° λ•Œλ¬Έμ— λ²”μœ„ 예츑이 νž˜λ“€μ–΄ 자체적으둜 캐싱을 ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.