nyximos.log

[Java] μ œλ„€λ¦­ λ³Έλ¬Έ

Programming/JAVA

[Java] μ œλ„€λ¦­

nyximos 2022. 9. 26. 12:05

πŸ‘©‍πŸš€ λͺ©ν‘œ

μžλ°”μ˜ μ œλ„€λ¦­μ— λŒ€ν•΄ ν•™μŠ΅ν•˜μ„Έμš”.

πŸ‘©‍πŸ’» ν•™μŠ΅ν•  것

  • μ œλ„€λ¦­ μ‚¬μš©λ²•
  • μ œλ„€λ¦­ μ£Όμš” κ°œλ… (λ°”μš΄λ””λ“œ νƒ€μž…, μ™€μΌλ“œ μΉ΄λ“œ)
  • μ œλ„€λ¦­ λ©”μ†Œλ“œ λ§Œλ“€κΈ°
  • Erasure

 

 

 

μ œλ„€λ¦­ Generics

λ‹€μ–‘ν•œ νƒ€μž…μ˜ 객체듀을 μ²˜λ¦¬ν•  수 μžˆλŠ” ν΄λž˜μŠ€μ™€ λ©”μ„œλ“œλ₯Ό μž‘μ„±ν•˜λŠ” 기법

μ»¬λ ‰μ…˜ ν΄λž˜μŠ€μ— 컴파일 μ‹œ νƒ€μž… 체크λ₯Ό ν•΄μ£ΌλŠ” κΈ°λŠ₯

μžλ°” 1.5λΆ€ν„° μΆ”κ°€

 

μž₯점

객체 νƒ€μž… μ•ˆμ •μ„±μ„ λ†’μ—¬μ€€λ‹€. (μ˜λ„ν•˜μ§€ μ•Šμ€ 객체λ₯Ό μ €μž₯ν•˜λŠ” 것을 막고, λ‹€λ₯Έ νƒ€μž…μœΌλ‘œ ν˜•λ³€ν™˜λ˜λŠ” κ°€λŠ₯성을 μ€„μ—¬μ€Œ)

νƒ€μž… 체크와 ν˜•λ³€ν™˜μ„ μƒλž΅ν•˜μ—¬ μ½”λ“œκ°€ 간결해진닀.

 

class Box<T>

Box<T> : μ œλ„€λ¦­ 클래슀 T의 Box, T Box라고 μ½λŠ”λ‹€.

T : νƒ€μž… λ³€μˆ˜

Box :  μ›μ‹œ νƒ€μž… raw type

 

 

μ œλ„€λ¦­ νƒ€μž… 호좜

Box<String> b = new Box<String>();

 

일반적으둜 μ‚¬μš©ν•˜λŠ” μ œλ„€λ¦­ νƒ€μž… 이름

  • E - Element (used extensively by the Java Collections Framework)
  • K - Key
  • N - Number
  • T - Type
  • V - Value
  • S,U,V etc. - 2nd, 3rd, 4th types

 

νƒ€μž…λ³€μˆ˜

μ œλ„€λ¦­ 클래슀 μž‘μ„±μ‹œ Object νƒ€μž… λŒ€μ‹  νƒ€μž… λ³€μˆ˜λ₯Ό μ„ μ–Έν•œλ‹€.

클래슀 μ˜†μ˜ <T> 의 Tκ°€ νƒ€μž… λ³€μˆ˜μ΄λ‹€.

 

 

μ œλ„€λ¦­ μ‚¬μš©λ²•

μ œλ„€λ¦­ μ‚¬μš© 이전 방법

Object νƒ€μž… λ³€μˆ˜λŠ” μ–΄λ–€ 객체도 μ°Έμ‘° ν•  수 μžˆλ‹€.

→ 내뢀에 Object νƒ€μž…μ˜ λ³€μˆ˜λ₯Ό μ„ μ–Έν•˜κ³  이 λ³€μˆ˜λ‘œ 데이터λ₯Ό 가리킨닀.

public class Box {
    private Object data;
	public void set(Object data){
    	this.data = data;
    }
    public Object get() {
    	return data;
    }
}

μ‚¬μš©

