πŸ‘¨πŸ»β€πŸ’» μ΄νŽ™ν‹°λΈŒ μžλ°” - 객체 생성과 파괴

PeterΒ·2022λ…„ 2μ›” 23일
1
post-thumbnail

2μž₯ - 객체 생성과 파괴


πŸ’‘ μƒμ„±μž λŒ€μ‹  정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ₯Ό κ³ λ €ν•˜λΌ

β€œμ •μ  νŒ©ν„°λ¦¬λ₯Ό μ‚¬μš©ν•˜λŠ” 게 μœ λ¦¬ν•œ κ²½μš°κ°€ 더 λ§ŽμœΌλ―€λ‘œ,
λ¬΄μž‘μ • public μƒμ„±μžλ₯Ό μ œκ³΅ν•˜λ˜ μŠ΅κ΄€μ΄ μžˆλ‹€λ©΄ κ³ μΉ˜μžβ€

1. 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œ

  • κ·Έ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό λ°˜ν™˜ν•˜λŠ” λ‹¨μˆœν•œ 정적 λ©”μ„œλ“œ
  • ex) Boolean.valueOf λ©”μ„œλ“œ
public static Boolean valueOf(boolean b) {
	return b ? Boolean.TRUE : Boolean.FALSE;
}

2. 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œμ˜ μž₯점 5가지

a) 이름을 κ°€μ§ˆ 수 μžˆλ‹€.

  • μƒμ„±μž BigInteger(int, int, Random)κ³Ό 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œ BigInteger.probablePrime 쀑 μ–΄λŠ μͺ½μ΄ β€˜κ°’μ΄ μ†Œμˆ˜μΈ BigIntegerλ₯Ό λ°˜ν™˜ν•œλ‹€β€™λŠ” 의미λ₯Ό 더 잘 μ„€λͺ…ν•  것 같은가?

b) 호좜될 λ•Œλ§ˆλ‹€ μΈμŠ€ν„΄μŠ€λ₯Ό μƒˆλ‘œ μƒμ„±ν•˜μ§€λŠ” μ•Šμ•„λ„ λœλ‹€.

  • ex) Boolean.valueOf(boolean) λ©”μ„œλ“œλŠ” 객체λ₯Ό μ•„μ˜ˆ μƒμ„±ν•˜μ§€ μ•ŠμŒ

c) λ°˜ν™˜ νƒ€μž…μ˜ ν•˜μœ„ νƒ€μž… 객체λ₯Ό λ°˜ν™˜ν•  수 μžˆλŠ” λŠ₯λ ₯이 μžˆλ‹€.

  • ex) μžλ°” μ»¬λ ‰μ…˜ ν”„λ ˆμž„μ›Œν¬μ˜ μœ ν‹Έλ¦¬ν‹° κ΅¬ν˜„μ²΄λ“€ λŒ€λΆ€λΆ„μ€ 단 ν•˜λ‚˜μ˜ μΈμŠ€ν„΄μŠ€ν™” λΆˆκ°€ 클래슀인 java.util.Collectionsμ—μ„œ 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ₯Ό 톡해 μ–»μŒ

d) μž…λ ₯ λ§€κ°œλ³€μˆ˜μ— 따라 맀번 λ‹€λ₯Έ 클래슀의 객체λ₯Ό λ°˜ν™˜ν•  수 μžˆλ‹€.

  • λ°˜ν™˜ νƒ€μž…μ˜ ν•˜μœ„ νƒ€μž…μ΄κΈ°λ§Œ ν•˜λ©΄ μ–΄λ–€ 클래슀의 객체λ₯Ό λ°˜ν™˜ν•˜λ“  상관 μ—†μŒ

e) 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ₯Ό μž‘μ„±ν•˜λŠ” μ‹œμ μ—λŠ” λ°˜ν™˜ν•  객체의 ν΄λž˜μŠ€κ°€ μ‘΄μž¬ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€.

3. 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œμ˜ 단점 2가지

a) 상속을 ν•˜λ €λ©΄ publicμ΄λ‚˜ protected μƒμ„±μžκ°€ ν•„μš”ν•˜λ‹ˆ 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ§Œ μ œκ³΅ν•˜λ©΄ ν•˜μœ„ 클래슀λ₯Ό λ§Œλ“€ 수 μ—†λ‹€.

