[Become a Java-MastaπŸ‘¨β€πŸ« 7μ£Όμ°¨] μ• λ…Έν…Œμ΄μ…˜, I/O, μ œλ„€λ¦­, λžŒλ‹€μ‹

λ°°λ­‰Β·2021λ…„ 9μ›” 28일
0
post-thumbnail

🎯 λͺ©ν‘œ

μžλ°”μ˜ Annotation, I/O, Generic, Lambda에 λŒ€ν•΄ ν•™μŠ΅ν•˜κΈ°.

πŸ“Œ ν•™μŠ΅ν•  것

Annotation

I/O

Generic

Lambda


Annotation

μ• λ…Έν…Œμ΄μ…˜(Annotation) : 사전적 의미둜 주석을 μ˜λ―Έν•˜λ©°, ν”„λ‘œκ·Έλž¨μ— λŒ€ν•œ 데이터λ₯Ό μ œκ³΅ν•˜λŠ” λ©”νƒ€λ°μ΄ν„°μ˜ ν•œ ν˜•νƒœ


μ •μ˜ν•˜λŠ” 방법

μ• λ…Έν…Œμ΄μ…˜ νƒ€μž…μ€ java.lang or java.lang.annotationμ—μ„œ μ œκ³΅ν•΄μ£ΌλŠ” 것이 있고 ν•„μš”μ—λ”°λΌ μžμ‹ μ΄ 직접 μ •μ˜ν•΄μ„œ μ‚¬μš©ν•  .

μ• λ…Έν…Œμ΄μ…˜μ„ 직접 μ •μ˜ν•˜λŠ” 방법은 @interface ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ μ •μ˜ν•œλ‹€.

public @interface CustomAnnotation {
    	// Element
	int value();
}

@CustomAnnotation(value = 29)
@CustomAnnotation(29)

@interfaceλŠ” μ• λ…Έν…Œμ΄μ…˜ νƒ€μž…(annotation type)을 μ„ μ–Έν•˜λŠ” ν‚€μ›Œλ“œμ΄κ³ , μ• λ…Έν…Œμ΄μ…˜ νƒ€μž… 선언을 일반적인 μΈν„°νŽ˜μ΄μŠ€ μ„ μ–Έκ³Ό κ΅¬λΆ„ν•˜κΈ° μœ„ν•΄ interface μ•žμ— 기호 @λ₯Ό 뢙인닀.

μ• λ…Έν…Œμ΄μ…˜μ€ ElementλΌλŠ” 것을 λ©€λ²„λ‘œ κ°€μ§ˆ 수 있으며, ElementλŠ” νƒ€μž…κ³Ό μ΄λ¦„μœΌλ‘œ κ΅¬μ„±λ˜λ©° default 값을 κ°€μ§ˆ 수 μžˆλ‹€.

Element의 이름 λ’€μ—λŠ” λ©”μ†Œλ“œλ₯Ό μž‘μ„±ν•˜λŠ” 것 처럼 뒀에 ()λ₯Ό λΆ™μ—¬μ•Ό ν•œλ‹€.

μ •μ˜λœ μ• λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜λŠ” 방법은 @μ• λ…Έν…Œμ΄μ…˜ λͺ…μœΌλ‘œ μ„ μ–Έν•  수 있고, νŠΉμ • ν΄λž˜μŠ€λ‚˜ λ©”μ†Œλ“œ, λ³€μˆ˜μ— λΆ™μ—¬ μ‚¬μš©ν•œλ‹€.

그리고 ν•œ 선언뢀에 μ—¬λŸ¬ μ• λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜λŠ” 것도 κ°€λŠ₯ν•˜λ‹€.

κΈ°λ³Έ ElementλŠ” value이며, ν•΄λ‹Ήν•˜λŠ” 값은 μƒλž΅ν•˜κ³  λ°”λ‘œ μ‚¬μš©μ΄ κ°€λŠ₯ν•˜λ‹€.


μ• λ…Έν…Œμ΄μ…˜μ˜ μš©λ„

  1. 컴파일 νƒ€μž„μ— μ œκ³΅ν•˜λŠ” 정보
    • @Override : μƒμœ„ 클래슀의 λ©”μ„œλ“œλ₯Ό μž¬μ •μ˜ν•˜μ˜€μŒμ„ λ‚˜νƒ€λ‚΄λŠ” Annotation. μƒμœ„ ν΄λž˜μŠ€μ— ν•΄λ‹Ή λ©”μ„œλ“œκ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” 경우 Compilerκ°€ κ²½κ³ ν•˜λŠ” κΈ°λŠ₯을 μ œκ³΅ν•¨.
    • @SuppressWarnings : μ»΄νŒŒμΌλŸ¬κ°€ κ²½κ³ ν•˜λŠ” λ‚΄μš©μ„ Ignore ν•  λ•Œ μ‚¬μš©ν•˜λŠ” Annotation
    • @Generated : μ†ŒμŠ€ μ½”λ“œλ₯Ό μƒμ„±ν•˜λŠ” 도ꡬ에 μ˜ν•΄μ„œ ν•΄λ‹Ή μ½”λ“œκ°€ μžλ™μ μœΌλ‘œ μƒμ„±λ˜μ—ˆμŒμ„ λ‚˜νƒ€λ‚΄λŠ” Annotation
  2. 컴파일 μ‹œκ°„ 및 배포 μ‹œκ°„ 처리 -> μ†Œν”„νŠΈμ›¨μ–΄ 개발툴이 μ• λ…Έν…Œμ΄μ…˜ 정보λ₯Ό μ²˜λ¦¬ν•˜μ—¬ μ½”λ“œ, XML νŒŒμΌλ“±μ„ 생성 κ°€λŠ₯ (μ• λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•œ 곳에 νŠΉμ • μ½”λ“œλ₯Ό μΆ”κ°€ ex) Lombok의 @Getter, @Setter)
  3. λŸ°νƒ€μž„ 처리 -> 일뢀애 λ…Έν…Œμ΄μ…˜μ€ λŸ°νƒ€μž„μ— νŠΉμ • κΈ°λŠ₯을 μ‹€ν–‰ν•˜λ„λ‘ 정보λ₯Ό 제곡 (Java Reflection)
    • μžλ°” λ¦¬ν”Œλ ‰μ…˜(Java Reflection) : ꡬ체적인 클래슀 νƒ€μž…μ„ μ•Œμ§€ λͺ»ν•΄λ„ λŸ°νƒ€μž„ μ‹œμ— 클래슀 μ΄λ¦„λ§Œ μ•Œκ³ μžˆλ‹€λ©΄ κ·Έ 클래슀의 λ©”μ†Œλ“œ, νƒ€μž…, λ³€μˆ˜λ“€μ— μ ‘κ·Όν•  수 μžˆλ„λ‘ ν•΄μ£ΌλŠ” μžλ°” API,
    • @FunctionalInterface : ν•΄λ‹Ή Interfaceκ°€ ν•˜λ‚˜μ˜ λ©”μ„œλ“œλ§Œμ„ μ œκ³΅ν•˜λŠ” ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μž„μ„ λ‚˜νƒ€λ‚΄λŠ” Annotation
    • @Deprecated : 더 이상 μ§€μ›ν•˜μ§€ μ•ŠλŠ” κΈ°λŠ₯μž„μ„ μ•Œλ €μ£ΌλŠ” Annotation
    • @SafeVarargs : Genericκ³Ό 같은 κ°€λ³€ 인자 Parameterλ₯Ό μ‚¬μš©ν•  λ•Œ λ°œμƒν•˜λŠ” κ²½κ³ λ₯Ό ignore ν•˜λŠ” Annotation
    • @Repeatable : ν•΄λ‹Ή Annotation을 반볡적으둜 μ‚¬μš©ν•  수 있게 μ§€μ›ν•˜λŠ” Annotation
    • @Inherited : Meta Annotation 쀑 ν•˜λ‚˜λ‘œ 써 적용된 λŒ€μƒ Annotation을 ν•˜μœ„ Class, Interfaceμ—κ²Œ μƒμ†μ‹œν‚€λŠ” Annotation

