λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
Java

[Java-기초] λžŒλ‹€μ‹

by μ½”λ”©ν•˜λŠ” λΆ•μ–΄ 2021. 2. 22.
λ°˜μ‘ν˜•

β–Ά λžŒλ‹€μ‹

 

*ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°κ³Ό λžŒλ‹€μ‹

ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄ μ€‘μ—λŠ” ν•¨μˆ˜μ˜ κ΅¬ν˜„κ³Ό 호좜만으둜 ν”„λ‘œκ·Έλž¨μ„ λ§Œλ“€ 수 μžˆλŠ” ν”„λ‘œκ·Έλž˜λ° 방식이 μžˆλ‹€. 이λ₯Ό 'ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°'이라고 ν•œλ‹€. μžλ°”μ—μ„œ μ œκ³΅ν•˜λŠ” ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ° 방식을 'λžŒλ‹€μ‹'이라고 ν•œλ‹€.

​

​

​

*λžŒλ‹€μ‹ κ΅¬ν˜„ν•˜κΈ°

λžŒλ‹€μ‹μ€ κ°„λ‹¨νžˆ μ„€λͺ…ν•˜λ©΄ ν•¨μˆ˜ 이름이 μ—†λŠ” 읡λͺ… ν•¨μˆ˜λ₯Ό λ§Œλ“œλŠ” 것이닀.

​

 

​

*λžŒλ‹€μ‹ 문법 μ‚΄νŽ΄λ³΄κΈ°

​

-λ§€κ°œλ³€μˆ˜ μžλ£Œν˜•κ³Ό κ΄„ν˜Έ μƒλž΅ν•˜κΈ°

-μ€‘κ΄„ν˜Έ μƒλž΅ν•˜κΈ°

-return μƒλž΅ν•˜κΈ°

​

​

​

*λžŒλ‹€μ‹ μ‚¬μš©ν•˜κΈ°

​

MyNumber.java

package lambda;

public interface MyNumber {
	int getMax(int num1, int num2);  // 좔상 λ©”μ„œλ“œ μ„ μ–Έ
}

 

 

TestMyNumber.java

package lambda;

public class TestMyNumber {
	public static void main(String[] args) {
		MyNumber max = (x, y) -> (x >= y) ? x : y;   // λžŒλ‹€μ‹μ„ μΈν„°νŽ˜μ΄μŠ€ν˜• max λ³€μˆ˜μ— λŒ€μž…
		System.out.println(max.getMax(10, 20));      // μΈν„°νŽ˜μ΄μŠ€ν˜• λ³€μˆ˜λ‘œ λ©”μ„œλ“œ 호좜
	}
}

<μ‹€ν–‰ κ²°κ³Ό>

​

​

​

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

λžŒλ‹€μ‹μ€ λ©”μ„œλ“œ 이름이 μ—†κ³  λ©”μ„œλ“œλ₯Ό μ‹€ν–‰ν•˜λŠ”λ° ν•„μš”ν•œ λ§€κ°œλ³€μˆ˜μ™€ λ§€κ°œλ³€μˆ˜λ₯Ό ν™œμš©ν•œ μ‹€ν–‰ μ½”λ“œλ₯Ό κ΅¬ν˜„ν•˜λŠ” 것이닀. 그러면 λ©”μ„œλ“œλŠ” 어디에 μ„ μ–Έν•˜κ³  κ΅¬ν˜„ν•΄μ•„ ν• κΉŒμš”? ν•¨μˆ˜ν˜• μ–Έμ–΄μ—μ„œλŠ” ν•¨μˆ˜λ§Œ λ”°λ‘œ ν˜ΈμΆœν•  수 μžˆμ§€λ§Œ, μžλ°”μ—μ„œλŠ” μ°Έμ‘° λ³€μˆ˜ 없이 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•  수 μ—†λ‹€. κ·ΈλŸ¬λ―€λ‘œ λžŒλ‹€μ‹μ„ κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ§Œλ“€κ³ , μΈν„°νŽ˜μ΄μŠ€μ— λžŒλ‹€μ‹μœΌλ‘œ κ΅¬ν˜„ν•  λ©”μ„œλ“œλ₯Ό μ„ μ–Έν•˜λŠ” 것이닀. λžŒλ‹€μ‹μ€ ν•˜λ‚˜μ˜ λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•˜μ—¬ μΈν„°νŽ˜μ΄μŠ€ν˜• λ³€μˆ˜μ— λŒ€μž…ν•˜λ―€λ‘œ μΈν„°νŽ˜μ΄μŠ€κ°€ 두 개 μ΄μƒμ˜ λ©”μ„œλ“œλ₯Ό κ°€μ Έμ„œλŠ” μ•ˆλœλ‹€.