b) 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œλŠ” ν”„λ‘œκ·Έλž˜λ¨Έκ°€ μ°ΎκΈ° μ–΄λ ΅λ‹€.

  • μƒμ„±μžμ²˜λŸΌ API μ„€λͺ…에 λͺ…ν™•νžˆ λ“œλŸ¬λ‚˜μ§€ μ•ŠμœΌλ‹ˆ μ‚¬μš©μžλŠ” 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œ 방식 클래슀λ₯Ό μΈμŠ€ν„΄μŠ€ν™”ν•  방법을 μ•Œμ•„λ‚΄μ•Ό 함.
  • from, of, valueOf, getType λ“± 널리 μ•Œλ €μ§„ κ·œμ•½μ„ 따라 μ§“λŠ” μ‹μœΌλ‘œ 이 단점을 μ™„ν™”ν•΄μ€˜μ•Ό 함


πŸ’‘ μƒμ„±μžμ— λ§€κ°œλ³€μˆ˜κ°€ λ§Žλ‹€λ©΄ λΉŒλ”λ₯Ό κ³ λ €ν•˜λΌ

β€œμƒμ„±μžλ‚˜ 정적 νŒ©ν„°λ¦¬κ°€ μ²˜λ¦¬ν•΄μ•Ό ν•  λ§€κ°œλ³€μˆ˜κ°€ λ§Žλ‹€λ©΄ λΉŒλ” νŒ¨ν„΄μ„ μ„ νƒν•˜μžβ€

1. λΉŒλ” νŒ¨ν„΄μ˜ 가독성

  • λ§€κ°œλ³€μˆ˜λ₯Ό λ‹€μ–‘ν™”ν•˜μ—¬ μƒμ„±μžλ₯Ό μ—¬λŸ¬κ°œ λ§Œλ“œλŠ” 점측적 μƒμ„±μž νŒ¨ν„΄(telescoping constructor pattern)은 ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œλ₯Ό μž‘μ„±ν•˜κ±°λ‚˜ 읽기 μ–΄λ ΅λ‹€.
    • 예λ₯Ό λ“€μ–΄ ν΄λΌμ΄μ–ΈνŠΈκ°€ μ‹€μˆ˜λ‘œ λ§€κ°œλ³€μˆ˜μ˜ μˆœμ„œλ₯Ό λ°”κΏ” κ±΄λ„€μ€˜λ„ μ»΄νŒŒμΌλŸ¬λŠ” μ•Œμ•„μ±„μ§€ λͺ»ν•˜κ³ , κ²°κ΅­ λŸ°νƒ€μž„μ— μ—‰λš±ν•œ λ™μž‘μ„ ν•˜κ²Œ 됨
  • λΉŒλ” νŒ¨ν„΄μ€ λ©”μ„œλ“œ 체이닝 λ°©μ‹μœΌλ‘œ λ§€κ°œλ³€μˆ˜μ˜ 가독성을 λ†’μ—¬μ€Œ
// 점측적 μƒμ„±μž νŒ¨ν„΄ : 각 λ§€κ°œλ³€μˆ˜κ°€ 무엇인지 ν—·κ°ˆλ¦Ό
new NutrionFacts(240, 8, 100, 0, 35, 27);
new NutrionFacts(100, 7, 120, 60);

// λΉŒλ” νŒ¨ν„΄ : λ§€κ°œλ³€μˆ˜κ°€ 무엇인지 ν‘œν˜„λ˜μ–΄ 있음
new NutrionFacts.Builder(240, 8)
		.calories(100).sodium(35).carbohydrate(27).build();

2. λΉŒλ” νŒ¨ν„΄μ˜ μ•ˆμ „μ„±

  • λ§€κ°œλ³€μˆ˜κ°€ μ—†λŠ” μƒμ„±μžλ‘œ 객체λ₯Ό λ§Œλ“  ν›„, μ„Έν„°(setter) λ©”μ„œλ“œλ“€μ„ ν˜ΈμΆœν•΄ μ›ν•˜λŠ” λ§€κ°œλ³€μˆ˜μ˜ 값을 μ„€μ •ν•˜λŠ” 방식인 μžλ°”λΉˆμ¦ˆ νŒ¨ν„΄(JavaBeans pattern)은 객체가 μ™„μ „νžˆ μƒμ„±λ˜κΈ° μ „κΉŒμ§€ 일관성(consistency)이 λ¬΄λ„ˆμ§„ μƒνƒœμ— λ†“μž„
  • λ°˜λ©΄μ— λΉŒλ” νŒ¨ν„΄μ€ 데이터 일관성, 객체 λΆˆλ³€μ„± 등을 λ§Œμ‘±μ‹œν‚΄