@Retention

@Retention μ—λ…Έν…Œμ΄μ…˜μ€ μ• λ…Έν…Œμ΄μ…˜ 선언에 μ‚¬μš©λ˜λŠ” 메타 μ• λ…Έν…Œμ΄μ…˜μœΌλ‘œ, 마크된 μ—λ…Έν…Œμ΄μ…˜μ„ μ–Έμ œκΉŒμ§€ μœ μ§€ν•  건지 κ²°μ •ν•΄μ£ΌλŠ” μ• λ…Έν…Œμ΄μ…˜μ΄λ‹€.

즉, Java μ»΄νŒŒμΌλŸ¬κ°€ μ• λ…Έν…Œμ΄μ…˜μ„ λ‹€λ£¨λŠ” 방법을 κΈ°μˆ ν•˜λ©°, μ–΄λŠ μ‹œμ κΉŒμ§€ 영ν–₯을 λ―ΈμΉ˜λŠ”μ§€ κ²°μ •ν•œλ‹€.

보쑴할 기간을 νŠΉμ •ν•˜κ²Œ λͺ…μ‹œν•˜μ§€ μ•ŠμœΌλ©΄ 기본값은 클래슀 νŒŒμΌκΉŒμ§€ λ³΄μ‘΄ν•œλ‹€.

ν•΄λ‹Ή 정책듀은 java.lang.annotation.RetentionPolicy에 enum으둜 μ •μ˜λ˜μ–΄ 있으며 μ•„λž˜μ™€ κ°™λ‹€.

  • SOURCE : μ»΄νŒŒμΌλŸ¬κ°€ μ»΄νŒŒμΌν•  λ•Œ ν•΄λ‹Ή μ• λ…Έν…Œμ΄μ…˜ μ œμ™Έ
  • CLASS : μ»΄νŒŒμΌλŸ¬κ°€ μ»΄νŒŒμΌμ—μ„œλŠ” ν•΄λ‹Ή μ• λ…Έν…Œμ΄μ…˜μ„ κ°€μ Έκ°€μ§€λ§Œ λŸ°νƒ€μž„ μ‹œμ—λŠ” 사라짐
  • RUNTIME : λŸ°νƒ€μž„μ—λ„ ν•΄λ‹Ή μ• λ…Έν…Œμ΄μ…˜ μœ μ§€
@Retention(RetentionPolicy.RUNTIME) //λŸ°νƒ€μž„μ—λ„ ν•΄λ‹Ή μ• λ…Έν…Œμ΄μ…˜ μœ μ§€
public @interface CustomAnnotation {
    	// Element
	int value();
}

@Target

@Target μ• λ…Έν…Œμ΄μ…˜μ€ μ• λ…Έν…Œμ΄μ…˜ 선언에 μ‚¬μš©λ˜λŠ” 메타 μ• λ…Έν…Œμ΄μ…˜μœΌλ‘œ, μ• λ…Έν…Œμ΄μ…˜μ„ μ μš©ν•  수 μžˆλŠ” λ²”μœ„λ₯Ό μ •μ˜ν•œλ‹€.

ν•΄λ‹Ή λ²”μœ„λ“€μ€ java.lang.annotation.ElementType에 λ‹€μ–‘ν•œ λ²”μœ„κ°€ μ •μ˜λ˜μ–΄ 있으며 μ•„λž˜μ™€ κ°™λ‹€.

  • TYPE : Class, Interface λ“±μ˜ Level에 μ„ μ–Έ κ°€λŠ₯
  • METHOD : λ©”μ„œλ“œμ— μ„ μ–Έ κ°€λŠ₯
  • FIELD : Enum, μƒμˆ˜, Field λ³€μˆ˜μ— λŒ€ν•΄ μ„ μ–Έ κ°€λŠ₯
  • PARAMETER : λ§€κ°œλ³€μˆ˜μ— μ„ μ–Έ κ°€λŠ₯
  • CONTRUCTOR : μƒμ„±μž Type에 μ„ μ–Έ κ°€λŠ₯
  • LOCAL_VARIABLE : 지역 λ³€μˆ˜μ— λŒ€ν•΄ μ„ μ–Έ κ°€λŠ₯
  • ANNOTATION_TYPE : Annotation에 μ„ μ–Έ κ°€λŠ₯
  • PACKAGE : νŒ¨ν‚€μ§€μ— μ„ μ–Έ κ°€λŠ₯
@Target(ElementType.FIELD) //  Enum, μƒμˆ˜, Field λ³€μˆ˜μ— λŒ€ν•΄ μ„ μ–Έ κ°€λŠ₯
@Retention(RetentionPolicy.RUNTIME) // λŸ°νƒ€μž„μ—λ„ ν•΄λ‹Ή μ• λ…Έν…Œμ΄μ…˜ μœ μ§€
public @interface CustomAnnotation {
    	// Element
	int value();
}

@Documented

@Documented μ• λ…Έν…Œμ΄μ…˜μ€ μ• λ…Έν…Œμ΄μ…˜ 선언에 μ‚¬μš©λ˜λŠ” 메타 μ• λ…Έν…Œμ΄μ…˜μœΌλ‘œ, ν•΄λ‹Ή μ• λ…Έν…Œμ΄μ…˜μ— λŒ€ν•œ 정보λ₯Ό Javadocλ¬Έμ„œμ— ν¬ν•¨ν•œλ‹€λŠ” 것을 μ„ μ–Έν•œλ‹€.

@Documented // 이 μ• λ…Έν…Œμ΄μ…˜μ— λŒ€ν•œ 정보λ₯Ό Javadocλ¬Έμ„œμ— 
@Target(ElementType.FIELD) //  Enum, μƒμˆ˜, Field λ³€μˆ˜μ— λŒ€ν•΄ μ„ μ–Έ κ°€λŠ₯
@Retention(RetentionPolicy.RUNTIME) // λŸ°νƒ€μž„μ—λ„ ν•΄λ‹Ή μ• λ…Έν…Œμ΄μ…˜ μœ μ§€
public @interface CustomAnnotation {
    	// Element
	int value();
}

Annotation Processor

Annotation ProcessorλŠ” μ• λ…Έν…Œμ΄μ…˜μ„ μ΄μš©ν•˜μ—¬ ν”„λ‘œμ„ΈμŠ€λ₯Ό μ²˜λ¦¬ν•˜λŠ” 것을 μ˜λ―Έν•˜λ©°, μ»΄νŒŒμΌλŸ¬κ°€ 컴파일 쀑에 μƒˆλ‘œμš΄ μ†ŒμŠ€μ½”λ“œλ₯Ό μƒμ„±ν•˜κ±°λ‚˜ 기쑴의 μ½”λ“œ 변경을 κ°€λŠ₯ν•˜κ²Œ ν•œλ‹€.

특히 컴파일 λ‹¨κ³„μ—μ„œ μ• λ…Έν…Œμ΄μ…˜μ— μ •μ˜λœ μ•‘μ…˜μ„ μ²˜λ¦¬ν•˜λŠ”λ°, 이것은 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ μ‹€ν–‰λ˜κΈ° μ „ 컴파일 νƒ€μž„μ— 미리 체크λ₯Ό ν•΄μ£ΌκΈ° λ•Œλ¬Έμ— μ• λ…Έν…Œμ΄μ…˜μ΄ μ˜λ„ν•œλŒ€λ‘œ 이루어지지 μ•ŠμœΌλ©΄ 눈으둜 확인할 수 μžˆλŠ” μ—λŸ¬λ‚˜ κ²½κ³ λ₯Ό 보여쀀닀.

μ• λ…Έν…Œμ΄μ…˜ ν”„λ‘œμ„Έμ„œμ˜ κ°€μž₯ λŒ€ν‘œμ μΈ μ˜ˆλ‘œλŠ” Lombok λΌμ΄λΈŒλŸ¬λ¦¬κ°€ μžˆλ‹€.