데이터λ₯Ό κΊΌλ‚Ό λŒ€λ§ˆλ‹€ 항상 ν˜•λ³€ν™˜μ΄ ν•„μš”ν•˜λ‹€.

λΆ€μ£Όμ˜ν•˜κ²Œ λ‹€λ₯Έ 객체둜 ν˜•λ³€ν™˜μ„ ν•  μˆ˜λ„ μžˆμ–΄ μ‹€ν–‰ 도쀑에 였λ₯˜λ₯Ό λ°œμƒμ‹œν‚¬ 수 μžˆλ‹€.

 

Box box = new box();

box.set("Hello World");
String s = (String)b.get();

box.set(new Integer(10));
Integer i = (Integer)box.get();

 

 

μ œλ„€λ¦­ μ‚¬μš©

μžλ£Œν˜•μ„ ν‘œμ‹œν•˜λŠ” μžλ¦¬μ— Tκ°€ μ‚¬μš©λœλ‹€.

public class Box<T> {
    private T data;
    public void set(T data) {
    	this.data = data;
    }
    public T get(){
    	return data;
    }
}

 

μ‚¬μš©

νƒ€μž… λ§€κ°œλ³€μˆ˜μ˜ 값은 객체λ₯Ό 생성할 λ•Œ ꡬ체적으둜 κ²°μ •λœλ‹€.

Box<String> stringBox = new Box<String>();
stringBox.set("Hello World");
String s = stringBox.get();

 

μ •μˆ˜ νƒ€μž…μ„ μΆ”κ°€ν•˜λ €κ³ ν•˜λ©΄

μ»΄νŒŒμΌλŸ¬κ°€ 컴파일러 λ‹¨κ³„μ—μ„œ 였λ₯˜λ₯Ό κ°μ§€ν•œλ‹€.

→ 더 μ•ˆμ „ν•˜κ²Œ ν”„λ‘œκ·Έλž˜λ° ν•  수 μžˆλ‹€.

Box<String> stringBox = new Box<String>();
stringBox.set(new Integer(10)); // 컴파일 였λ₯˜!

 

μ£Όμ˜μ‚¬ν•­

1. static ν•„λ“œλ‘œ νƒ€μž… λ³€μˆ˜λ₯Ό μ‚¬μš©ν•  수 μ—†λ‹€.

TλŠ” μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λ‘œ κ°„μ£Όλ˜κΈ° λ•Œλ¬Έμ΄λ‹€.

static λ©€λ²„λŠ” μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λ₯Ό μ°Έμ‘°ν•  수 μ—†λ‹€.

public class Fruit<T> {
	static T fruit; // 컴파일 μ—λŸ¬
}

2. μ œλ„€λ¦­ νƒ€μž…μ˜ 배열을 생성할 수 μ—†λ‹€. νƒ€μž…λ³€μˆ˜λ‘œ λ°°μ—΄ 선언은 κ°€λŠ₯ν•˜λ‹€.

new μ—°μ‚°μž λ•Œλ¬ΈμΈλ°

new μ—°μ‚°μžλŠ” 컴파일 μ‹œμ μ— νƒ€μž… Tκ°€ 무엇인지 μ •ν™•νžˆ μ•Œμ•„μ•Ό ν•œλ‹€.

κ·ΈλŸ¬λ‚˜ μ•„λž˜ μ½”λ“œμ˜ Box<T> 클래슀λ₯Ό 컴파일 μ‹œμ μ— Tκ°€ μ–΄λ–€ νƒ€μž…μ΄ 될 지 μ•Œ 수 μ—†μœΌλ―€λ‘œ 배열을 생성할 수 μ—†λŠ” 것이닀.

class Box<T> {
    T[] itemArr;  // Tνƒ€μž… 배열을 μœ„ν•œ μ°Έμ‘°λ³€μˆ˜
    
    T[] toArr() {
    	T[] tmmpArr = new T[itemArr.length]; // μ—λŸ¬, μ œλ„€λ¦­ λ°°μ—΄ μƒμ„±λΆˆκ°€
       	...
        return tmpArr;
    }
}

4. νƒ€μž… 맀개 λ³€μˆ˜λ‘œ μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 수 μ—†λ‹€.