λžŒλ‹€μ‹μ€ 이름이 μ—†λŠ” 읡λͺ… ν•¨μˆ˜λ‘œ κ΅¬ν˜„ν•˜κΈ° λ•Œλ¬Έμ— μΈν„°νŽ˜μ΄μŠ€μ— λ©”μ„œλ“œκ°€ μ—¬λŸ¬ 개 μžˆλ‹€λ©΄ μ–΄λ–€ λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•œ 것인지 λͺ¨ν˜Έν•΄μ§„λ‹€. λ”°λΌμ„œ λžŒλ‹€μ‹μ€ 였직 ν•˜λ‚˜μ˜ λ©”μ„œλ“œλ§Œ μ„ μ–Έν•œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•  수 μžˆλ‹€.

​

​

-FunctionalInterface μ• λ…Έν…Œμ΄μ…˜

ν”„λ‘œκ·Έλž˜λ°μ„ ν•˜λ‹€ 보면 λžŒλ‹€μ‹μœΌλ‘œ κ΅¬ν˜„ν•œ μΈν„°νŽ˜μ΄μŠ€μ— μ‹€μˆ˜λ‘œ λ‹€λ₯Έ λ©”μ„œλ“œλ₯Ό μΆ”κ°€ν•  μˆ˜λ„ μžˆλ‹€. μ΄λŸ¬ν•œ μ‹€μˆ˜λ₯Ό 막기 μœ„ν•΄ @FunctionalInterface μ• λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•œλ‹€. @FunctionalInterfaceλ₯Ό μ‚¬μš©ν•˜λ©΄ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λΌλŠ” 의미이고, λ©”μ„œλ“œλ₯Ό ν•˜λ‚˜ 이상 μ„ μ–Έν•˜λ©΄ λ‹€μŒκ³Ό 같이 였λ₯˜κ°€ λ‚œλ‹€.

 

 

 

*객체 지ν–₯ ν”„λ‘œκ·Έλž˜λ° 방식과 λžŒλ‹€μ‹ 비ꡐ

λžŒλ‹€μ‹μ„ μ‚¬μš©ν•˜λ©΄ κΈ°μ‘΄ 방식보닀 κ°„κ²°ν•œ μ½”λ“œλ₯Ό κ΅¬ν˜„ν•  수 μžˆλ‹€. λ‹€μŒ μΈν„°νŽ˜μ΄μŠ€λ₯Ό ν΄λž˜μŠ€μ™€ λžŒλ‹€μ‹ 두 가지 λ°©μ‹μœΌλ‘œ κ΅¬ν˜„ν•΄ 보겠닀.

​

StringConcat.java

package lambda;

public interface StringConcat {
	public void makeString(String s1, String s2);
}

 

​

StringConcatImpl.java

package lambda;

public class StringConcatImpl implements StringConcat {
	@Override
	public void makeString(String s1, String s2) {
		System.out.println(s1 + "," + s2);
	}
}

 

 

TestStringConcat.java

package lambda;

public class TestStringConcat {
	public static void main(String[] args) {
		String s1 = "Hello";
		String s2 = "World";
		StringConcatImpl concat1 = new StringConcatImpl();
		concat1.makeString(s1, s2);
	}
}

-StringConcatImpl 클래슀λ₯Ό μΈμŠ€ν„΄μŠ€λ‘œ μƒμ„±ν•΄μ„œ μ°Έμ‘° λ³€μˆ˜ concat1을 μ‚¬μš©ν•΄ makeString( ) λ©”μ„œλ“œλ₯Ό 호좜.

​

<μ‹€ν–‰ κ²°κ³Ό>

​

​

​

*λžŒλ‹€μ‹μœΌλ‘œ μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„ν•˜κΈ°

λžŒλ‹€μ‹μœΌλ‘œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•  땐 클래슀λ₯Ό λ”°λ‘œ 생성할 ν•„μš” 없이 λ°”λ‘œ λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•œλ‹€.

​​

TestStringConcat.java

package lambda;

public class TestStringConcat {
	public static void main(String[] args) {
		String s1 = "Hello";
		String s2 = "World";
		StringConcatImpl concat1 = new StringConcatImpl();
		concat1.makeString(s1, s2);
		
		StringConcat concat2 = (s, v) -> System.out.println(s + "," + v); // λžŒλ‹€μ‹
		concat2.makeString(s1, s2);
	}
}

 