Getter, Setter와 같이 반볡적이고 μ€‘λ³΅λ˜λŠ” λ§Žμ€ μ½”λ“œλ₯Ό μ–‘μ‚°ν•˜λŠ” μ½”λ“œ(boilerplate code)λ₯Ό μ΅œμ†Œν™”ν•˜κ³  핡심적인 κΈ°λŠ₯을 λͺ…ν™•ν•˜κ²Œ 확인할 수 μžˆλ„λ‘ ν•œλ‹€.

μ• λ…Έν…Œμ΄μ…˜ ν”„λ‘œμ„Έμ„œλ₯Ό μž‘μ„±ν•˜κ³  λ“±λ‘ν•˜κΈ° μœ„ν•΄μ„œλŠ” AbstractProcessror 클래슀λ₯Ό 상속받아야 ν•˜λŠ”λ°, Lombok λ˜ν•œ AbstractProcessorλ₯Ό 상속받아 μ• λ…Έν…Œμ΄μ…˜ ν”„λ‘œμ„Έμ„œλ₯Ό μ •μ˜ν•œ 것이닀.

  1. Lombok
    • @Getter @Setter @Builder
  2. AutoService :
    • java.util.ServiceLoader 용 파일 생성 μœ ν‹Έλ¦¬ν‹°
    • λ¦¬μ†ŒμŠ€ νŒŒμΌμ„ λ§Œλ“€μ–΄ 쀌.
    • META-INF λ°‘μ˜ service 밑에 ServiceLoader용 λ ˆμ§€μŠ€νŠΈλ¦¬ νŒŒμΌμ„ λ§Œλ“€μ–΄ 쀌.
  3. @Override
    • μ»΄νŒŒμΌλŸ¬κ°€ μ˜€λ²„λΌμ΄λ”©ν•˜λŠ” λ©”μ„œλ“œκ°€ 잘λͺ»λœ λŒ€μƒμž„μ„ μ²΄ν¬ν•΄μ£ΌλŠ” 것도 μ• λ…Έν…Œμ΄μ…˜ ν”„λ‘œμ„Έμ„œμž„
  4. Dagger2
    • 컴파일 νƒ€μž„ DI 제곡 -> λŸ°νƒ€μž„ λΉ„μš©μ΄ 없어짐.
  5. μ•ˆλ“œλ‘œμ΄λ“œ 라이브러리
    • ButterKnife : @BindView (λ·° 아이디와 μ• λ…Έν…Œμ΄μ…˜ 뢙인 ν•„λ“œ 바인딩)
    • DeepLinkDispatcher : νŠΉμ • URI 링크λ₯Ό Activity둜 μ—°κ²°ν•  λ•Œ μ‚¬μš©

I/O

I/OλŠ” Input(μž…λ ₯) and Output(좜λ ₯)의 μ•½μžμ΄λ‹€.

I/O의 κ°„λ‹¨ν•œ μ˜ˆμ‹œλŠ”, ν‚€λ³΄λ“œλ‘œ ν…μŠ€νŠΈλ₯Ό μž…λ ₯ν•˜κ³  λͺ¨λ‹ˆν„°λ‘œ μž…λ ₯ν•œ ν…μŠ€νŠΈλ₯Ό 좜λ ₯ν•˜λŠ” 것이닀.

기쑴의 IO(I/O)방식은 슀트림 λ°©μ‹μ˜ μž…μΆœλ ₯인데, 이 λ°©μ‹μœΌλ‘œλŠ” λ„€νŠΈμ›Œν¬μƒμ—μ„œ μ΄λ£¨μ–΄μ§€λŠ” μž…μΆœλ ₯의 속도가 ν•˜λ“œμ›¨μ–΄μ—μ„œ μ΄λ£¨μ–΄μ§€λŠ” μž…μΆœλ ₯ 속도에 λΉ„ν•΄ ν˜„μ €νžˆ 느리기 λ•Œλ¬Έμ— 문제점이 생겼닀.

λ˜ν•œ 슀트림 방식은 병λͺ©ν˜„상에 맀우 μ·¨μ•½ν•˜λ‹€λŠ” 단점이 있고 λ„€νŠΈμ›Œν¬μ˜ λ°œμ „λ³΄λ‹€ ν•˜λ“œμ›¨μ–΄μ˜ λ°œμ „μ†λ„κ°€ μ•žμ„œλ‚˜κ°€λ©΄μ„œ μƒˆλ‘œμš΄ I/O 방식이 ν•„μš”ν•΄μ‘Œλ‹€.

κ·Έλž˜μ„œ μ΄λŸ¬ν•œ λ„€νŠΈμ›Œν¬ ν™˜κ²½μ—μ„œμ˜ λ¬Έμ œμ μ„ ν•΄κ²°ν•˜κΈ° μœ„ν•΄μ„œ NIO(NEW I/O)방식이 λ‚˜νƒ€λ‚¬λ‹€.

ꡬ뢄IONIO
μž…μΆœλ ₯μŠ€νŠΈλ¦Όμ±„λ„
버퍼non-버퍼버퍼
비동기지원 μ•ˆν•¨μ§€μ›
λΈ”λ‘œν‚ΉλΈ”λ‘œν‚Ήλ§Œ μ§€μ›λΈ”λ‘œν‚Ή / non-λΈ”λ‘œν‚Ή λͺ¨λ‘ 지원

Stream

Streamμ΄λž€, ν•œ λ°©ν–₯으둜 μ—°μ†μ μœΌλ‘œ ν˜λŸ¬κ°€λŠ” 것을 μ˜λ―Έν•œλ‹€.

Untitled

이 Stream이 ν”„λ‘œκ·Έλž˜λ°μ—μ„œλŠ” 데이터가 ν•œ λ°©ν–₯으둜 흘러갈 수 μžˆλ„λ‘ λ„μ™€μ£ΌλŠ” κ΄€, ν†΅λ‘œλΌλŠ” 의미둜 μ‚¬μš©λœλ‹€.

μž…μΆœλ ₯ λ…Έλ“œμ— 직접 μ—°κ²°λ˜λŠ” Stream을 λ…Έλ“œμŠ€νŠΈλ¦Όμ΄λΌκ³  ν•˜κ³ , μ΄λŠ” ν•„μˆ˜ λ‹€.

그리고 λ‹€λ₯Έ μŠ€νŠΈλ¦Όμ„ λ³΄μ‘°ν•˜λŠ” κΈ°λŠ₯적인 Stream을 ν•„ν„°μŠ€νŠΈλ¦Όμ΄λΌκ³  ν•˜λ©°, μ΄λŠ” μ˜΅μ…˜ 이닀.

λ°μ½”λ ˆμ΄ν„° νŒ¨ν„΄μœΌλ‘œ λ…Έλ“œμŠ€νŠΈλ¦Όμ— ν•„ν„°μŠ€νŠΈλ¦Όμ΄ μΆ”κ°€λ˜λŠ” 방식이닀.


Stream이 데이터λ₯Ό μ–΄λ–€ λ°©μ‹μœΌλ‘œ μ „λ‹¬ν•˜λŠλƒμ— 따라 2κ°€μ§€λ‘œ ꡬ뢄할 수 μžˆλ‹€.

  1. Byte Stream (λ°”μ΄νŠΈ 슀트림)
    • 데이터λ₯Ό Byte λ‹¨μœ„λ‘œ μ£Όκ³  λ°›μŒ
    • Binary 데이터λ₯Ό μž…μΆœλ ₯ν•˜λŠ” 슀트림
    • λͺ¨λ“  μ’…λ₯˜μ˜ 데이터 λ₯Ό 주고받을 수 있음
    • InputStreamκ³Ό OutputStream 클래슀λ₯Ό 상속받아 μ‚¬μš©

    • FileInputStream / FileOutputStream : 파일 μž…μΆœλ ₯ 슀트림
    • ByteArrayInputStream / ByteArrayOutputStream : λ©”λͺ¨λ¦¬ μž…μΆœλ ₯ 슀트림
    • PipedInputStream / PipedOutputStream : ν”„λ‘œμ„ΈμŠ€ μž…μΆœλ ₯ 슀트림
    • AudioInputStream / AudioOutputStream : μ˜€λ””μ˜€ μž₯치 μž…μΆœλ ₯ 슀트림