3. instanceof μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•  수 μ—†λ‹€. μ™€μΌλ“œμΉ΄λ“œ? λ₯Ό μ‚¬μš©ν•˜λ©΄ κ°€λŠ₯ν•˜λ‹€.

 

μ œλ„€λ¦­ μ£Όμš” κ°œλ… (λ°”μš΄λ””λ“œ νƒ€μž…, μ™€μΌλ“œ μΉ΄λ“œ)

ν•œμ •λœ νƒ€μž… 맀개 λ³€μˆ˜ bounded type parameter

νƒ€μž… 맀개 λ³€μˆ˜λ‘œ μ „λ‹¬λ˜λŠ” νƒ€μž… μ’…λ₯˜ μ œν•œ ν•˜κ³  싢을 λ•Œ μ‚¬μš©

ν‚€μ›Œλ“œ extendsλ₯Ό μ‚¬μš©ν•œλ‹€.

νŠΉμ • νƒ€μž…μ˜ μžμ†λ“€λ§Œ λŒ€μž…ν•  수 있게 μ œν•œν•  수 μžˆλ‹€.

 

과일 μƒμžμ— μž₯λ‚œκ°μ„ 담을 수 μžˆλ‹€.

FruitBox<Toy> FruitBox = new FruitBox<Toy>();
fruitBox.add(new Toy());

 

Fruit의 μžμ†λ§Œ νƒ€μž…μœΌλ‘œ 지정 κ°€λŠ₯

class FruitBox<T extends Fruit> {
    ArrayList<T> list = new ArrayList<T>();
}

 

μ—¬μ „νžˆ ν•œ μ’…λ₯˜μ˜ νƒ€μž…λ§Œ 담을 수 μžˆμ§€λ§Œ Fruit클래슀의 μžμ†λ“€λ§Œ 담을 수 μžˆλ‹€λŠ” μ œν•œμ΄ μΆ”κ°€ λ˜μ—ˆλ‹€....

FruitBox<Apple> appleBox = new FruitBox<Apple>();
FruitBox<Toy> toyBox = new FruitBox<Toy>(); // ToyλŠ” Fruit의 μžμ†μ΄ μ•„λ‹ˆλΌμ„œ μ—λŸ¬

 

ν΄λž˜μŠ€κ°€ μ•„λ‹Œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•΄μ•Όν•œλ‹€λŠ” μ œμ•½μ΄ ν•„μš”ν•  λ•Œλ„ extends ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•œλ‹€.

implementsλ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šλ„λ‘ μ£Όμ˜ν•œλ‹€.

interface Eatable {}

// μ˜¬λ°”λ₯Έ μ‚¬μš©
class FruitBox<T extends Eatable> {...}

// 잘λͺ»λœ μ‚¬μš©
class FruitBox<T implements Eatable> {...}

 

클래슀 Fruit의 μžμ†μ΄λ©΄μ„œ Eatable μΈν„°νŽ˜μ΄μŠ€λ„ κ΅¬ν˜„ν•΄μ•Ό ν•  λ•ŒλŠ” & 기호둜 μ—°κ²°ν•œλ‹€.

class FruitBox<T extends Fruit & Eatable> {...}

 

 

 

 

μ œλ„€λ¦­ 클래슀 μƒμ„±μ‹œ μ°Έμ‘° λ³€μˆ˜μ— μ§€μ •λœ μ œλ„€λ¦­ νƒ€μž…κ³Ό μƒμ„±μžμ— μ§€μ •λœ νƒ€μž…μ΄ μΌμΉ˜ν•΄μ•Ό ν•œλ‹€.

μΌμΉ˜ν•˜μ§€ μ•ŠμœΌλ©΄ 컴파일 μ—λŸ¬κ°€ λ°œμƒν•œλ‹€. (상속관계더라도 μ—λŸ¬)

ArrayList<Fruit> fruitList = new Array<Apple>(); // μ—λŸ¬

 

μ™€μΌλ“œμΉ΄λ“œ WildCard

μ œλ„€λ¦­ νƒ€μž…μ— λ‹€ν˜•μ„±μ„ μ μš©ν•˜λŠ” 방법

기호 ? μ‚¬μš©

extends ν‚€μ›Œλ“œλ‘œ μƒν•œμ„, super ν‚€μ›Œλ“œλ‘œ ν•˜ν•œμ„ μ œν•œν•  수 μžˆλ‹€. 

 