// μžλ°”λΉˆμ¦ˆ νŒ¨ν„΄
NutrionFacts cocaCola = new NutrionFacts();
cocaCola.setServingSize(240);
cocaCola.setServings(8);
cocaCola.setCalories(100);
cocaCola.setSodium(35);
cocaCola.setCarbohydrate(27);


πŸ’‘ private μƒμ„±μžλ‚˜ μ—΄κ±° νƒ€μž…μœΌλ‘œ μ‹±κΈ€ν„΄μž„μ„ λ³΄μ¦ν•˜λΌ

β€œμ‹±κΈ€ν„΄μ„ λ§Œλ“œλŠ” μ„Έ 가지 방법 : public static final ν•„λ“œ 방식, 정적 νŒ©ν„°λ¦¬ 방식, μ—΄κ±° νƒ€μž… 방식”

1. public static final ν•„λ“œ 방식

public class Elvis {
	public static final Elvis INSTANCE = new Elvis();
    private Elvis() { ... }
	
	public void leaveTheBuilding() { ... }
}

// μ‚¬μš©ν•  λ•Œ
Elvis.INSTANCE;
  • μž₯점
    - ν•΄λ‹Ή ν΄λž˜μŠ€κ°€ μ‹±κΈ€ν„΄μž„μ΄ API에 λͺ…λ°±νžˆ λ“œλŸ¬λ‚¨
    - 간결함

2. 정적 νŒ©ν„°λ¦¬ 방식

public class Elvis {
	private static final Elvis INSTANCE = new Elvis();
	private Elvis();
	public static Elvis getInstance() { return INSTANCE; }

	public void leaveTheBuilding() { ... }
}

// μ‚¬μš©ν•  λ•Œ
Elvis.getInstance();
  • μž₯점
    - 마음이 λ°”λ€Œλ©΄ APIλ₯Ό 바꾸지 μ•Šκ³ λ„ 싱글턴이 μ•„λ‹ˆκ²Œ λ³€κ²½ν•  수 있음
    - μ›ν•œλ‹€λ©΄ 정적 νŒ©ν„°λ¦¬λ₯Ό μ œλ„€λ¦­ μ‹±κΈ€ν„΄ νŒ©ν„°λ¦¬λ‘œ λ§Œλ“€ 수 있음
    - 정적 νŒ©ν„°λ¦¬μ˜ λ©”μ„œλ“œ μ°Έμ‘°λ₯Ό κ³΅κΈ‰μž(supplier)둜 μ‚¬μš©ν•  수 있음

3. μ—΄κ±° νƒ€μž… 방식

public enum Elvis {
	INSTANCE;
	
	public void leaveTheBuilding() { ... }
}

// μ‚¬μš©ν•  λ•Œ
Elvis.INSTANCE;
  • λŒ€λΆ€λΆ„ μƒν™©μ—μ„œ 이 방법이 κ°€μž₯ 쒋은 방법이닀
  • 단, λ§Œλ“€λ €λŠ” 싱글턴이 Enum μ™Έμ˜ 클래슀λ₯Ό 상속해야 ν•œλ‹€λ©΄ 이 방법은 μ‚¬μš©ν•  수 μ—†λ‹€


πŸ’‘ μΈμŠ€ν„΄μŠ€ν™”λ₯Ό λ§‰μœΌλ €κ±°λ“  private μƒμ„±μžλ₯Ό μ‚¬μš©ν•˜λΌ

β€œprivate μƒμ„±μž : μΈμŠ€ν„΄μŠ€ν™” 방지, 상속 방지”

1. μΈμŠ€ν„΄μŠ€ν™”λ₯Ό λ§‰μœΌλ €λŠ” 상황

  • java.lang.Math처럼 정적 λ©”μ„œλ“œμ™€ 정적 ν•„λ“œλ§Œμ„ 담은 클래슀λ₯Ό λ§Œλ“€κ³  싢을 λ•Œ
  • java.util.Collections처럼 νŠΉμ • μΈν„°νŽ˜μ΄μŠ€μ˜ κ΅¬ν˜„μ²΄λ₯Ό μƒμ„±ν•΄μ£ΌλŠ” 정적 νŒ©ν„°λ¦¬λ₯Ό λͺ¨μ•„놓고 싢을 λ•Œ
  • final ν΄λž˜μŠ€μ™€ κ΄€λ ¨ν•œ λ©”μ„œλ“œλ“€μ„ λͺ¨μ•„놓을 λ•Œ