μžλ°”μ—μ„œ κ°€μž₯ μž‘μ€ νƒ€μž…μΈ char ν˜•μ΄ 2λ°”μ΄νŠΈμ΄λ―€λ‘œ, 1λ°”μ΄νŠΈμ”© μ „μ†‘λ˜λŠ” λ°”μ΄νŠΈ 기반 μŠ€νŠΈλ¦ΌμœΌλ‘œλŠ” μ›ν™œν•œ μ²˜λ¦¬κ°€ νž˜λ“  κ²½μš°κ°€ μžˆλ‹€. μ΄λŸ¬ν•œ 경우λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ μžλ°”λŠ” Character Stream을 지원함

  1. Character Stream (문자 슀트림)
    • 데이터λ₯Ό Character λ‹¨μœ„λ‘œ μ£Όκ³  λ°›μŒ
    • 문자 데이터λ₯Ό 인코딩 μ²˜λ¦¬ν•˜μ—¬ μž…μΆœλ ₯ν•˜λŠ” 슀트림
    • 였직 문자 데이터 만 주고받을 수 있음
    • Reader와 Writer 클래슀λ₯Ό 상속받아 μ‚¬μš©

    • FileReader / FileWriter : 파일 μž…μΆœλ ₯ 슀트림
    • CharArrayReader / CharArrayWriter : λ©”λͺ¨λ¦¬ μž…μΆœλ ₯ 슀트림
    • PipedReader / PipedWriter : ν”„λ‘œμ„ΈμŠ€ μž…μΆœλ ₯ 슀트림
    • StringReader / StringWriter : λ¬Έμžμ—΄ μž…μΆœλ ₯ 슀트림

두 Stream은 λͺ¨λ‘ μ²˜μŒμ—λŠ” byte둜 받아듀이고, κ·Έ λ‹€μŒμ€ 각 Stream이 μ•Œμ•„μ„œ 처리λ₯Ό ν•΄μ€€λ‹€.


ν‘œμ€€ Stream

System ClassλŠ” μžλ°”μ—μ„œ 미리 μ •μ˜ν•΄λ‘” ν‘œμ€€ μž…μΆœλ ₯ 클래슀이며, java.lang νŒ¨ν‚€μ§€μ— ν¬ν•¨λ˜μ–΄ μžˆλ‹€.

  • System.in : ν‘œμ€€ μž…λ ₯ 슀트림
  • System.out : ν‘œμ€€ 좜λ ₯ 슀트림
  • System.err : ν‘œμ€€ μ—λŸ¬ 좜λ ₯ 슀트림

Channel

μ„œλ²„μ™€ ν΄λΌμ΄μ–ΈνŠΈκ°„μ˜ ν†΅μ‹ μˆ˜λ‹¨μ„ μ˜λ―Έν•œλ‹€.

일반적으둜 NIO(new I/O)의 λͺ¨λ“  I/OλŠ” μ±„λ„λ‘œ μ‹œμž‘ν•œλ‹€.

채널은 슀트림과 μœ μ‚¬ν•˜μ§€λ§Œ λͺ‡ 가지 차이점이 μ‘΄μž¬ν•œλ‹€.

  • 비동기적 μž…μΆœλ ₯
  • μŠ€νŠΈλ¦Όμ€ 단방ν–₯ μž…μΆœλ ₯(읽기 λ˜λŠ” μ“°κΈ°) 만 κ°€λŠ₯ν•˜μ§€λ§Œ 채널을 ν†΅ν•΄μ„œλŠ” μ–‘λ°©ν–₯ μž…μΆœλ ₯(읽고 μ“°κΈ°) 이 κ°€λŠ₯ν•˜λ‹€ μžˆλ‹€.
  • 항상 버퍼λ₯Ό μ΄μš©ν•˜μ—¬ μž…μΆœλ ₯을 ν•œλ‹€.

Buffer

데이터λ₯Ό μž„μ‹œ μ €μž₯ν•˜λŠ” 곡간을 μ˜λ―Έν•œλ‹€.

IOμ—μ„œλŠ” 좜λ ₯ 슀트림이 1λ°”μ΄νŠΈλ₯Ό μ“°λ©΄ μž…λ ₯ 슀트림이 1λ°”μ΄νŠΈλ₯Ό μ½λŠ”λ‹€.

NIOμ—μ„œ λ²„νΌλŠ” 채널과 μƒν˜Έμž‘μš©ν•  λ•Œ μ‚¬μš©λœλ‹€. 컀널에 μ˜ν•΄ κ΄€λ¦¬λ˜λŠ” μ‹œμŠ€ν…œ λ©”λͺ¨λ¦¬λ₯Ό 직접 μ‚¬μš©ν•  수 μžˆλŠ” 채널에 의 ν•΄ 직접 read λ˜κ±°λ‚˜ write 될 수 μžˆλŠ” λ°°μ—΄κ³Ό 같은 객체이닀.

μž…μΆœλ ₯을 λ‹΄λ‹Ήν•˜λŠ” μž₯치, ν”„λ‘œμ„ΈμŠ€μ—μ„œ 고속 μž₯치(ν”„λ‘œμ„ΈμŠ€)κ°€ 저속 μž₯치(ν”„λ‘œμ„ΈμŠ€)κ°€ μž‘μ—…μ„ ν•˜λŠ” λ™μ•ˆ κΈ°λ‹€λ¦¬λŠ” μ‹œκ°„μ„ 쀄여 κ°œλ³„ μž‘μ—…λ“€ κ°„μ˜ ν˜‘λ™μ„ μ›ν™œν•˜κ²Œ μ§€μ›ν•˜κΈ° μœ„ν•΄ μ‘΄μž¬ν•œλ‹€.

λ”°λΌμ„œ, 1λ°”μ΄νŠΈμ”© 전달이 μ•„λ‹ˆλΌ κΈ°λ‹€λ¦¬λŠ” λ™μ•ˆ 버퍼에 데이터λ₯Ό μΆ•μ²™ν•˜μ—¬ ν•œλ²ˆμ— μ „λ‹¬ν•˜μ—¬ λΉ λ₯Έ 속도λ₯Ό 보인닀.


InputStream

Byte Stream기반의 μž…λ ₯ 슀트림의 μ΅œμƒμœ„ 클래슀(μΆ”μƒν΄λž˜μŠ€)둜써 λͺ¨λ“  Byte기반 μž…λ ₯ μŠ€νŠΈλ¦Όμ€ 이 클래슀λ₯Ό 상속받고 λ°μ½”λ ˆμ΄ν„° νŒ¨ν„΄μœΌλ‘œ κΈ°λŠ₯을 μΆ”κ°€ν•˜λŠ” λ°©μ‹μœΌλ‘œ 슀트림이 λ§Œλ“€μ–΄μ§„λ‹€.