<? extends T>  Upper Bounded Wildcard

μ™€μΌλ“œ μΉ΄λ“œμ˜ μƒν•œ μ œν•œ, T와 T의 μžμ†λ“€λ§Œ κ°€λŠ₯


<? super T>  Lower Bounded Wildcard

μ™€μΌλ“œ μΉ΄λ“œμ˜ ν•˜ν•œ μ œν•œ,  T와 T의 μ‘°μƒλ“€λ§Œ κ°€λŠ₯

 

<?> Unbounded WildCard

μ œν•œμ΄ μ—†λŠ” μ™€μΌλ“œ μΉ΄λ“œ. λͺ¨λ“  νƒ€μž…μ΄ κ°€λŠ₯, <? extends Object>와 동일

 

ν•˜λ‚˜μ˜ μ°Έμ‘°λ³€μˆ˜λ‘œ λ‹€λ₯Έ μ œλ„€λ¦­ νƒ€μž…μ΄ μ§€μ •λœ 객체λ₯Ό λ‹€λ£° 수 μžˆλ‹€.

ArrayList<? extends Fruit> fruitList = new Array<Apple>();
ArrayList<? extends Fruit> fruitList = new Array<Banana>();

 

μ™€μΌλ“œ μΉ΄λ“œλ₯Ό λ§€κ°œλ³€μˆ˜μ— 적용

 

static Juice makeJuice(FruitBox<? extends Fruite> box){
    String tmp = "";
    for(Fruit f : box.getList()){
    	tmp += f + " ";
    }
    return new Juice(tmp);
}

νƒ€μž…μ΄ λ‹€λ₯Έ μ—¬λŸ¬ 객체λ₯Ό 맀개 λ³€μˆ˜λ‘œ 지정 κ°€λŠ₯

System.out.println(Juicer.makeJuice(new FruiteBox<Fruit>()));
System.out.println(Juicer.makeJuice(new FruiteBox<Apple>()));

 

 

μ œλ„€λ¦­ λ©”μ†Œλ“œ λ§Œλ“€κΈ°

μ œλ„€λ¦­ λ©”μ†Œλ“œ

λ©”μ„œλ“œμ˜ 선언뢀에 μ œλ„€λ¦­ νƒ€μž…μ΄ μ„ μ–Έλœ λ©”μ†Œλ“œ

μ œλ„€λ¦­ νƒ€μž…μ˜ μ„ μ–Έμœ„μΉ˜λŠ” λ°˜ν™˜ νƒ€μž… λ°”λ‘œ μ•žμ΄λ‹€.

static <T> void sort(List<T> list, Comparator<? super T> c)

 

μ œλ„€λ¦­ ν΄λž˜μŠ€μ— μ •μ˜λœ νƒ€μž… λ§€κ°œλ³€μˆ˜κ°€ T이고,

μ œλ„€λ¦­ λ©”μ„œλ“œμ— μ •μ˜λœ νƒ€μž… λ§€κ°œλ³€μˆ˜κ°€ T여도 이 λ‘˜μ€ λ³„κ°œμ˜ 것이닀.

같은 νƒ€μž… 문자 Tλ₯Ό μ‚¬μš©ν•˜λ”λΌλ„ λ‹€λ₯Έ νƒ€μž… λ³€μˆ˜λΌλŠ” 것을 μœ μ˜ν•˜μž.

class FruitBox<T> {

     static <T> void sort(List<T> list, Comparator<? super T> c)

}

 

static λ©€λ²„μ—λŠ” νƒ€μž… λ§€κ°œλ³€μˆ˜λ₯Ό μ‚¬μš©ν•  수 μ—†μ§€λ§Œ,

λ©”μ„œλ“œμ— μ œλ„€λ¦­ νƒ€μž…μ„ μ„ μ–Έν•˜κ³  μ‚¬μš©ν•˜λŠ” 것은 κ°€λŠ₯ν•˜λ‹€.

 

λ©”μ„œλ“œμ— μ„ μ–Έλœ μ œλ„€λ¦­ νƒ€μž… λ§€κ°œλ³€μˆ˜λŠ”

