item 54 jihoonKim - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

[item54] null์ด ์•„๋‹Œ, ๋นˆ ์ปฌ๋ ‰์…˜์ด๋‚˜ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•˜๋ผ

// ๋”ฐ๋ผ ํ•˜์ง€ ๋ง ๊ฒƒ! - ์žฌ๊ณ ๊ฐ€ ์—†๋‹ค๊ณ  ํŠน๋ณ„ ์ทจ๊ธ‰ํ•  ์ด์œ ๋Š” ์—†๋‹ค.

private final List<Cheese> cheesesInStock = ...;

/**
 * @return ๋งค์žฅ ์•ˆ์˜ ๋ชจ๋“  ์น˜์ฆˆ ๋ชฉ๋ก์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
 * 	๋‹จ, ์žฌ๊ณ ๊ฐ€ ํ•˜๋‚˜๋„ ์—†๋‹ค๋ฉด null์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
 */
public List<Cheese> getCheeses() {
	return cheesesInStock.isEmtpy() ? null
		: new ArrayList<>(cheesesInStock);
}
// client ์ธก์—์„œ null์„ ๋ฆฌํ„ดํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ•ญ์ƒ ์ด์™€ ๊ฐ™์€ ๋ฐฉ์–ด์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด์ค˜์•ผ ํ•œ๋‹ค.
List<Cheese> cheeses = shop.getCheeses();
if (cheeses != null && cheeses.contains(Cheese.M\ozzarell
	...
}

๋นˆ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ• ๋‹นํ•˜์—ฌ ๋ฆฌํ„ดํ•˜๋Š” ๊ฒƒ์ด null ๋ฆฌํ„ด๋ณด๋‹ค ๋‚˜์€ ์ 

  • ์„ฑ๋Šฅ ์ €ํ•˜์˜ ์ฃผ๋ฒ”์ด๋ผ๊ณ  ํ™•์ธ๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด ์ด ์ •๋„ ์„ฑ๋Šฅ ์ฐจ์ด๋Š” ๊ฑฐ์˜ ์—†๋‹ค.
  • ๋นˆ ์ปฌ๋ ‰์…˜๊ณผ ๋นˆ ๋ฐฐ์—ด์€ ์ƒˆ๋กœ ํ• ๋‹นํ•˜์ง€ ์•Š๊ณ ๋„ ๋ฆฌํ„ดํ•  ์ˆ˜ ์žˆ๋‹ค.

๋นˆ ์ปฌ๋ ‰์…˜ ๋ฆฌํ„ด

// ๋นˆ ์ปฌ๋ ‰์…˜์„ ๋ฆฌํ„ดํ•˜๋Š” ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ
public List<Cheese> getCheeses() {
	return new ArrayList<>(cheesesInStock);
}

๋งค๋ฒˆ ๋˜‘๊ฐ™์€ ๋นˆ '๋ถˆ๋ณ€(immutable)' ์ปฌ๋ ‰์…˜์„ ๋ฆฌํ„ดํ•˜์—ฌ ์ตœ์ ํ™”

  • Colections.emptyList()
  • Colections.emptySet()
  • Colections.emptyMap()
// ์ตœ์ ํ™” - ๋นˆ '๋ถˆ๋ณ€(immutable)' ์ปฌ๋ ‰์…˜ ๋ฆฌํ„ด(๊ผญ ํ•„์š”ํ•  ๋•Œ๋งŒ ์‚ฌ์šฉํ•˜๊ณ , ์„ฑ๋Šฅ ๊ฐœ์„ ์ด ๋˜๋Š”์ง€ ํ™•์ธ ํ•„์ˆ˜)
public List<Cheese> getCheeses() {
	return cheesesInStock.isEmtpy() ? Collections.emptyList()
		: new ArrayList<>(cheesesInStock);
}

์ฐธ๊ณ )

  • ๋ถˆ๋ณ€์€ Thread-safeํ•˜๋‹ค.
  • ๋ถˆ๋ณ€์— add์™€ ๊ฐ™์€ ๋ณ€ํ™”๋ฅผ ์‹œ๋„ํ•œ๋‹ค๋ฉด UnsupportedOperationException์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์กฐ์‹ฌํžˆ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

๋นˆ ๋ฐฐ์—ด ๋ฆฌํ„ด