InputStream ν΄λž˜μŠ€μ—λŠ” μž…λ ₯을 μœ„ν•΄ ν•„μš”ν•œ 기본적인 λ©”μ†Œλ“œλ“€μ΄ μ •μ˜λ˜μ–΄ μžˆλ‹€.

  • int available() : ν˜„μž¬ 읽을 수 μžˆλŠ” byte수λ₯Ό 리턴
  • abstract int read() : InputStreamμœΌλ‘œλΆ€ν„° 1byteλ₯Ό 읽고 리턴.
  • int read(byte[] b) : InputStreamμœΌλ‘œλΆ€ν„° 읽은 λ°”μ΄νŠΈλ“€μ„ byte[] b에 μ €μž₯ν•˜κ³  읽은 λ°”μ΄νŠΈ 수λ₯Ό 리턴.
  • int read(byte[] b, int off, int len) : InputStreamμœΌλ‘œλΆ€ν„° len byte만큼 읽어 byte[] b의 b[ off ] λΆ€ν„° len κ°œκΉŒμ§€ μ €μž₯ν•œ ν›„ 읽은 byte 수인 len 개λ₯Ό 리턴. λ§Œμ•½ len κ°œλ³΄λ‹€ 적은 byteλ₯Ό μ½λŠ” 경우 μ‹€μ œ 읽은 byte수λ₯Ό 리턴
  • void close() : μ‚¬μš©ν•œ μ‹œμŠ€ν…œ λ¦¬μ†ŒμŠ€λ₯Ό λ°˜λ‚© ν›„ μž…λ ₯ μŠ€νŠΈλ¦Όμ„ λ‹«λŠ” λ©”μ†Œλ“œ.close() : μ‚¬μš©ν•œ μ‹œμŠ€ν…œ λ¦¬μ†ŒμŠ€λ₯Ό λ°˜λ‚© ν›„ InputStream을 λ‹«μŒ.

OutputStream

OutputStream λ˜ν•œ Byte Stream기반의 좜λ ₯ 슀트림의 μ΅œμƒμœ„ 클래슀(μΆ”μƒν΄λž˜μŠ€)둜써 λͺ¨λ“  Byte기반 좜λ ₯ μŠ€νŠΈλ¦Όμ€ 이 클래슀λ₯Ό 상속받고 λ°μ½”λ ˆμ΄ν„° νŒ¨ν„΄μœΌλ‘œ κΈ°λŠ₯을 μΆ”κ°€ν•˜λŠ” λ°©μ‹μœΌλ‘œ 슀트림이 λ§Œλ“€μ–΄μ§„λ‹€.

OutputStream ν΄λž˜μŠ€μ—λ„ 좜λ ₯을 μœ„ν•΄ ν•„μš”ν•œ 기본적인 λ©”μ†Œλ“œλ“€μ΄ μ •μ˜λ˜μ–΄ μžˆλ‹€.

  • void flush() : 버퍼에 λ‚¨μ•„μžˆλŠ” OutputStream을을 좜λ ₯
  • abstract void write(int b) : μ •μˆ˜ b의 ν•˜μœ„ 1byteλ₯Ό 좜λ ₯
  • void write(byte[] b) : λ²„νΌμ˜ λ‚΄μš©μ„ 좜λ ₯
  • void write(byte[] b, int off, int len) : b λ°°μ—΄ μ•ˆμ˜ μ‹œμž‘μ  off λΆ€ν„° len 만큼 좜λ ₯
  • void close() : μ‚¬μš©ν•œ μ‹œμŠ€ν…œ λ¦¬μ†ŒμŠ€λ₯Ό λ°˜λ‚© ν›„ OutputStream을 λ‹«μŒ.

파일 읽고 μ“°κΈ°

μžλ°”μ˜ λ‚΄μž₯ 클래슀인 FileReader, FileWriter, BufferedReader, BufferedWriterλ₯Ό μ‚¬μš©ν•˜μ—¬ νŒŒμΌμ„ 읽고 μ“Έ 수 μžˆλ‹€.

File file = new File(PATH);

FileWriter fw = new FileWriter(file);
FileReader fr = new FileReader(file);
BufferedWriter bw = new BufferedWriter(fw);
BufferedReader br = new BufferedReader(fr);

FileReader, FileWriter와 BufferedReader, BufferedWriterλŠ” λ°μ½”λ ˆμ΄ν„° νŒ¨ν„΄μ΄ μ μš©λ¨μ„ μ•Œ 수 μžˆλ‹€.


Generic

Java 5λΆ€ν„° μΆ”κ°€λ˜μ–΄ ν΄λž˜μŠ€μ™€ μΈν„°νŽ˜μ΄μŠ€, λ©”μ†Œλ“œλ₯Ό μ •μ˜ν•  λ•Œ νƒ€μž… λ³€μˆ˜λ₯Ό μ‚¬μš©ν•  수 있게 ν•˜λŠ” 방법이닀.

  • νƒ€μž… λ³€μˆ˜ : 일반적으둜 λŒ€λ¬Έμž μ•ŒνŒŒλ²³ ν•œ κΈ€μžλ‘œ ν‘œν˜„ν•œλ‹€.
    • <T> : Type
    • <E> : Element
    • <K> : Key
    • <N> : Number
    • <V> : Value
    • <R> : Return

컴파일 μ‹œμ˜ 객체의 νƒ€μž…μ„ 체크λ₯Ό ν•΄μ£ΌλŠ” κΈ°λŠ₯을 μ œκ³΅ν•¨μœΌλ‘œμ¨ μ•ˆμ •μ„±μ„ 높이고 ν˜•λ³€ν™˜μ˜ λ²ˆκ±°λ‘œμ›€μ„ 쀄여쀀닀.

Collection λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ ν”νžˆ Generic이 ν™œμš©λœλ‹€.

//List<T>
List<Integer> listG = new ArrayList<>(); // μ œλ„€λ¦­
listG.add(1);
int temp = listG.get(0);

List listNG = new ArrayList(); // μ œλ„€λ¦­ μ‚¬μš© X
listNG.add(1);
temp = (int)listNG.get(0); // ν˜•λ³€ν™˜ ν•„μš”

Generic은 Generic νƒ€μž…κ³Ό Generic λ©”μ†Œλ“œλ‘œ ꡬ뢄할 수 μžˆλ‹€.

Generic νƒ€μž…

νƒ€μž… λ³€μˆ˜κ°€ μžˆλŠ” 클래슀 λ˜λŠ” μΈν„°νŽ˜μ΄μŠ€

class GenericClass<T> {
     ...
}

interface  GenericInterface<T> {
     ...
}

Generic λ©”μ†Œλ“œ

맀개 νƒ€μž…κ³Ό 리턴 νƒ€μž…μœΌλ‘œ νƒ€μž… λ³€μˆ˜λ₯Ό κ°–λŠ” λ©”μ†Œλ“œ

public <T, R> R genericMethod(T t) { }

μ œλ„€λ¦­μ„ μ‚¬μš©ν•  수 μ—†λŠ” 경우

  1. μ œλ„€λ¦­ νƒ€μž…μ˜ 배열을 생성할 경우 : new T[N]은 컴파일 νƒ€μž„μ— λ°°μ—΄μ˜ νƒ€μž…μ„ μ•Œ 수 μ—†κΈ° λ•Œλ¬Έμ— μ‚¬μš©ν•  수 μ—†λ‹€.

  2. static λ³€μˆ˜μ— μ‚¬μš©ν•  경우 : static λ³€μˆ˜λŠ” μΈμŠ€ν„΄μŠ€μ— μ’…μ†λ˜μ§€ μ•ŠμœΌλ―€λ‘œ μΈμŠ€ν„΄μŠ€λ³„ νƒ€μž…μ΄ 변경될 수 μ—†κΈ° λ•Œλ¬Έμ— μ‚¬μš©ν•  수 μ—†λ‹€. (단, static λ©”μ†Œλ“œμ—λŠ” μ œλ„€λ¦­ μ‚¬μš© κ°€λŠ₯)


Generic의 μ£Όμš” κ°œλ…μœΌλ‘œλŠ” Bounded-Typeκ³Ό Wild-Cardκ°€ μžˆλ‹€.


BoundedType

Bounded-Type은 μ œλ„€λ¦­μœΌλ‘œ μ‚¬μš©λ  νƒ€μž… λ³€μˆ˜μ˜ λ²”μœ„λ₯Ό μ œν•œν•˜λŠ” 것이닀.

Generic νƒ€μž…μ— extendsλ₯Ό μ‚¬μš©ν•˜μ—¬ νƒ€μž… λ³€μˆ˜μ˜ λ²”μœ„λ₯Ό μ œν•œν•œλ‹€. (μΈν„°νŽ˜μ΄μŠ€, 클래슀 λͺ¨λ‘ 상관없이 extendsλ₯Ό μ‚¬μš©)