λ©”μ„œλ“œ λ‚΄μ—μ„œλ§Œ μ§€μ—­μ μœΌλ‘œ μ‚¬μš©λ  κ²ƒμ΄λ―€λ‘œ λ©”μ„œλ“œκ°€ static이건 μ•„λ‹ˆκ±΄ 상관없닀. 

 

 

Type Erasure

컴파일 μ‹œ μ—„κ²©ν•œ νƒ€μž… 검사λ₯Ό μœ„ν•΄ λ„μž…λ˜μ—ˆλ‹€.

μ œλ„€λ¦­μ„ κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄ Java μ»΄νŒŒμΌλŸ¬λŠ” μ•„λž˜ μœ ν˜•μΌ λ•Œ μœ ν˜•μ‚­μ œλ₯Ό μ μš©ν•œλ‹€.

  • νƒ€μž… λ§€κ°œλ³€μˆ˜κ°€ μ œν•œλ˜μ§€ μ•Šμ„ λ•Œ μ œλ„€λ¦­ 맀개 λ³€μˆ˜λ₯Ό ν•΄λ‹Ή 경계 λ˜λŠ” object둜 λ°”κΎΌλ‹€.
    λ”°λΌμ„œ μƒμ„±λœ λ°”μ΄νŠΈ μ½”λ“œμ—λŠ” 일반 클래슀, μΈν„°νŽ˜μ΄μŠ€, λ©”μ„œλ“œλ§Œ ν¬ν•¨λœλ‹€.
  • μœ ν˜• μ•ˆμ „μ„±μ„ μœ μ§€ν•˜κΈ° μœ„ν•΄ ν•„μš”ν•œκ²½μš° type castsλ₯Ό μ‚½μž…ν•œλ‹€.
  • ν™•μž₯된 μ œλ„€λ¦­ ν˜•μ‹μ—μ„œ λ‹€ν˜•μ„±μ„ μœ μ§€ν•˜κΈ°μœ„ν•΄ bridge methodλ₯Ό μƒμ„±ν•œλ‹€.

Type ErasureλŠ” λ§€κ°œλ³€μˆ˜ν™” 된 μœ ν˜•μ— λŒ€ν•΄ μƒˆ ν΄λž˜μŠ€κ°€ μƒμ„±λ˜μ§€ μ•Šλ„λ‘ ν•œλ‹€.

결과적으둜 μ œλ„€λ¦­μ€ λŸ°νƒ€μž„ μ˜€λ²„ν—€λ“œλ₯Ό λ°œμƒμ‹œν‚€μ§€ μ•ŠλŠ”λ‹€.

 

https://docs.oracle.com/javase/tutorial/java/generics/erasure.html

 

Type Erasure (The Java™ Tutorials > Learning the Java Language > Generics (Updated))

The Java Tutorials have been written for JDK 8. Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available. See Java Language Changes for a summary of updated

docs.oracle.com

 

 

Erasure of Generic Types

Type Erasure ν”„λ‘œμ„ΈμŠ€ λ™μ•ˆ,

Java μ»΄νŒŒμΌλŸ¬λŠ” λͺ¨λ“  νƒ€μž… λ§€κ°œλ³€μˆ˜λ₯Ό μ§€μš°κ³ 

νƒ€μž… λ§€κ°œλ³€μˆ˜κ°€ μ œν•œλ˜μ–΄ 있으면 각 λ§€κ°œλ³€μˆ˜λ₯Ό 첫 번째 λ°”μš΄λ“œλ‘œ λŒ€μ²΄ν•˜κ³ 

μœ ν˜• λ§€κ°œλ³€μˆ˜κ°€ μ œν•œλ˜μ§€ μ•Šμ€ 경우 Object둜 λ°”κΎΌλ‹€.

public class Node<T> {

    private T data;
    private Node<T> next;

    public Node(T data, Node<T> next) {
        this.data = data;
        this.next = next;
    }

    public T getData() { return data; }
    // ...
}

이런 μ½”λ“œκ°€ μžˆμ„ λ•Œ νƒ€μž… λ§€κ°œλ³€μˆ˜ TλŠ” μ œν•œλ˜μ§€ μ•ŠμœΌλ―€λ‘œ Java μ»΄νŒŒμΌλŸ¬λŠ” Object둜 λŒ€μ²΄ν•œλ‹€.