<μ‹€ν–‰ κ²°κ³Ό>

-λžŒλ‹€μ‹μœΌλ‘œ κ΅¬ν˜„ν•˜λ €λ©΄ λ©”μ„œλ“œλ₯Ό ν•˜λ‚˜λ§Œ ν¬ν•¨ν•˜λŠ” ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ§Œ κ°€λŠ₯ν•˜λ‹€.

​

​

​

*읡λͺ… 객체λ₯Ό μƒμ„±ν•˜λŠ” λžŒλ‹€μ‹

μžλ°”λŠ” 객체 지ν–₯ 언어이닀. 그런데 λžŒλ‹€μ‹μ€ 객체 없이 μΈν„°νŽ˜μ΄μŠ€μ˜ κ΅¬ν˜„λ§ŒμœΌλ‘œ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•  수 μžˆλ‹€. μžλ°”λŠ” 객체 생성 없이 λ©”μ„œλ“œ 호좜이 일어날 수 μ—†λŠ”λ° 이 λ©”μ„œλ“œλŠ” μ–΄λ–»κ²Œ ν˜ΈμΆœλ˜λŠ” κ²ƒμΌκΉŒμš”?

읡λͺ… λ‚΄λΆ€ ν΄λž˜μŠ€λŠ” 클래슀 이름 없이 μΈν„°νŽ˜μ΄μŠ€ μžλ£Œν˜• λ³€μˆ˜μ— λ°”λ‘œ λ©”μ„œλ“œ κ΅¬ν˜„λΆ€λ₯Ό μƒμ„±ν•˜μ—¬ λŒ€μž…ν•  수 μžˆλ‹€. 즉, λžŒλ‹€μ‹μœΌλ‘œ λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•΄μ„œ ν˜ΈμΆœν•˜λ©΄ 컴퓨터 λ‚΄λΆ€μ—μ„œλŠ” λ‹€μŒμ²˜λŸΌ 읡λͺ… ν΄λž˜μŠ€κ°€ μƒμ„±λ˜κ³  이λ₯Ό 톡해 읡λͺ… 객체가 μƒμ„±λ˜λŠ” 것이닀.

읡λͺ…인지 μ•„λ‹Œμ§€ κ΅¬λ³„ν•˜λŠ”λ²• → }; 유무둜 κ΅¬λ³„ν•œλ‹€. }; κ°€ 있으면 읡λͺ….

StringConcat concat3 = new StringConcat() {
    @Override
    public void makeString(String s1, String s2) {
        System.out.println(s1 + "," + s2);
	}
}

 

 

 

*λžŒλ‹€μ‹μ—μ„œ μ‚¬μš©ν•˜λŠ” 지역 λ³€μˆ˜

두 λ¬Έμžμ—΄μ„ μ—°κ²°ν•˜λŠ” λžŒλ‹€μ‹ μ½”λ“œμ—μ„œ μ™ΈλΆ€ λ©”μ„œλ“œμ˜ 지역 λ³€μˆ˜μΈ iλ₯Ό μˆ˜μ •ν•˜λ©΄ μ–΄λ–»κ²Œ λ κΉŒμš”?

​

TestStringConcat.java