public class CustomGeneric<T extends Number> {
     ...
}

CustomGeneric<Integer> listI = new CustomGeneric<();
CustomGeneric<String> listS = new CustomGeneric<>(); // Bounded-Type으둜 νƒ€μž… λ³€μˆ˜λ₯Ό Number둜 μ œν•œν–ˆκΈ° λ•Œλ¬Έμ— 컴파일 μ—λŸ¬ λ°œμƒ!
public class CustomGeneric<T extends ClassName & InterfaceName> { // & 기호λ₯Ό μ‚¬μš©ν•˜μ—¬ νƒ€μž… λ³€μˆ˜λ₯Ό ν΄λž˜μŠ€μ™€ μΈν„°νŽ˜μ΄μŠ€ 2개둜 μ œν•œ κ°€λŠ₯ 
     ...
}

WildCard

μ œλ„€λ¦­ νƒ€μž…μ„ λ©”μ†Œλ“œμ˜ λ§€κ°œκ°’μœΌλ‘œ 전달할 λ•Œ ꡬ체적인 νƒ€μž…μœΌλ‘œλ§Œ νƒ€μž… μ œν•œμ΄ 생긴닀 κ·ΈλŸ¬ν•œ 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ μ™€μΌλ“œ μΉ΄λ“œλ₯Ό μ‚¬μš©ν•œλ‹€.

? ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ μ™€μΌλ“œ μΉ΄λ“œλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

  • μ œλ„€λ¦­ νƒ€μž… <?> : μ œν•œ μ—†μŒ. λͺ¨λ“  ν΄λž˜μŠ€λ‚˜ μΈν„°νŽ˜μ΄μŠ€ κ°€λŠ₯
  • μ œλ„€λ¦­ νƒ€μž… <? extends μƒμœ„ νƒ€μž…> : νƒ€μž…μ˜ μƒν•œμ„  지정(ν•΄λ‹Ή νƒ€μž… 및 ν•˜μœ„νƒ€μž…λ§Œ, μ΅œμƒμ΄ μ œμ‹œν•œ νƒ€μž…), μ΅œλŒ€ μ œμ‹œλœ μƒμœ„ νƒ€μž…λ³΄λ‹€ 더 μƒμœ„ νƒ€μž…μ„ μ‚¬μš©ν•  수 μ—†μŒ
  • μ œλ„€λ¦­ νƒ€μž… <? super ν•˜μœ„ νƒ€μž…> : νƒ€μž…μ˜ ν•˜ν•œμ„  지정(ν•΄λ‹Ή νƒ€μž… 및 μƒμœ„νƒ€μž…λ§Œ, μ΅œν•˜κ°€ μ œμ‹œν•œ νƒ€μž…), μ΅œμ†Œ μ œμ‹œλœ ν•˜μœ„ νƒ€μž…λ³΄λ‹€ 더 ν•˜μœ„ νƒ€μž…μ„ μ‚¬μš©ν•  수 μ—†μŒ

Erasure

  • μ œλ„€λ¦­μ˜ νƒ€μž… μ†Œκ±°(Generics Type Erasure) : μ»΄νŒŒμΌλŸ¬λŠ” μ œλ„€λ¦­ νƒ€μž…μ„ μ΄μš©ν•΄ μ†ŒμŠ€νŒŒμΌμ„ κ²€μ‚¬ν•˜κ³  λŸ°νƒ€μž„μ—λŠ” ν•΄λ‹Ή νƒ€μž…μ˜ 정보λ₯Ό μ•Œ 수 μ—†λ‹€λŠ” κ°œλ…μ΄λ‹€. 즉, 컴파일된 파일*.classμ—λŠ” μ œλ„€λ¦­ νƒ€μž…μ— λŒ€ν•œ 정보가 μ—†λ‹€λŠ” 뜻.

Erasure κ·œμΉ™

  • UnBounded-Type은 Object
    • ex) (<?>, <T>) => Object
  • Bounded-Type은 extends 뒀에 μž‘μ„±ν•œ 객체
    • ex) <T extends Number> => Number

Lambda

λžŒλ‹€μ‹(Lambda expression)은 λ©”μ†Œλ“œλ₯Ό κ°„λ‹¨ν•˜λ©΄μ„œ λͺ…ν™•ν•œ 식(expression)으둜 ν‘œν˜„ν•œ 것이닀.

λžŒλ‹€μ‹μ€ 인해 이름과 λ¦¬ν„΄νƒ€μž…μ΄ ν•„μš”μ—†μ–΄, 읡λͺ… ν•¨μˆ˜(anonymous function)라고도 ν•œλ‹€.

λžŒλ‹€μ‹μ€ λ©”μ†Œλ“œμ™€ λ™λ“±ν•œ κ²ƒμ²˜λŸΌ λ³΄μ΄μ§€λ§Œ, 사싀 λžŒλ‹€μ‹μ€ 읡λͺ… 클래슀의 객체와 λ™λ“±ν•˜μ—¬ λŸ°νƒ€μž„ μ‹œμ— μΈν„°νŽ˜μ΄μŠ€μ˜ 읡λͺ… κ΅¬ν˜„ 객체둜 μƒμ„±λ˜κ³  λŒ€μž…λ˜λŠ” μΈν„°νŽ˜μ΄μŠ€μ— 따라 κ΅¬ν˜„ μΈν„°νŽ˜μ΄μŠ€κ°€ κ²°μ •λœλ‹€.

Lambda의 λ„μž…μœΌλ‘œ 인해 μžλ°”λŠ” 객체 지ν–₯ 언어인 λ™μ‹œμ— ν•¨μˆ˜ν˜• μ–Έμ–΄κ°€ λ˜μ—ˆλ‹€.


Lambda μ‚¬μš©λ²•

λ©”μ†Œλ“œμ—μ„œ λ©”μ†Œλ“œμ΄λ¦„κ³Ό λ¦¬ν„΄νƒ€μž…μ„ μ œκ±°ν•˜κ³  λ§€κ°œλ³€μˆ˜ {μ‹€ν–‰μ½”λ“œ} 사이에 -> ν™”μ‚΄ν‘œλ₯Ό μΆ”κ°€ν•˜μ—¬

λ§€κ°œλ³€μˆ˜ -> {μ‹€ν–‰μ½”λ“œ} 둜 λžŒλ‹€μ‹μ„ μ‚¬μš©ν•  수 μžˆλ‹€.

λ©”μ†Œλ“œλ₯Ό μ„ μ–Έ ν•  λ•Œλ„ 끝에 μ„Έλ―Έμ½œλ‘  ;을 뢙이지 μ•Šλ“―μ΄, λžŒλ‹€μ‹ λ˜ν•œ λ§ˆμ°¬κ°€μ§€λ‘œ μ„Έλ―Έμ½œλ‘  ;을 뢙이지 μ•ŠλŠ”λ‹€

// λ©”μ†Œλ“œ
λ¦¬ν„΄νƒ€μž… λ©”μ†Œλ“œμ΄λ¦„ (λ§€κ°œλ³€μˆ˜νƒ€μž… λ§€κ°œλ³€μˆ˜) {
    μ‹€ν–‰μ½”λ“œ
}
// λžŒλ‹€μ‹
((λ§€κ°œλ³€μˆ˜) -> {μ‹€ν–‰μ½”λ“œ})
// λ§€κ°œλ³€μˆ˜ :
// λ§€κ°œλ³€μˆ˜κ°€ ν•˜λ‚˜μΌ λ•ŒλŠ” ()λ₯Ό μƒλž΅ν•  수 μžˆλ‹€.   
// 단, λ§€κ°œλ³€μˆ˜ νƒ€μž…μ΄ 있으면(λŒ€λΆ€λΆ„μ˜ λ§€κ°œλ³€μˆ˜ νƒ€μž…μ€ 좔둠이 κ°€λŠ₯ν•΄μ„œ μƒλž΅ κ°€λŠ₯) ()λ₯Ό μƒλž΅ν•  수 μ—†λ‹€.  
// μ½”λ“œ : 
// μ‹€ν–‰μ½”λ“œκ°€ ν•˜λ‚˜μΌ λ•ŒλŠ” {}λ₯Ό μƒλž΅ν•  수 μžˆλ‹€.   
// 단, {} μ•ˆμ˜ μ‹€ν–‰μ½”λ“œμ— return ν‚€μ›Œλ“œκ°€ μ‚¬μš©λ˜λŠ” 경우 {}λ₯Ό μƒλž΅ν•  수 μ—†λ‹€. 