public class Node {

    private Object data;
    private Node next;

    public Node(Object data, Node next) {
        this.data = data;
        this.next = next;
    }

    public Object getData() { return data; }
    // ...
}

 

λ‹€μŒ μ˜ˆμ œμ—μ„œ 일반 Node ν΄λž˜μŠ€λŠ” μ œν•œλœ ν˜•μ‹ 맀개 λ³€μˆ˜λ₯Ό μ‚¬μš©ν•œλ‹€.

public class Node<T extends Comparable<T>> {

    private T data;
    private Node<T> next;

    public Node(T data, Node<T> next) {
        this.data = data;
        this.next = next;
    }

    public T getData() { return data; }
    // ...
}

Java μ»΄νŒŒμΌλŸ¬λŠ” bounded type λ§€κ°œλ³€μˆ˜ Tλ₯Ό 첫 번째 bound 클래슀인 Comparable둜 λ°”κΎΌλ‹€.

public class Node {

    private Comparable data;
    private Node next;

    public Node(Comparable data, Node next) {
        this.data = data;
        this.next = next;
    }

    public Comparable getData() { return data; }
    // ...
}

 

Erasure of Generic Methods

Java μ»΄νŒŒμΌλŸ¬λŠ” 일반 λ©”μ†Œλ“œ 인수의 μœ ν˜• λ§€κ°œλ³€μˆ˜λ„ μ§€μš΄λ‹€.

// Counts the number of occurrences of elem in anArray.

public static <T> int count(T[] anArray, T elem) {
    int cnt = 0;
    for (T e : anArray)
        if (e.equals(elem))
            ++cnt;
        return cnt;
}

TλŠ” μ œν•œμ΄ μ—†κΈ° λ•Œλ¬Έμ— Java μ»΄νŒŒμΌλŸ¬λŠ” 이λ₯Ό Object둜 λŒ€μ²΄ν•œλ‹€.

public static int count(Object[] anArray, Object elem) {
    int cnt = 0;
    for (Object e : anArray)
        if (e.equals(elem))
            ++cnt;
        return cnt;
}

 

λ‹€μŒ ν΄λž˜μŠ€κ°€ μ •μ˜λ˜μ–΄ μžˆλ‹€κ³  κ°€μ •ν•΄λ³΄μž.

class Shape { /* ... */ }
class Circle extends Shape { /* ... */ }
class Rectangle extends Shape { /* ... */ }

λ‹€λ₯Έ λͺ¨μ–‘을 그리기 μœ„ν•΄ generic methodλ₯Ό μ‚¬μš©ν•˜μ—¬ draw() λ©”μ†Œλ“œλ₯Ό μž‘μ„±ν•  수 μžˆλ‹€.

public static <T extends Shape> void draw(T shape) { /* ... */ }

Java μ»΄νŒŒμΌλŸ¬λŠ” Tλ₯Ό Shape둜 λ°”κΎΌλ‹€.

public static void draw(Shape shape) { /* ... */ }

 

 

 

 

μ°Έμ‘°

14μ£Όμ°¨ κ³Όμ œ: μ œλ„€λ¦­

남ꢁ성, μžλ°”μ˜ μ •μ„ κΈ°μ΄ˆνŽΈ, λ„μš°μΆœνŒ, 2019
천인ꡭ, μ–΄μ„œμ™€ JAVAλŠ” μ²˜μŒμ΄μ§€!, INFINITYBOOKS, 2015

https://docs.oracle.com/javase/tutorial/java/generics/genTypes.html

 

Erasure of Generic Types (The Java™ Tutorials > Learning the Java Language > Generics (Updated))

The Java Tutorials have been written for JDK 8. Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available. See Java Language Changes for a summary of updated

docs.oracle.com

 

 

 

 

'Programming > JAVA' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

[Java] λžŒλ‹€μ‹  (0) 2023.03.29
[Java] I/O  (1) 2022.09.21
[Java] μ• λ…Έν…Œμ΄μ…˜  (1) 2022.09.11
[Java] Enum  (1) 2022.09.08
[Java] λ©€ν‹°μ“°λ ˆλ“œ ν”„λ‘œκ·Έλž˜λ°  (0) 2022.09.06