item 7 sijun - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

์•„์ดํ…œ7 ๋‹ค ์“ด ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ํ•ด์ œํ•˜๋ผ

์ž๋ฐ”์ฒ˜๋Ÿผ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๋ฅผ ๊ฐ–์ถ˜ ์–ธ์–ด๋Š” ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ์— ๋” ์ด์ƒ ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์•„๋„ ๋œ๋‹ค๋Š” ๋ง์€ ์‚ฌ์‹ค์ด ์•„๋‹ˆ๋‹ค.

์ด๋ฒˆ item์—์„œ๋Š” ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ(๋‹ค ์“ด ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ํ•ด์ œํ•ด์•ผํ• ) 3๊ฐ€์ง€ ๊ฒฝ์šฐ๋ฅผ ์‚ดํŽด๋ณธ๋‹ค.

๋‹ค ์“ด ์ฐธ์กฐ(obsolete reference) : ํ”„๋กœ๊ทธ๋žจ์—์„œ ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฐ์ฒด์˜ reference

1. ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ง์ ‘ ๊ด€๋ฆฌํ•˜๋Š” ํด๋ž˜์Šค์˜ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜

public class Stack {
	private Object[] elements;
	private int size = 0;
	private static final int DEFAULT_INITIAL_CAPACITY = 16;

	public Stack() {
		elements = new Object[DEFAULT_INITIAL_CAPACITY];
	}

	public void push(Object e) {
		ensureCapacity();
		elements[size++] = e;
	}

	public Object pop() {
		if (size == 0)
			throw new EmptyStackException();
		return elements[--size]; // ๋ฌธ์ œ : pop() ๋Œ€์ƒ์„ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๊ฐ€ ํšŒ์ˆ˜ํ•˜์ง€ ์•Š์Œ
	}

	private void ensureCapacity() {
		if (elements.length == size)
			elements = Arrays.copyOf(elements, 2 * size + 1);
	}
}

์œ„ ์ฝ”๋“œ ์˜ˆ์ œ์—์„œ, ๋‹ค ์“ด ์ฐธ์กฐ๋ฅผ ๊ฐ€์ง€๊ฒŒ๋˜๋Š” ์ฝ”๋“œ๋กœ ์ธํ•ด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ์ผ์–ด๋‚œ๋‹ค.

pop() ๋ฉ”์„œ๋“œ๋Š” size ๋ณ€์ˆ˜๋ฅผ 1๋งŒํผ ๊ฐ์†Œ์‹œํ‚ค๊ณ , elements array๋ฅผ --size๋งŒํผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

ํ•˜์ง€๋งŒ, Stack class๊ฐ€ elements ๋ฐฐ์—ด์„ ์ง์ ‘ ๊ฐ€์ง€๊ณ  ์ €์žฅ์†Œ ํ’€์„ ๋งŒ๋“ค์–ด ์›์†Œ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค. ๋”ฐ๋ผ์„œ elements์˜ ์›์†Œ๋“ค์ด ๋ถˆํ•„์š”ํ•œ ๊ฒƒ์ธ์ง€ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๋Š” ์•Œ ์ˆ˜๊ฐ€ ์—†๋‹ค.

๊ทธ๋ž˜์„œ ์ž๊ธฐ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ง์ ‘ ๊ด€๋ฆฌํ•˜๋Š” ํด๋ž˜์Šค๋ผ๋ฉด ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” ํ•ญ์‹œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜์— ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค.

public Object pop(){
	if (size == 0)
		throw new EmptyStackException();
	Object result = elements[--size];
	elements[size] = null; // ๋‹ค ์“ด ์ฐธ์กฐ ํ•ด์ œ
	return result;
}

2. ์บ์‹œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜

WeakHashMap ์‚ฌ์šฉ