// λ©”μ†Œλ“œ
int max(int a, int b) {
    return a > b ? a : b;
}
// λžŒλ‹€μ‹
((a, b) -> a > b ? a : b) // λ§€κ°œλ³€μˆ˜κ°€ a와 b 2κ°œμ΄λ―€λ‘œ () μƒλž΅ λΆˆκ°€. 그리고 return ν‚€μ›Œλ“œκ°€ μ‚¬μš©λ˜μ§€ μ•ŠμœΌλ―€λ‘œ {} μƒλž΅ κ°€λŠ₯

Listλ₯Ό λžŒλ‹€μ‹μœΌλ‘œ μ‘°μž‘ν•˜λŠ” κ°„λ‹¨ν•œ μ˜ˆμ‹œλ₯Ό μ‚΄νŽ΄λ³΄μž.

ArrayList<Integer> list = new ArrayList<Integer>();
for(int i=1; i<=10; ++i) list.add(i);
		
list.replaceAll(e -> e+10); // λͺ¨λ“  μš”μ†Œμ— 10μ”© λ”ν•˜κΈ°
list.removeIf(e -> e%2==1); // ν™€μˆ˜κ°’ μš”μ†Œ μ—†μ• κΈ°
list.forEach(e -> System.out.println(e)); // λͺ¨λ“  μš”μ†Œ 좜λ ₯	

그리고 PSλ₯Ό ν•˜λ‹€λ³΄λ©΄ 자주 μ ‘ν•˜κ²Œ λ˜λŠ” Comparator μΈν„°νŽ˜μ΄μŠ€μ˜ compareλ©”μ†Œλ“œ λ˜ν•œ 읡λͺ… κ΅¬ν˜„ 객체둜 μ‚¬μš©ν•  μˆ˜λ„ μžˆμ§€λ§Œ, λžŒλ‹€μ‹μœΌλ‘œ κ°„λ‹¨ν•˜κ²Œ ν‘œν˜„ν•  수 μžˆλ‹€.

// Comparator μΈν„°νŽ˜μ΄μŠ€μ˜ compareλ©”μ†Œλ“œ 읡λͺ… κ΅¬ν˜„ 객체
Arrays.sort(time, new Comparator<int[]>() {
			@Override
			public int compare(int[] t1, int[] t2) {
				if(t1[0] == t2[0]) return t1[1] - t2[1];
				else return t1[0] - t2[0];
			}
		});
// λžŒλ‹€μ‹
Arrays.sort(time, (t1, t2)->{
			if(t1[0] == t2[0]) return t1[1] - t2[1];
			else return t1[0] - t2[0];
		});

ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€

λžŒλ‹€ ν‘œν˜„μ‹μœΌλ‘œ κ΅¬ν˜„μ΄ κ°€λŠ₯ν•œ μΈν„°νŽ˜μ΄μŠ€λŠ” 좔상 λ©”μ„œλ“œλ₯Ό 1개만 가지고 μžˆλŠ” μΈν„°νŽ˜μ΄μŠ€λ§Œ κ°€λŠ₯ν•˜λ‹€.

κ·Έλž˜μ„œ 좔상 λ©”μ„œλ“œκ°€ 1개인 μΈν„°νŽ˜μ΄μŠ€λ₯Ό ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λΌκ³  ν•œλ‹€.

// 약식 μ‚¬μš© 예제
@FunctionalInterface
interface CustomFunction{
    void customMethod();
}

// μ‚¬μš© 1. λžŒλ‹€μ‹μ„ μ°Έμ‘°ν•˜λŠ” μ°Έμ‘°λ³€μˆ˜λ‘œ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ§€μ •ν•˜κ³ , μ°Έμ‘°λ³€μˆ˜μ—μ„œ λ©”μ†Œλ“œλ₯Ό 호좜
CustomFunction cf = () -> System.out.println("This is FunctionalInterface");
customMethod(cf); // This is FunctionalInterface

// μ‚¬μš© 2. μ°Έμ‘°λ³€μˆ˜ 없이 λ°”λ‘œ λžŒλ‹€μ‹μ„ λ©”μ†Œλ“œλ‘œ μ‚¬μš© 
customMethod() -> System.out.println("This is FunctionalInterface");
// λ§€κ°œλ³€μˆ˜λ₯Ό λ°›κ³  λ¦¬ν„΄ν•΄μ£ΌλŠ” 예제
@FunctionalInterface
interface CustomFunction{
    int customMethod(int a, int b);
}

CustomFunction cf = (a, b) -> a > b ? a : b;
int bigNum = cf.customMethod(1, 2); 

@FunctionalInterface : ν•΄λ‹Ή μΈν„°νŽ˜μ΄μŠ€κ°€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λΌλŠ”κ±Έ μ•Œλ €μ£ΌλŠ” μ• λ…Έν…Œμ΄μ…˜, μΈν„°νŽ˜μ΄μŠ€ μ„ μ–Έμ‹œ ν•΄λ‹Ή μ• λ…Έν…Œμ΄μ…˜μ„ 뢙이면 2개 μ΄μƒμ˜ 좔상 λ©”μ†Œλ“œκ°€ μ„ μ–Έλ˜μ§€ μ•Šμ•˜λŠ”μ§€ μ»΄νŒŒμΌλŸ¬κ°€ μ²΄ν¬ν•˜μ—¬ 2개 μ΄μƒμ˜ 좔상 λ©”μ†Œλ“œκ°€ μ„ μ–Έλ˜μ–΄ μžˆλ‹€λ©΄ 컴파일 μ—λŸ¬κ°€ λ°œμƒν•œλ‹€.

λͺ¨λ“  μ• λ…Έν…Œμ΄μ…˜λ“€μ˜ κΈ°λŠ₯이 κ·Έλ ‡λ“―, @FunctionalInterface은 μ»΄νŒŒμΌλŸ¬μ—κ²Œ 확인을 λΆ€νƒν•˜λŠ” 것일 뿐 μ•ˆλΆ™μ–΄μžˆλ‹€κ³  ν•΄μ„œ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ‘œ λ™μž‘ν•˜μ§€ μ•ŠλŠ” 것은 μ•„λ‹ˆλ‹€.

μžλ°”μ—μ„œ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ œκ³΅ν•˜λŠ” ν‘œμ€€ API java.util.functionλ₯Ό μ œκ³΅ν•΄μ€€λ‹€.


Variable Capture

Variable CaptureλŠ” λžŒλ‹€μ‹μ—μ„œ νŒŒλΌλ―Έν„°λ‘œ λ„˜κ²¨μ§„ λ³€μˆ˜κ°€ μ•„λ‹Œ μ™ΈλΆ€μ—μ„œ μ •μ˜λœ λ³€μˆ˜λ₯Ό μ°Έμ‘°ν•˜λŠ” 것을 μ˜λ―Έν•œλ‹€.

λžŒλ‹€μ‹μ—μ„œ μ ‘κ·Ό κ°€λŠ₯ν•œ λ³€μˆ˜λ“€μ€ μ•„λž˜μ™€ κ°™λ‹€.

  1. 둜컬 λ³€μˆ˜
  2. static λ³€μˆ˜
  3. μΈμŠ€ν„΄μŠ€ λ³€μˆ˜

