μ λ
Έν
μ΄μ
(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μ΄λ©°, ν΄λΉνλ κ°μ μλ΅νκ³ λ°λ‘ μ¬μ©μ΄ κ°λ₯νλ€.
μ»΄νμΌ νμ
μ μ 곡νλ μ 보 @Override
: μμ ν΄λμ€μ λ©μλλ₯Ό μ¬μ μνμμμ λνλ΄λ Annotation. μμ ν΄λμ€μ ν΄λΉ λ©μλκ° μ‘΄μ¬νμ§ μλ κ²½μ° Compilerκ° κ²½κ³ νλ κΈ°λ₯μ μ 곡ν¨.@SuppressWarnings
: μ»΄νμΌλ¬κ° κ²½κ³ νλ λ΄μ©μ Ignore ν λ μ¬μ©νλ Annotation@Generated
: μμ€ μ½λλ₯Ό μμ±νλ λꡬμ μν΄μ ν΄λΉ μ½λκ° μλμ μΌλ‘ μμ±λμμμ λνλ΄λ Annotation@Getter
, @Setter
)μλ° λ¦¬νλ μ
(Java Reflection)
: ꡬ체μ μΈ ν΄λμ€ νμ
μ μμ§ λͺ»ν΄λ λ°νμ μμ ν΄λμ€ μ΄λ¦λ§ μκ³ μλ€λ©΄ κ·Έ ν΄λμ€μ λ©μλ, νμ
, λ³μλ€μ μ κ·Όν μ μλλ‘ ν΄μ£Όλ μλ° API, @FunctionalInterface
: ν΄λΉ Interfaceκ° νλμ λ©μλλ§μ μ 곡νλ ν¨μν μΈν°νμ΄μ€μμ λνλ΄λ Annotation@Deprecated
: λ μ΄μ μ§μνμ§ μλ κΈ°λ₯μμ μλ €μ£Όλ Annotation@SafeVarargs
: Genericκ³Ό κ°μ κ°λ³ μΈμ Parameterλ₯Ό μ¬μ©ν λ λ°μνλ κ²½κ³ λ₯Ό ignore νλ Annotation@Repeatable
: ν΄λΉ Annotationμ λ°λ³΅μ μΌλ‘ μ¬μ©ν μ μκ² μ§μνλ Annotation@Inherited
: Meta Annotation μ€ νλλ‘ μ¨ μ μ©λ λμ Annotationμ νμ Class, Interfaceμκ² μμμν€λ Annotation@Retention
μλ
Έν
μ΄μ
μ μ λ
Έν
μ΄μ
μ μΈμ μ¬μ©λλ λ©ν μ λ
Έν
μ΄μ
μΌλ‘, λ§ν¬λ μλ
Έν
μ΄μ
μ μΈμ κΉμ§ μ μ§ν κ±΄μ§ κ²°μ ν΄μ£Όλ μ λ
Έν
μ΄μ
μ΄λ€.
μ¦, Java μ»΄νμΌλ¬κ° μ λ Έν μ΄μ μ λ€λ£¨λ λ°©λ²μ κΈ°μ νλ©°, μ΄λ μμ κΉμ§ μν₯μ λ―ΈμΉλμ§ κ²°μ νλ€.
보쑴ν κΈ°κ°μ νΉμ νκ² λͺ μνμ§ μμΌλ©΄ κΈ°λ³Έκ°μ ν΄λμ€ νμΌκΉμ§ 보쑴νλ€.
ν΄λΉ μ μ±
λ€μ java.lang.annotation.RetentionPolicy
μ enum
μΌλ‘ μ μλμ΄ μμΌλ©° μλμ κ°λ€.
SOURCE
: μ»΄νμΌλ¬κ° μ»΄νμΌν λ ν΄λΉ μ λ
Έν
μ΄μ
μ μΈCLASS
: μ»΄νμΌλ¬κ° μ»΄νμΌμμλ ν΄λΉ μ λ
Έν
μ΄μ
μ κ°μ Έκ°μ§λ§ λ°νμ μμλ μ¬λΌμ§RUNTIME
: λ°νμμλ ν΄λΉ μ λ
Έν
μ΄μ
μ μ§@Retention(RetentionPolicy.RUNTIME) //λ°νμμλ ν΄λΉ μ λ
Έν
μ΄μ
μ μ§
public @interface CustomAnnotation {
// Element
int value();
}
@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
μ λ
Έν
μ΄μ
μ μ λ
Έν
μ΄μ
μ μΈμ μ¬μ©λλ λ©ν μ λ
Έν
μ΄μ
μΌλ‘, ν΄λΉ μ λ
Έν
μ΄μ
μ λν μ 보λ₯Ό Javadocλ¬Έμμ ν¬ν¨νλ€λ κ²μ μ μΈνλ€.
@Documented // μ΄ μ λ
Έν
μ΄μ
μ λν μ 보λ₯Ό Javadocλ¬Έμμ
@Target(ElementType.FIELD) // Enum, μμ, Field λ³μμ λν΄ μ μΈ κ°λ₯
@Retention(RetentionPolicy.RUNTIME) // λ°νμμλ ν΄λΉ μ λ
Έν
μ΄μ
μ μ§
public @interface CustomAnnotation {
// Element
int value();
}
Annotation Processor
λ μ λ
Έν
μ΄μ
μ μ΄μ©νμ¬ νλ‘μΈμ€λ₯Ό μ²λ¦¬νλ κ²μ μλ―Ένλ©°, μ»΄νμΌλ¬κ° μ»΄νμΌ μ€μ μλ‘μ΄ μμ€μ½λλ₯Ό μμ±νκ±°λ κΈ°μ‘΄μ μ½λ λ³κ²½μ κ°λ₯νκ² νλ€.
νΉν μ»΄νμΌ λ¨κ³μμ μ λ Έν μ΄μ μ μ μλ μ‘μ μ μ²λ¦¬νλλ°, μ΄κ²μ μ ν리μΌμ΄μ μ΄ μ€νλκΈ° μ μ»΄νμΌ νμμ 미리 체ν¬λ₯Ό ν΄μ£ΌκΈ° λλ¬Έμ μ λ Έν μ΄μ μ΄ μλνλλ‘ μ΄λ£¨μ΄μ§μ§ μμΌλ©΄ λμΌλ‘ νμΈν μ μλ μλ¬λ κ²½κ³ λ₯Ό 보μ¬μ€λ€.
μ λ
Έν
μ΄μ
νλ‘μΈμμ κ°μ₯ λνμ μΈ μλ‘λ Lombok
λΌμ΄λΈλ¬λ¦¬κ° μλ€.
Getter, Setterμ κ°μ΄ λ°λ³΅μ μ΄κ³ μ€λ³΅λλ λ§μ μ½λλ₯Ό μμ°νλ μ½λ(boilerplate code)λ₯Ό μ΅μννκ³ ν΅μ¬μ μΈ κΈ°λ₯μ λͺ ννκ² νμΈν μ μλλ‘ νλ€.
μ λ
Έν
μ΄μ
νλ‘μΈμλ₯Ό μμ±νκ³ λ±λ‘νκΈ° μν΄μλ AbstractProcessror
ν΄λμ€λ₯Ό μμλ°μμΌ νλλ°, Lombok
λν AbstractProcessor
λ₯Ό μμλ°μ μ λ
Έν
μ΄μ
νλ‘μΈμλ₯Ό μ μν κ²μ΄λ€.
Lombok
AutoService
: @Override
Dagger2
μλλ‘μ΄λ λΌμ΄λΈλ¬λ¦¬
I/O
λ Input(μ
λ ₯) and Output(μΆλ ₯)μ μ½μμ΄λ€.
I/Oμ κ°λ¨ν μμλ, ν€λ³΄λλ‘ ν μ€νΈλ₯Ό μ λ ₯νκ³ λͺ¨λν°λ‘ μ λ ₯ν ν μ€νΈλ₯Ό μΆλ ₯νλ κ²μ΄λ€.
κΈ°μ‘΄μ IO(I/O)
λ°©μμ μ€νΈλ¦Ό λ°©μμ μ
μΆλ ₯μΈλ°, μ΄ λ°©μμΌλ‘λ λ€νΈμν¬μμμ μ΄λ£¨μ΄μ§λ μ
μΆλ ₯μ μλκ° νλμ¨μ΄μμ μ΄λ£¨μ΄μ§λ μ
μΆλ ₯ μλμ λΉν΄ νμ ν λ리기 λλ¬Έμ λ¬Έμ μ μ΄ μκ²Όλ€.
λν μ€νΈλ¦Ό λ°©μμ λ³λͺ©νμμ λ§€μ° μ·¨μ½νλ€λ λ¨μ μ΄ μκ³ λ€νΈμν¬μ λ°μ λ³΄λ€ νλμ¨μ΄μ λ°μ μλκ° μμλκ°λ©΄μ μλ‘μ΄ I/O λ°©μμ΄ νμν΄μ‘λ€.
κ·Έλμ μ΄λ¬ν λ€νΈμν¬ νκ²½μμμ λ¬Έμ μ μ ν΄κ²°νκΈ° μν΄μ NIO(NEW I/O)
λ°©μμ΄ λνλ¬λ€.
κ΅¬λΆ | IO | NIO |
---|---|---|
μ μΆλ ₯ | μ€νΈλ¦Ό | μ±λ |
λ²νΌ | non-λ²νΌ | λ²νΌ |
λΉλκΈ° | μ§μ μν¨ | μ§μ |
λΈλ‘νΉ | λΈλ‘νΉλ§ μ§μ | λΈλ‘νΉ / non-λΈλ‘νΉ λͺ¨λ μ§μ |
Streamμ΄λ, ν λ°©ν₯μΌλ‘ μ°μμ μΌλ‘ νλ¬κ°λ κ²μ μλ―Ένλ€.
μ΄ Streamμ΄ νλ‘κ·Έλλ°μμλ λ°μ΄ν°κ° ν λ°©ν₯μΌλ‘ νλ¬κ° μ μλλ‘ λμμ£Όλ κ΄, ν΅λ‘λΌλ μλ―Έλ‘ μ¬μ©λλ€.
μ
μΆλ ₯ λ
Έλμ μ§μ μ°κ²°λλ Streamμ λ
Έλμ€νΈλ¦Ό
μ΄λΌκ³ νκ³ , μ΄λ νμ λ€.
κ·Έλ¦¬κ³ λ€λ₯Έ μ€νΈλ¦Όμ 보쑰νλ κΈ°λ₯μ μΈ Streamμ νν°μ€νΈλ¦Ό
μ΄λΌκ³ νλ©°, μ΄λ μ΅μ
μ΄λ€.
λ°μ½λ μ΄ν° ν¨ν΄
μΌλ‘ λ
Έλμ€νΈλ¦Ό
μ νν°μ€νΈλ¦Ό
μ΄ μΆκ°λλ λ°©μμ΄λ€.
Streamμ΄ λ°μ΄ν°λ₯Ό μ΄λ€ λ°©μμΌλ‘ μ λ¬νλλμ λ°λΌ 2κ°μ§λ‘ ꡬλΆν μ μλ€.
Byte Stream
(λ°μ΄νΈ μ€νΈλ¦Ό)InputStream
κ³Ό OutputStream
ν΄λμ€λ₯Ό μμλ°μ μ¬μ©FileInputStream
/ FileOutputStream
: νμΌ μ
μΆλ ₯ μ€νΈλ¦ΌByteArrayInputStream
/ ByteArrayOutputStream
: λ©λͺ¨λ¦¬ μ
μΆλ ₯ μ€νΈλ¦ΌPipedInputStream
/ PipedOutputStream
: νλ‘μΈμ€ μ
μΆλ ₯ μ€νΈλ¦ΌAudioInputStream
/ AudioOutputStream
: μ€λμ€ μ₯μΉ μ
μΆλ ₯ μ€νΈλ¦Όμλ°μμ κ°μ₯ μμ νμ
μΈ char νμ΄ 2λ°μ΄νΈμ΄λ―λ‘, 1λ°μ΄νΈμ© μ μ‘λλ λ°μ΄νΈ κΈ°λ° μ€νΈλ¦ΌμΌλ‘λ μνν μ²λ¦¬κ° νλ κ²½μ°κ° μλ€. μ΄λ¬ν κ²½μ°λ₯Ό ν΄κ²°νκΈ° μν΄ μλ°λ Character Stream
μ μ§μν¨
Character Stream
(λ¬Έμ μ€νΈλ¦Ό)Reader
μ Writer
ν΄λμ€λ₯Ό μμλ°μ μ¬μ©FileReader
/ FileWriter
: νμΌ μ
μΆλ ₯ μ€νΈλ¦ΌCharArrayReader
/ CharArrayWriter
: λ©λͺ¨λ¦¬ μ
μΆλ ₯ μ€νΈλ¦ΌPipedReader
/ PipedWriter
: νλ‘μΈμ€ μ
μΆλ ₯ μ€νΈλ¦ΌStringReader
/ StringWriter
: λ¬Έμμ΄ μ
μΆλ ₯ μ€νΈλ¦Όλ Streamμ λͺ¨λ μ²μμλ byteλ‘ λ°μλ€μ΄κ³ , κ·Έ λ€μμ κ° Streamμ΄ μμμ μ²λ¦¬λ₯Ό ν΄μ€λ€.
System
Classλ μλ°μμ 미리 μ μν΄λ νμ€ μ
μΆλ ₯ ν΄λμ€μ΄λ©°, java.lang
ν¨ν€μ§μ ν¬ν¨λμ΄ μλ€.
System.in
: νμ€ μ
λ ₯ μ€νΈλ¦ΌSystem.out
: νμ€ μΆλ ₯ μ€νΈλ¦ΌSystem.err
: νμ€ μλ¬ μΆλ ₯ μ€νΈλ¦Όμλ²μ ν΄λΌμ΄μΈνΈκ°μ ν΅μ μλ¨
μ μλ―Ένλ€.
μΌλ°μ μΌλ‘ NIO(new I/O)μ λͺ¨λ I/Oλ μ±λλ‘ μμνλ€.
μ±λμ μ€νΈλ¦Όκ³Ό μ μ¬νμ§λ§ λͺ κ°μ§ μ°¨μ΄μ μ΄ μ‘΄μ¬νλ€.
μ€νΈλ¦Ό
μ λ¨λ°©ν₯ μ
μΆλ ₯(μ½κΈ° λλ μ°κΈ°) λ§ κ°λ₯νμ§λ§ μ±λ
μ ν΅ν΄μλ μλ°©ν₯ μ
μΆλ ₯(μ½κ³ μ°κΈ°) μ΄ κ°λ₯νλ€ μλ€.λ²νΌ
λ₯Ό μ΄μ©νμ¬ μ
μΆλ ₯μ νλ€.λ°μ΄ν°λ₯Ό μμ μ μ₯νλ 곡κ°μ μλ―Ένλ€.
IO
μμλ μΆλ ₯ μ€νΈλ¦Όμ΄ 1λ°μ΄νΈλ₯Ό μ°λ©΄ μ
λ ₯ μ€νΈλ¦Όμ΄ 1λ°μ΄νΈλ₯Ό μ½λλ€.
NIO
μμ λ²νΌλ μ±λκ³Ό μνΈμμ©ν λ μ¬μ©λλ€. 컀λμ μν΄ κ΄λ¦¬λλ μμ€ν
λ©λͺ¨λ¦¬λ₯Ό μ§μ μ¬μ©ν μ μλ μ±λμ μ ν΄ μ§μ read λκ±°λ write λ μ μλ λ°°μ΄κ³Ό κ°μ κ°μ²΄μ΄λ€.
μ μΆλ ₯μ λ΄λΉνλ μ₯μΉ, νλ‘μΈμ€μμ κ³ μ μ₯μΉ(νλ‘μΈμ€)κ° μ μ μ₯μΉ(νλ‘μΈμ€)κ° μμ μ νλ λμ κΈ°λ€λ¦¬λ μκ°μ μ€μ¬ κ°λ³ μμ λ€ κ°μ νλμ μννκ² μ§μνκΈ° μν΄ μ‘΄μ¬νλ€.
λ°λΌμ, 1λ°μ΄νΈμ© μ λ¬μ΄ μλλΌ κΈ°λ€λ¦¬λ λμ λ²νΌμ λ°μ΄ν°λ₯Ό μΆμ²νμ¬ νλ²μ μ λ¬νμ¬ λΉ λ₯Έ μλλ₯Ό 보μΈλ€.
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 λν 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
λ λ°μ½λ μ΄ν° ν¨ν΄μ΄ μ μ©λ¨μ μ μ μλ€.
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) { }
μ λ€λ¦ νμ μ λ°°μ΄μ μμ±ν κ²½μ° : new T[N]μ μ»΄νμΌ νμμ λ°°μ΄μ νμ μ μ μ μκΈ° λλ¬Έμ μ¬μ©ν μ μλ€.
static λ³μμ μ¬μ©ν κ²½μ° : static λ³μλ μΈμ€ν΄μ€μ μ’ μλμ§ μμΌλ―λ‘ μΈμ€ν΄μ€λ³ νμ μ΄ λ³κ²½λ μ μκΈ° λλ¬Έμ μ¬μ©ν μ μλ€. (λ¨, static λ©μλμλ μ λ€λ¦ μ¬μ© κ°λ₯)
Genericμ μ£Όμ κ°λ
μΌλ‘λ Bounded-Type
κ³Ό Wild-Card
κ° μλ€.
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κ°λ‘ μ ν κ°λ₯
...
}
μ λ€λ¦ νμ μ λ©μλμ 맀κ°κ°μΌλ‘ μ λ¬ν λ ꡬ체μ μΈ νμ μΌλ‘λ§ νμ μ νμ΄ μκΈ΄λ€ κ·Έλ¬ν λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ μμΌλ μΉ΄λλ₯Ό μ¬μ©νλ€.
?
ν€μλλ₯Ό μ¬μ©νμ¬ μμΌλ μΉ΄λλ₯Ό μ¬μ©ν μ μλ€.
μ λ€λ¦ νμ
<?>
: μ ν μμ. λͺ¨λ ν΄λμ€λ μΈν°νμ΄μ€ κ°λ₯μ λ€λ¦ νμ
<? extends μμ νμ
>
: νμ
μ μνμ μ§μ (ν΄λΉ νμ
λ° νμνμ
λ§, μ΅μμ΄ μ μν νμ
), μ΅λ μ μλ μμ νμ
λ³΄λ€ λ μμ νμ
μ μ¬μ©ν μ μμμ λ€λ¦ νμ
<? super νμ νμ
>
: νμ
μ ννμ μ§μ (ν΄λΉ νμ
λ° μμνμ
λ§, μ΅νκ° μ μν νμ
), μ΅μ μ μλ νμ νμ
λ³΄λ€ λ νμ νμ
μ μ¬μ©ν μ μμμ λ€λ¦μ νμ
μκ±°(Generics Type Erasure)
: μ»΄νμΌλ¬λ μ λ€λ¦ νμ
μ μ΄μ©ν΄ μμ€νμΌμ κ²μ¬νκ³ λ°νμμλ ν΄λΉ νμ
μ μ 보λ₯Ό μ μ μλ€λ κ°λ
μ΄λ€. μ¦, μ»΄νμΌλ νμΌ*.class
μλ μ λ€λ¦ νμ
μ λν μ λ³΄κ° μλ€λ λ».UnBounded-Type
μ Object(<?>, <T>)
=> ObjectBounded-Type
μ extends λ€μ μμ±ν κ°μ²΄<T extends Number>
=> Numberλλ€μ(Lambda expression)μ λ©μλλ₯Ό κ°λ¨νλ©΄μ λͺ
νν μ(expression)
μΌλ‘ ννν κ²μ΄λ€.
λλ€μμ μΈν΄ μ΄λ¦κ³Ό 리ν΄νμ
μ΄ νμμμ΄, μ΅λͺ
ν¨μ(anonymous function)
λΌκ³ λ νλ€.
λλ€μμ λ©μλμ λλ±ν κ²μ²λΌ 보μ΄μ§λ§, μ¬μ€ λλ€μμ μ΅λͺ ν΄λμ€μ κ°μ²΄μ λλ±νμ¬ λ°νμ μμ μΈν°νμ΄μ€μ μ΅λͺ ꡬν κ°μ²΄λ‘ μμ±λκ³ λμ λλ μΈν°νμ΄μ€μ λ°λΌ ꡬν μΈν°νμ΄μ€κ° κ²°μ λλ€.
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
λ λλ€μμμ νλΌλ―Έν°λ‘ λκ²¨μ§ λ³μκ° μλ μΈλΆμμ μ μλ λ³μλ₯Ό μ°Έμ‘°νλ κ²μ μλ―Ένλ€.
λλ€μμμ μ κ·Ό κ°λ₯ν λ³μλ€μ μλμ κ°λ€.
λ‘컬 λ³μ
static λ³μ
μΈμ€ν΄μ€ λ³μ
Variable Capture
μλ μ λ³μλ€ μ€ 1. λ‘컬 λ³μ
μ λν μ μ½ μ‘°κ±΄μ΄ μ‘΄μ¬νλ€.
final
μΌλ‘ μ μΈλμ΄μΌ νλ€,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; // μμ±μ μ°Έμ‘°