WeakHaspMap์€ key๋ฅผ ์ฐธ์กฐํ•˜๋Š” reference๊ฐ€ ์—†์œผ๋ฉด, ํ•ด๋‹น ํ‚ค๋ฅผ ์ž๋™์œผ๋กœ GC๊ฐ€ ๋ฒ„๋ ค์ฃผ๋Š” HashMap์˜ ํ•œ ์ข…๋ฅ˜์ด๋‹ค.

์บ์‹œ ์™ธ๋ถ€์—์„œ ํ‚ค(key)๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋™์•ˆ๋งŒ ์—”ํŠธ๋ฆฌ๊ฐ€ ์‚ด์•„ ์žˆ๋Š” ์บ์‹œ๊ฐ€ ํ•„์š”ํ•œ ์ƒํ™ฉ์ด๋ผ๋ฉด WeakHashMap์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ฏธ์‚ฌ์šฉ ์—”ํŠธ๋ฆฌ ๊ด€๋ฆฌ

์บ์‹œ๋ฅผ ๋งŒ๋“ค ๋•Œ ๋ณดํ†ต์€ ์บ์‹œ ์—”ํŠธ๋ฆฌ์˜ ์œ ํšจ ๊ธฐ๊ฐ„์„ ์ •ํ™•ํžˆ ์ •์˜ํ•˜๊ธฐ ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์— ์‹œ๊ฐ„์ด ์ง€๋‚ ์ˆ˜๋ก ์—”ํŠธ๋ฆฌ์˜ ๊ฐ€์น˜๋ฅผ ๋–จ์–ด๋œจ๋ฆฌ๋Š” ๋ฐฉ์‹์„ ํ”ํžˆ ์‚ฌ์šฉํ•œ๋‹ค.

์ด๋Ÿฐ ๋ฐฉ์‹์—์„œ๋Š” ์“ฐ์ง€ ์•Š๋Š” ์—”ํŠธ๋ฆฌ๋ฅผ ์ด๋”ฐ๊ธˆ ์ฒญ์†Œํ•ด์ค˜์•ผ ํ•œ๋‹ค.

Scheduled ThreadPoolExecutor ๊ฐ™์€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ๋ฅผ ํ™œ์šฉํ•˜๊ฑฐ๋‚˜ ์บ์‹œ์— ์ƒˆ ์—”ํŠธ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ ๋ถ€์ˆ˜ ์ž‘์—…์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ์ง„ํ–‰ํ•˜๋ฉด ๋œ๋‹ค.

LinkedHashMap์€ removeEldestEntry ๋ฉ”์„œ๋“œ๋ฅผ ์จ์„œ ํ›„์ž์˜ ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค.

3. ๋ฆฌ์Šค๋„ˆ ํ˜น์€ ์ฝœ๋ฐฑ ๋ˆ„์ˆ˜

๋ฆฌ์Šค๋„ˆ(listener) ํ˜น์€ ์ฝœ๋ฐฑ(callback) ๋‚ด์—์„œ๋„ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ฝœ๋ฐฑ์„ ๋“ฑ๋ก๋งŒ ํ•˜๊ณ  ๋ช…ํ™•ํžˆ ํ•ด์ง€ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ๋ญ”๊ฐ€ ์กฐ์น˜ํ•ด์ฃผ์ง€ ์•Š๋Š” ํ•œ ์ฝœ๋ฐฑ์€ ๊ณ„์† ์Œ“์—ฌ๊ฐˆ ๊ฒƒ์ด๋‹ค. ์ด๋Ÿด ๋•Œ ์ฝœ๋ฐฑ์€ ์•ฝํ•œ ์ฐธ์กฐ(weak reference)๋กœ ์ €์žฅํ•˜๋ฉด ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ๊ฐ€ ์ฆ‰์‹œ ์ˆ˜๊ฑฐํ•ด๊ฐ„๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด WeakHashMap์— ํ‚ค๋กœ ์ €์žฅํ•˜๋ฉด ๋œ๋‹ค.