Variable Captureμ—λŠ” μœ„ λ³€μˆ˜λ“€ 쀑 1. 둜컬 λ³€μˆ˜μ— λŒ€ν•œ μ œμ•½ 쑰건이 μ‘΄μž¬ν•œλ‹€.

  1. 둜컬 λ³€μˆ˜λŠ” final으둜 μ„ μ–Έλ˜μ–΄μ•Ό ν•œλ‹€,
  2. final둜 μ„ μ–Έλ˜μ–΄ μžˆμ§€ μ•Šμ€ 둜컬 λ³€μˆ˜λŠ” Effectively Final(μœ μ‚¬ final; final 처럼 λ™μž‘)이어야 ν•œλ‹€. 즉, κ°’μ˜ μž¬ν• λ‹Ήμ΄ μΌμ–΄λ‚˜λ©΄ μ•ˆλœλ‹€.

λ”°λΌμ„œ, λžŒλ‹€μ‹μ—μ„œ 둜컬 λ³€μˆ˜λ§Œ 변경이 λΆˆκ°€λŠ₯ν•˜κ³ , λ‚˜λ¨Έμ§€ λ³€μˆ˜λ“€μ€ 읽기 및 μ“°κΈ°κ°€ κ°€λŠ₯ν•˜λ‹€.

μ΄λŸ¬ν•œ μ œμ•½μ΄ μ‘΄μž¬ν•˜λŠ” μ΄μœ λŠ” μ•„λž˜μ™€ κ°™λ‹€.

1μ£Όμ°¨μ—μ„œ μ •λ¦¬ν•˜μ˜€λ“―μ΄, JVMμ—μ„œ 둜컬 λ³€μˆ˜λŠ” μŠ€νƒ μ˜μ—­μ— μƒμ„±λœλ‹€.

μ‹€μ œ λ©”λͺ¨λ¦¬μ™€λŠ” 달리 JVMμ—μ„œ μŠ€νƒ μ˜μ—­μ€ μ“°λ ˆλ“œλ§ˆλ‹€ λ³„λ„μ˜ μŠ€νƒμ΄ 또 μƒμ„±λ˜μ–΄ μ“°λ ˆλ“œλΌλ¦¬λŠ” 둜컬 λ³€μˆ˜ κ³΅μœ κ°€ λΆˆκ°€λŠ₯ ν•˜λ‹€.

그리고 JVMμ—μ„œ μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λŠ” νž™ μ˜μ—­μ— μƒμ„±λ˜κΈ° λ•Œλ¬Έμ— μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λŠ” μ“°λ ˆλ“œλΌλ¦¬ κ³΅μœ κ°€ κ°€λŠ₯ν•˜λ‹€.

λžŒλ‹€μ‹μ€ 둜컬 λ³€μˆ˜κ°€ μ‘΄μž¬ν•˜λŠ” μŠ€νƒμ— 직접 μ ‘κ·Όν•˜μ§€ μ•Šκ³ , 둜컬 λ³€μˆ˜λ₯Ό μžμ‹ (λžŒλ‹€κ°€ λ™μž‘ν•˜λŠ” λ³„λ„μ˜ μ“°λ ˆλ“œ)의 μŠ€νƒμ— λ³΅μ‚¬ν•œλ‹€.

κ·Έλž˜μ„œ λ§Œμ•½ μ›λž˜ 지역 λ³€μˆ˜κ°€ μžˆλŠ” μ“°λ ˆλ“œλŠ” μ‚¬λΌμ Έμ„œ 둜컬 λ³€μˆ˜κ°€ 사라져도 μ—λŸ¬κ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.

κ·Έλž˜μ„œ μ§„μ§œ λ¬Έμ œλŠ” λ©€ν‹° μ“°λ ˆλ“œ ν™˜κ²½μ—μ„œ, μ—¬λŸ¬ 개의 μ“°λ ˆλ“œμ—μ„œ λžŒλ‹€μ‹μ„ μ‚¬μš©ν•˜λ©΄μ„œ λžŒλ‹€ 캑쳐링이 계속 λ°œμƒν•˜λŠ”λ° 이 λ•Œ μ™ΈλΆ€ λ³€μˆ˜ κ°’μ˜ λΆˆλ³€μ„±μ„ 보μž₯ν•˜μ§€ λͺ»ν•œλ‹€λ©΄ 동기(sync)ν™” λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆλ‹€.

μ΄λŸ¬ν•œ 문제 λ•Œλ¬Έμ— μ§€μ—­λ³€μˆ˜μ— λŒ€ν•œ μ œμ•½μ‚¬ν•­μ΄ μ‘΄μž¬ν•˜κ²Œ λ˜λŠ” 것이닀.

static λ³€μˆ˜λ‚˜ μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λŠ” μŠ€νƒ μ˜μ—­μ΄ μ•„λ‹Œ νž™ μ˜μ—­μ— μœ„μΉ˜ν•˜κ³ , νž™ μ˜μ—­μ€ λͺ¨λ“  μ“°λ ˆλ“œκ°€ κ³΅μœ ν•˜κ³  μžˆλŠ” λ©”λͺ¨λ¦¬ μ˜μ—­μ΄κΈ° λ•Œλ¬Έμ— 값을 직접 μ ‘κ·Όν•˜κΈ° λ•Œλ¬Έμ— λ¬Έμ œκ°€ μ—†λŠ” 것이닀.


λ©”μ†Œλ“œ, μƒμ„±μž 레퍼런슀

Method Reference

λžŒλ‹€μ‹μ΄ ν•˜λ‚˜μ˜ λ©”μ†Œλ“œλ§Œ ν˜ΈμΆœν•˜λŠ” κ²½μš°μ—λŠ” 'λ©”μ†Œλ“œ μ°Έμ‘°(Method References)'λ₯Ό 톡해 λžŒλ‹€μ‹μ„ 더 κ°„λž΅ν•˜κ²Œ ν‘œν˜„ν•  수 μžˆλ‹€.

λ©”μ†Œλ“œλ₯Ό μ°Έμ‘°ν•΄μ„œ 맀개 λ³€μˆ˜μ˜ 정보 및 리턴 νƒ€μž…μ„ μ•Œμ•„λ‚Έλ‹€. λžŒλ‹€μ‹μ—μ„œ λΆˆν•„μš”ν•œ 맀개 λ³€μˆ˜λ₯Ό μ œκ±°ν•˜λŠ” 것이 λͺ©μ μ΄λ‹€.

ClassName::MethodName

or

ReferenceVariable::MethodName

Integer parseInt(String s) { 				// λ©”μ†Œλ“œ
    return Integer.parseInt(s);
}
Function<String, Integer> f = s -> Integer.parseInt(s); // λžŒλ‹€μ‹
Function<String, Integer> f = Integer::parseInt; 	// λ©”μ†Œλ“œ μ°Έμ‘°
Function<String, String, Boolean> f = (s1, s2) -> s1.equlas(s2); 	// λžŒλ‹€μ‹
Function<String, String, Boolean> f = String::equals; 			// λ©”μ†Œλ“œ μ°Έμ‘°

Constructor References

μƒμ„±μž μ°Έμ‘°(Constructor References)λŠ” Constructorλ₯Ό μƒμ„±ν•΄μ£ΌλŠ” μ½”λ“œλ‘œμ¨ 객체 생성을 μ˜λ―Έν•œλ‹€.

ClassName::new

Function<Integer, int[]> f = x -> new int[x];   // λžŒλ‹€μ‹
Function<Integer, int[]> f = int[]::new;  	// μƒμ„±μž μ°Έμ‘°
Supplier<CustomClass> s = () -> new CustomClass(); 	// λžŒλ‹€μ‹
Supplier<CustomClass> s = CustomClass:new; 		// μƒμ„±μž μ°Έμ‘°
profile
SSAFY 6th -> SEC VD SW πŸ‘¨β€πŸ’»πŸ”₯

0개의 λŒ“κΈ€