public class TestStringConcat {
	public static void main(String[] args) {
		...
        int i = 100; // main() ν•¨μˆ˜μ˜ 지역 λ³€μˆ˜
		
		StringConcat concat2 = (s, v) -> {
            // i = 200;
            System.out.println(i);
            System.out.println(s + "," + v);
	};

iλŠ” main( ) ν•¨μˆ˜μ˜ 지역 λ³€μˆ˜μ΄λ‹€. λ§Œμ•½ λžŒλ‹€μ‹ λ‚΄λΆ€μ—μ„œ λ³€μˆ˜ i값을 λ³€κ²½ν•˜λ©΄ 였λ₯˜κ°€ λ‚œλ‹€. λ³€μˆ˜ 값을 λ³€κ²½ν•˜μ§€ μ•Šκ³  좜λ ₯만 ν•˜λ©΄ 였λ₯˜κ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€. κ·Έ μ΄μœ λŠ” λ¬΄μ—‡μΌκΉŒ?

지역 λ³€μˆ˜λŠ” λ©”μ„œλ“œ 호좜이 λλ‚˜λ©΄ λ©”λͺ¨λ¦¬μ—μ„œ 사라지기 λ•Œλ¬Έμ— 읡λͺ… λ‚΄λΆ€ ν΄λž˜μŠ€μ—μ„œ μ‚¬μš©ν•˜λŠ” κ²½μš°μ—λŠ” 지역 λ³€μˆ˜κ°€ μƒμˆ˜λ‘œ λ³€ν•œλ‹€. λžŒλ‹€μ‹ μ—­μ‹œ 읡λͺ… λ‚΄λΆ€ ν΄λž˜μŠ€κ°€ μƒμ„±λ˜λ―€λ‘œ μ™ΈλΆ€ λ©”μ„œλ“œμ˜ 지역 λ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜λ©΄ λ³€μˆ˜λŠ” final λ³€μˆ˜, 즉 μƒμˆ˜κ°€ λœλ‹€. λ”°λΌμ„œ 이 λ³€μˆ˜λ₯Ό λ³€κ²½ν•˜λ©΄ 였λ₯˜κ°€ λ°œμƒν•˜λŠ” 것이닀.

​

​

​

*λ§€κ°œλ³€μˆ˜λ‘œ μ „λ‹¬ν•˜λŠ” λžŒλ‹€μ‹

λžŒλ‹€μ‹μ„ λ³€μˆ˜μ— λŒ€μž…ν•˜λ©΄ 이λ₯Ό λ§€κ°œλ³€μˆ˜λ‘œ 전달할 수 μžˆλ‹€. 이 λ•Œ μ „λ‹¬λ˜λŠ” λ§€κ°œλ³€μˆ˜μ˜ μžλ£Œν˜•μ€ μΈν„°νŽ˜μ΄μŠ€ν˜•μ΄λ‹€.

​

TestLambda.java

package lambda;

interface PrintString {
	void showString(String str);
}

public class TestLambda {
	public static void main(String[] args) {
		PrintString lambdaStr = s -> System.out.println(s);
		lambdaStr.showString("hello lamda_1"); // λžŒλ‹€μ‹μ„ μΈν„°νŽ˜μ΄μŠ€ν˜• λ³€μˆ˜μ— λŒ€μž…ν•˜κ³  κ·Έ λ³€μˆ˜λ₯Ό μ‚¬μš©ν•΄ λžŒλ‹€μ‹ κ΅¬ν˜„λΆ€ 호좜
		showMyString(lambdaStr); // λ©”μ„œλ“œμ˜ λ§€κ°œλ³€μˆ˜λ‘œ λžŒλ‹€μ‹μ„ λŒ€μž…ν•œ λ³€μˆ˜ 전달
	}

	public static void showMyString(PrintString p) { // λ§€κ°œλ³€μˆ˜λ₯Ό μΈν„°νŽ˜μ΄μŠ€ν˜•μœΌλ‘œ λ°›μŒ
		p.showString("hello lamda_2");
	}
}

<μ‹€ν–‰ κ²°κ³Ό>

​

​

 

*λ°˜ν™˜ κ°’μœΌλ‘œ μ“°μ΄λŠ” λžŒλ‹€μ‹

​​

TestLambda.java

package lambda;

interface PrintString {
	void showString(String str);
}

public class TestLambda {
	public static void main(String[] args) {
		PrintString lambdaStr = s -> System.out.println(s);
		lambdaStr.showString("hello lamda_1");
		showMyString(lambdaStr);

		PrintString reStr = returnString();  // λ³€μˆ˜λ‘œ λ°˜ν™˜ν•˜κΈ°
		reStr.showString("hello");           // λ©”μ„œλ“œ 호좜
	}

	public static void showMyString(PrintString p) {
		p.showString("hello lamda_2");
	}

	public static PrintString returnString() { // λžŒλ‹€μ‹μ„ λ°˜ν™˜ν•˜λŠ” λ©”μ„œλ“œ
		return s -> System.out.println(s + " World");
	}
}

<μ‹€ν–‰ κ²°κ³Ό>

​

β˜… μ§€κΈˆκΉŒμ§€ 보면 λžŒλ‹€μ‹μ€ ν•¨μˆ˜μ˜ κ΅¬ν˜„λΆ€λ₯Ό λ³€μˆ˜μ— λŒ€μž…ν•˜κ³ , λ§€κ°œλ³€μˆ˜λ‘œ μ „λ‹¬ν•˜κ³ , ν•¨μˆ˜μ˜ λ°˜ν™˜ κ°’μœΌλ‘œ μ‚¬μš©ν•  수 μžˆλ‹€. 마치 λ³€μˆ˜μ²˜λŸΌ μ‚¬μš©ν•  수 μžˆλ‹€. μ΄λŠ” ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ˜ νŠΉμ§• 쀑 ν•˜λ‚˜μ΄λ‹€.

λ°˜μ‘ν˜•

λŒ“κΈ€