2. private μƒμ„±μž

  • ν΄λž˜μŠ€μ— μƒμ„±μžλ₯Ό λͺ…μ‹œν•˜μ§€ μ•ŠμœΌλ©΄ μ»΄νŒŒμΌλŸ¬κ°€ μžλ™μœΌλ‘œ λ§€κ°œλ³€μˆ˜λ₯Ό 받지 μ•ŠλŠ” public μƒμ„±μžλ₯Ό λ§Œλ“€μ–΄ μ€€λ‹€. (즉, μΈμŠ€ν„΄μŠ€ν™” κ°€λŠ₯)
    • μ‚¬μš©μžλŠ” 이 μƒμ„±μžκ°€ μžλ™μƒμ„±λœ 것인지 ꡬ뢄할 수 μ—†μŒ
    • μ‹€μ œλ‘œ 곡개된 APIλ“€μ—μ„œλ„ μ˜λ„μΉ˜ μ•Šκ²Œ μΈμŠ€ν„΄μŠ€ν™”ν•  수 있게 된 ν΄λž˜μŠ€κ°€ μ’…μ’… 있음
  • private μƒμ„±μžλ‘œ μœ„μ˜ 상황을 방지할 수 있음
public class UtilityClass {
	// κΈ°λ³Έ μƒμ„±μžκ°€ λ§Œλ“€μ–΄μ§€λŠ” 것을 λ§‰λŠ”λ‹€(μΈμŠ€ν„΄μŠ€ν™” λ°©μ§€μš©).
	private UtilityClass() {
		throw new AssertionError(); // 클래슀 μ•ˆμ—μ„œ μ‹€μˆ˜λ‘œλΌλ„ μƒμ„±μž ν˜ΈμΆœν•˜μ§€ μ•Šλ„λ‘ 방지	
	}
}
  • 이 방식은 상속을 λΆˆκ°€λŠ₯ν•˜κ²Œ λ§Œλ“€κΈ°λ„ 함. λͺ¨λ“  μƒμ„±μžλŠ” λͺ…μ‹œμ μ΄λ“  λ¬΅μ‹œμ μ΄λ“  μƒμœ„ 클래슀의 μƒμ„±μžλ₯Ό ν˜ΈμΆœν•˜κ²Œ λ˜λŠ”λ°, 이λ₯Ό private으둜 μ„ μ–Έν–ˆμœΌλ‹ˆ ν•˜μœ„ ν΄λž˜μŠ€κ°€ μƒμœ„ 클래슀의 μƒμ„±μžμ— μ ‘κ·Όν•  수 μ—†μŒ


πŸ’‘ μžμ›μ„ 직접 λͺ…μ‹œν•˜μ§€ 말고 의쑴 객체 μ£Όμž…μ„ μ‚¬μš©ν•˜λΌ

β€œμ˜μ‘΄ 객체 μ£Όμž…μ€ 클래슀의 μœ μ—°μ„±, μž¬μ‚¬μš©μ„±, ν…ŒμŠ€νŠΈ μš©μ΄μ„±μ„ κ°œμ„ ν•΄μ€€λ‹€.”

1. 의쑴 객체

  • ex) λ§žμΆ€λ²• 검사기 클래슀(SpellCheker)λ₯Ό λ§Œλ“€ λ•Œ, 사전 객체(dictionary)λ₯Ό μ‚¬μš©ν•΄μ•Όν•¨
    • λ§žμΆ€λ²• 검사기 ν΄λž˜μŠ€κ°€ 사전 객체에 μ˜μ‘΄ν•˜λŠ” 것
    • λ§žμΆ€λ²• κ²€μ‚¬κΈ°λŠ” μ˜μ–΄ 사전, ν•œκΈ€ 사전 λ“± μ—¬λŸ¬ μ’…λ₯˜μ˜ 사전을 지원해야함.
  • μœ„μ™€ 같이 μ‚¬μš©ν•˜λŠ” μžμ›μ— 따라 λ™μž‘μ΄ λ‹¬λΌμ§€λŠ” ν΄λž˜μŠ€μ—λŠ” 정적 μœ ν‹Έλ¦¬ν‹° ν΄λž˜μŠ€λ‚˜ μ‹±κΈ€ν„΄ 방식이 μ ν•©ν•˜μ§€ μ•ŠμŒ

2. 의쑴 객체 μ£Όμž…

public class SpellChecker {
	private final Lexicon dictionary;
	
	public SpellChecker(Lexicon dictionary) {
		this.dictionary = Objects.requireNonNull(dictionary);
	}