// ๊ธธ์ด๊ฐ€ 0์ผ ์ˆ˜๋„ ์žˆ๋Š” ๋ฐฐ์—ด์„ ๋ฆฌํ„ดํ•˜๋Š” ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•
public Cheese[] getCheeses() {
	return cheesesInStock.toArray(new Cheese[0]);
}

์ฐธ๊ณ )

  • <T> T[] List.toArray(T[] a) ๋ฉ”์„œ๋“œ๋Š” a์˜ ์‚ฌ์ด์ฆˆ๊ฐ€ ํฌ๋ฉด a ์•ˆ์— ์›์†Œ๋ฅผ ๋‹ด์•„ ๋ฆฌํ„ดํ•œ๋‹ค.
  • a์˜ ์‚ฌ์ด์ฆˆ๊ฐ€ List๋ณด๋‹ค ์ž‘์œผ๋ฉด T[] ํƒ€์ž…์„ ์ƒˆ๋กœ ๋งŒ๋“ค์–ด ๊ทธ ์•ˆ์— ์›์†Œ๋ฅผ ๋‹ด์•„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • cheesesInStock์˜ ์‚ฌ์ด์ฆˆ๊ฐ€ 1 ์ด์ƒ์ด๋ฉด ๋ฐฐ์—ด์„ ์ƒˆ๋กœ ์ƒ์„ฑํ•ด ๋ฆฌํ„ดํ•˜๊ณ , ์‚ฌ์ด์ฆˆ๊ฐ€ 0์ด๋ฉด 0์ธ ๋ฐฐ์—ด์„ ์ƒˆ๋กœ ์ƒ์„ฑํ•ด ๋ฆฌํ„ดํ•œ๋‹ค.

// ์ตœ์ ํ™” - ๊ธธ์ด 0์งœ๋ฆฌ ๋ฐฐ์—ด์„ ๋ฏธ๋ฆฌ ์„ ์–ธํ•ด๋‘๊ณ  ๋งค๋ฒˆ ๊ทธ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜(๊ธธ์ด 0์ธ ๋ฐฐ์—ด์€ ๋ชจ๋‘ ๋ถˆ๋ณ€)
private static final Cheese[] EMTPY_CHEESE_ARRAY = new Cheese[0];

public Cheese[] getCheeses() {	
	return cheesesInStock.toArray(EMTPY_CHEESE_ARRAY);
}

์ฐธ๊ณ )

  • cheesesInStock์˜ ์‚ฌ์ด์ฆˆ๊ฐ€ 1 ์ด์ƒ์ด๋ฉด ๋ฐฐ์—ด์„ ์ƒˆ๋กœ ์ƒ์„ฑํ•ด ๋ฆฌํ„ดํ•˜๊ณ , ์‚ฌ์ด์ฆˆ๊ฐ€ 0์ด๋ฉด EMPTY_CHEESE_ARRAY๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.
  • array identity๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ๊ธฐ์—, ๋ชจ๋“  ๊ณณ์— ์œ„ ์ฝ”๋“œ๋กœ ์น˜ํ™˜ํ•˜๋Š” ๊ฒƒ์€ ์œ ํšจํ•˜์ง€ ์•Š๋‹ค.(https://shipilev.net/blog/2016/arrays-wisdom-ancients/)

๋‹จ์ˆœํžˆ ์„ฑ๋Šฅ ๊ฐœ์„  ๋ชฉ์ ์œผ๋กœ toArray์— ๋„˜๊ธฐ๋Š” ๋ฐฐ์—ด์„ ๋ฏธ๋ฆฌ ํ• ๋‹นํ•˜๋Š” ๊ฑด ์˜คํžˆ๋ ค ์„ฑ๋Šฅ์ด ๋–จ์–ด์ง„๋‹ค๋Š” ์—ฐ๊ตฌ ๊ฒฐ๊ณผ๋„ ์žˆ๋‹ค.

// ๋‚˜์œ ์˜ˆ
return cheesesInStock.toArray(new Cheese[cheesesInStock.size()]);

ํ•ต์‹ฌ ์ •๋ฆฌ

null์€ ์˜ˆ์™ธ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋นˆ ๋ฐฐ์—ด์ด๋‚˜ ๋นˆ ์ปฌ๋ ‰์…˜์„ ๋ฆฌํ„ดํ•˜๋ผ.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