	public boolean isValid(String word) { ... }
	public List<String> suggestions(String typo) { ... }
}
  • 의쑴 객체 μ£Όμž… : μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 λ•Œ μƒμ„±μžμ— ν•„μš”ν•œ μžμ›μ„ λ„˜κ²¨μ£ΌλŠ” 방식
  • ν΄λž˜μŠ€λŠ” μ—¬λŸ¬ μžμ› μΈμŠ€ν„΄μŠ€λ₯Ό 지원할 수 있고, ν΄λΌμ΄μ–ΈνŠΈλŠ” μ›ν•˜λŠ” μžμ›μ„ μ‚¬μš©ν•  수 있음
  • 의쑴 객체 μ£Όμž…μ΄ μœ μ—°μ„±κ³Ό ν…ŒμŠ€νŠΈ μš©μ΄μ„±μ„ κ°œμ„ ν•΄μ£ΌκΈ΄ ν•˜μ§€λ§Œ, μ˜μ‘΄μ„±μ΄ 수 μ²œκ°œλ‚˜ λ˜λŠ” 큰 ν”„λ‘œμ νŠΈμ—μ„œλŠ” μ½”λ“œλ₯Ό μ–΄μ§€λŸ½κ²Œ λ§Œλ“€κΈ°λ„ 함
    • μ΄λŠ” λŒ€κ±°(Dagger), 주슀(Guice), μŠ€ν”„λ§(Spring) 같은 의쑴 객체 μ£Όμž… ν”„λ ˆμž„μ›Œν¬λ₯Ό μ‚¬μš©ν•˜μ—¬ ν•΄κ²°ν•˜μž


πŸ’‘ λΆˆν•„μš”ν•œ 객체 생성을 ν”Όν•˜λΌ

β€œλΆˆν•„μš”ν•œ 객체λ₯Ό μƒμ„±ν•˜κ²Œ λ˜λŠ” 4가지 μ˜ˆμ‹œβ€

1. new String(String);

  • μœ„ λ¬Έμž₯은 싀행될 λ•Œλ§ˆλ‹€ String μΈμŠ€ν„΄μŠ€λ₯Ό μƒˆλ‘œ λ§Œλ“ λ‹€.
  • μœ„ λ¬Έμž₯이 반볡문 μ•ˆμ— μžˆλ‹€λ©΄ μ“Έλ°μ—†λŠ” StringμΈμŠ€ν„΄μŠ€κ°€ 수백만 개 λ§Œλ“€μ–΄ 질 μˆ˜λ„ μžˆλŠ” 것
// μ΄λ ‡κ²Œ μ“°μž : 이 방식은 λ˜‘κ°™μ€ λ¬Έμžμ—΄ λ¦¬ν„°λŸ΄μ„ μ‚¬μš©ν•˜λŠ” λͺ¨λ“  μ½”λ“œκ°€ 같은 객체λ₯Ό μž¬μ‚¬μš©ν•¨
String s = "bikini";

2. new Boolean(String);

  • μœ„ λ¬Έμž₯도 λ§ˆμ°¬κ°€μ§€λ‘œ 싀행될 λ•Œ λ§ˆλ‹€ Boolean μΈμŠ€ν„΄μŠ€λ₯Ό μƒˆλ‘œ λ§Œλ“ λ‹€.
  • λŒ€μ‹  정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μž
// μ΄λ ‡κ²Œ μ“°μž 
Boolean.valueOf(String);

3. String.matches(String)

  • String.matches λ©”μ„œλ“œκ°€ λ§Œλ“œλŠ” μ •κ·œν‘œν˜„μ‹μš© Pattern μΈμŠ€ν„΄μŠ€λŠ”, ν•œ 번 μ“°κ³  λ²„λ €μ Έμ„œ κ³§λ°”λ‘œ 가비지 μ»¬λ ‰μ…˜ λŒ€μƒμ΄ λœλ‹€.
    • Pattern은 μž…λ ₯받은 μ •κ·œν‘œν˜„μ‹μ— ν•΄λ‹Ήν•˜λŠ” μœ ν•œ μƒνƒœ λ¨Έμ‹ (finite state machine)을 λ§Œλ“€κΈ° λ•Œλ¬Έμ— μΈμŠ€ν„΄μŠ€ 생성 λΉ„μš©μ΄ λ†’λ‹€
  • String.matchesλ₯Ό μ‚¬μš©ν•˜λŠ” λ‚˜μœ μ˜ˆμ™€ 쒋은 예λ₯Ό μ‚΄νŽ΄λ³΄μž
// λ‚˜μœ 예 : 호좜될 λ•Œ λ§ˆλ‹€ matchesκ°€ μ‹€ν–‰ & λ‚΄λΆ€μ μœΌλ‘œ Pattern 생성
static boolean isRomanNumeral(String s) {
	return s.matches("μ •κ·œμ‹");
}
/*
 쒋은 예 : Pattern μΈμŠ€ν„΄μŠ€λ₯Ό 클래슀 μ΄ˆκΈ°ν™” κ³Όμ •μ—μ„œ 직접 생성해 캐싱해두고, 
          isRomanNumeral λ©”μ„œλ“œκ°€ 호좜될 λ•Œ λ§ˆλ‹€ μž¬μ‚¬μš©
*/
public class RomanNumerals {
	private static final Pattern ROMAN = Pattern.compile("μ •κ·œμ‹");
	
	static boolean isRomanNumeral(String s) {
		return ROMAN.matcher(s).matches();	
	}
}

4. μ˜€ν† λ°•μ‹±(auto boxing)

  • μ˜€ν† λ°•μ‹± : ν”„λ‘œκ·Έλž˜λ¨Έκ°€ κΈ°λ³Έ νƒ€μž…(ex. long)κ³Ό λ°•μ‹±λœ κΈ°λ³Έ νƒ€μž…(ex. Long)을 μ„žμ–΄ μ“Έ λ•Œ μžλ™μœΌλ‘œ μƒν˜Έ λ³€ν™˜ν•΄μ£ΌλŠ” 기술
  • μ˜€ν† λ°•μ‹±μœΌλ‘œ μ„±λŠ₯이 μ €ν•˜λ˜λŠ” μ˜ˆμ‹œλ₯Ό μ‚΄νŽ΄λ³΄μž
private static long sum() {
	Long sum = 0L;
	for(long i = 0; i <= Integer.MAX_VALUE; i++) 
		sum += i; // μ—¬κΈ°μ„œ longνƒ€μž…(i)을 Longνƒ€μž…(sum)에 λ”ν•˜κΈ° μœ„ν•΄ LongμΈμŠ€ν„΄μŠ€κ°€ μƒμ„±λœλ‹€.

	return sum;
}
  • sum λ³€μˆ˜λ₯Ό long이 μ•„λ‹Œ Long으둜 μ„ μ–Έν•΄μ„œ λΆˆν•„μš”ν•œ LongμΈμŠ€ν„΄μŠ€κ°€ μ•½ 2^31κ°œλ‚˜ λ§Œλ“€μ–΄ μ§€κ²Œ λœλ‹€.

β†’ λ°•μ‹±λœ κΈ°λ³Έ νƒ€μž…λ³΄λ‹€λŠ” κΈ°λ³Έ νƒ€μž…μ„ μ‚¬μš©ν•˜κ³ , μ˜λ„μΉ˜ μ•Šμ€ μ˜€ν† λ°•μ‹±μ΄ μˆ¨μ–΄λ“€μ§€ μ•Šλ„λ‘ μ£Όμ˜ν•˜μž


πŸ’‘ λ‹€ μ“΄ 객체 μ°Έμ‘°λ₯Ό ν•΄μ œν•˜λΌ

β€œλ©”λͺ¨λ¦¬ λˆ„μˆ˜λŠ” κ²‰μœΌλ‘œ 잘 λ“œλŸ¬λ‚˜μ§€ μ•Šμ•„ μ‹œμŠ€ν…œμ— μˆ˜λ…„κ°„ μž λ³΅ν•˜λŠ” 사둀도 μžˆλ‹€β€

1. 자기 λ©”λͺ¨λ¦¬λ₯Ό 직접 κ΄€λ¦¬ν•˜λŠ” 클래슀

  • 가비지 μ»¬λ ‰ν„°λŠ” ν”„λ‘œκ·Έλž˜λ¨Έκ°€ μ˜λ„μΉ˜ μ•Šκ²Œ μ‚΄λ €λ‘” 객체λ₯Ό μ•Œμ•„μ±„κΈ° μ–΄λ ΅λ‹€.
    • 객체 μ°Έμ‘° ν•˜λ‚˜λ₯Ό 살렀두면 가비지 μ»¬λ ‰ν„°λŠ” κ·Έ κ°μ²΄λΏμ•„λ‹ˆλΌ κ·Έ 객체가 μ°Έμ‘°ν•˜λŠ” 객체(그리고 또 κ·Έ 객체듀이 μ°Έμ‘°ν•˜λŠ” λͺ¨λ“  객체 ...)λ₯Ό νšŒμˆ˜ν•΄κ°€μ§€ λͺ»ν•œλ‹€.
    • 단 λͺ‡ 개의 객체가 맀우 λ§Žμ€ 객체λ₯Ό νšŒμˆ˜ν•˜μ§€ λͺ»ν•˜κ²Œ ν•  수 μžˆλ‹€λŠ” 것

β†’ 객체 μ°Έμ‘°λ₯Ό λ‹΄λŠ” λ°°μ—΄ 등을 μ‚¬μš©ν•΄μ„œ 자기 λ©”λͺ¨λ¦¬λ₯Ό 직접 κ΄€λ¦¬ν•˜λŠ” ν΄λž˜μŠ€μ—μ„œλŠ” μ›μ†Œλ₯Ό λ‹€ μ‚¬μš©ν•œ μ¦‰μ‹œ κ·Έ μ›μ†Œκ°€ μ°Έμ‘°ν•œ 객체듀을 λ‹€ null처리 ν•΄μ€˜μ•Ό ν•œλ‹€.

2. μΊμ‹œ

  • 객체 μ°Έμ‘°λ₯Ό μΊμ‹œμ— 넣어두고, 객체λ₯Ό λ‹€ μΌλŠ”λ°λ„ ν•œμ°Έ κ·Έλƒ₯ λ†”λ‘λŠ” 경우λ₯Ό μ‘°μ‹¬ν•˜μž

β†’ WeakHashMapλ₯Ό ν™œμš©ν•˜λŠ” λ“± 상황에 따라 λ©”λͺ¨λ¦¬ λˆ„μˆ˜λ₯Ό λ°©μ§€ν•˜μž

3. λ¦¬μŠ€λ„ˆ(listener) ν˜Ήμ€ 콜백(callback)

  • ν΄λΌμ΄μ–ΈνŠΈκ°€ μ½œλ°±μ„ λ“±λ‘λ§Œν•˜κ³  λͺ…ν™•νžˆ ν•΄μ§€ν•˜μ§€ μ•ŠλŠ” κ²½μš°μ— λ­”κ°€ μ‘°μΉ˜ν•˜μ§€ μ•ŠλŠ” ν•œ μ½œλ°±μ€ 계속 μŒ“μ—¬κ°ˆ 것이닀.

β†’ μ½œλ°±μ„ μ•½ν•œ μ°Έμ‘°(weak reference)둜 μ €μž₯ν•˜λ©΄ 가비지 컬렉터가 μˆ˜κ±°ν•΄κ°.

ex) WeakHashMap에 ν‚€λ‘œ μ €μž₯


πŸ’‘ finalizer와 cleaner μ‚¬μš©μ„ ν”Όν•˜λΌ

β€œfinalizer와 cleanerλŠ” μ˜ˆμΈ‘ν•  수 μ—†κ³ , 일반적으둜 λΆˆν•„μš”ν•˜λ‹€.”

1. μˆ˜ν–‰μ‹œμ κ³Ό μˆ˜ν–‰μ—¬λΆ€

  • μˆ˜ν–‰μ‹œμ  : 예츑 λΆˆκ°€, finalizer와 cleanerλŠ” μ¦‰μ‹œ μˆ˜ν–‰λœλ‹€λŠ” 보μž₯이 μ—†μŒ
    • λ”°λΌμ„œ 객체의 μ†Œλ©Έ μ‹œμ μ— μ˜μ‘΄ν•˜λŠ” λ™μž‘μ„ finalizer와 cleaner에 맑기면 μ•ˆ 됨
    • ex) 파일 λ‹«κΈ°
    • C++ destructor의 λ™μž‘μ„ κΈ°λŒ€ν•˜λ©΄ μ•ˆ 됨
  • μˆ˜ν–‰μ—¬λΆ€ : μžλ°” μ–Έμ–΄ λͺ…μ„ΈλŠ” finalizerλ‚˜ cleaner의 μˆ˜ν–‰ μ—¬λΆ€μ‘°μ°¨ 보μž₯ν•˜μ§€ μ•ŠμŒ
    • λ”°λΌμ„œ μƒνƒœλ₯Ό 영ꡬ적으둜 μˆ˜μ •ν•˜λŠ” μž‘μ—…μ„ μ ˆλŒ€ finalizerλ‚˜ cleaner에 맑기면 μ•ˆ 됨
    • ex) DB같은 곡유 μžμ›μ˜ 영ꡬ 락(lock) ν•΄μ œ

2. μ„±λŠ₯κ³Ό λ³΄μ•ˆ 이슈

  • μ„±λŠ₯ : 느림
    • finalizer와 cleanerλŠ” 가비지 μ»¬λ ‰ν„°μ˜ νš¨μœ¨μ„ λ–¨μ–΄λœ¨λ¦Ό
  • λ³΄μ•ˆ : finalizer 곡격에 취약함

3. λŒ€μ²΄μ œ

  • AutoCloseable을 κ΅¬ν˜„ν•΄μ„œ μ‚¬μš©ν•˜μž!
    • finalizerλ‚˜ cleanerλ₯Ό λŒ€μ‹ ν•˜μ—¬ κ·Έμ € AutoCloseable을 κ΅¬ν˜„ν•΄μ£Όκ³ , ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ μΈμŠ€ν„΄μŠ€λ₯Ό λ‹€ μ“°κ³  λ‚˜λ©΄ close λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ λœλ‹€.


πŸ’‘ try-finallyλ³΄λ‹€λŠ” try-with-resourcesλ₯Ό μ‚¬μš©ν•˜λΌ

1. try-finally

static String firstLineOfFile(String path) throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        br.close();
    }
}
  • μ „ν†΅μ μœΌλ‘œ μžμ›μ΄ μ œλŒ€λ‘œ λ‹«νž˜μ„ 보μž₯ν•˜λŠ” μˆ˜λ‹¨μœΌλ‘œ μœ„μ™€ 같이 try-finallyκ°€ μ“°μ˜€λ‹€.
  • μœ„ μ½”λ“œμ—μ„œ μ˜ˆμ™ΈλŠ” try 블둝과 finally 블둝 λͺ¨λ‘μ—μ„œ λ°œμƒν•  수 μžˆλŠ”λ°, μ˜ˆμ»¨λŒ€ 기기에 물리적인 λ¬Έμ œκ°€ 생긴닀면 try블둝 μ•ˆμ˜ readLine λ©”μ„œλ“œκ°€ μ˜ˆμ™Έλ₯Ό λ˜μ§€κ³ , 같은 이유둜 close λ©”μ„œλ“œλ„ μ‹€νŒ¨ν•  것이닀. β†’ 이런 μƒν™©μ—μ„œ μŠ€νƒ 좔적 λ‚΄μ—­μ—λŠ” 두 번째 μ˜ˆμ™Έμ˜ μ •λ³΄λ§Œ λ‚¨κ²Œ λ˜μ–΄ 디버깅에 어렀움을 μ€€λ‹€.
  • λ”ν•˜μ—¬ 이 방법은 μžμ›μ„ 두 개 이상 μ‚¬μš©ν•˜λŠ” 상황(μ•„λž˜ μ˜ˆμ‹œ)μ—μ„œ μ½”λ“œκ°€ 지저뢄해진닀.
// μžμ›μ΄ λ‘˜ 이상이면 try-finally 방식은 λ„ˆλ¬΄ μ§€μ €λΆ„ν•˜λ‹€!
static void copy(String src, String dst) throws IOException {
    InputStream in = new FileInputStream(src);
    try {
        OutputStream out = new FileOutputStream(dst);
        try {
            byte[] buf = new byte[BUFFER_SIZE];
            int n;
            while ((n = in.read(buf)) >= 0)
                out.write(buf, 0, n);
        } finally {
            out.close();
        }
    } finally {
        in.close();
    }
}

2. try-with-resource

// 볡수의 μžμ›μ„ μ²˜λ¦¬ν•˜λŠ” try-with-resources - 짧고 λ§€ν˜Ήμ μ΄λ‹€!
static void copy(String src, String dst) throws IOException {
    try (InputStream   in = new FileInputStream(src);
         OutputStream out = new FileOutputStream(dst)) {
        byte[] buf = new byte[BUFFER_SIZE];
        int n;
        while ((n = in.read(buf)) >= 0)
            out.write(buf, 0, n);
    }
}
  • try-with-resource 버전이 훨씬 κ°„κ²°ν•˜κ³  가독성이 μ’‹λ‹€.
  • λ˜ν•œ try-finally λ°©μ‹κ³ΌλŠ” λ‹€λ₯΄κ²Œ μˆ¨κ²¨μ§„ μ˜ˆμ™Έλ“€λ„ κ·Έλƒ₯ 버렀지지 μ•Šκ³ , μŠ€νƒ 좔적 내역에 β€˜μˆ¨κ²¨μ‘Œλ‹€(suppressed)β€™λŠ” κΌ¬λ¦¬ν‘œλ₯Ό 달고 좜λ ₯λœλ‹€.
profile
https://dev-peter.online/

0개의 λŒ“κΈ€