본문 바로가기

말하는 감자 탈출하기

Java day10

내부 클래스

인스턴스, 정적(static), 지역(local), __이너클래스 4가지가 있음

 

예제

- 인스턴스 이너클래스 : 외부클래스가 생성될 때 같이 생성됨

package innerclass;

class OutClass{ 
	//instance innerclass: static 키워드x, 메서드 안에서 정의된 것도 아님
	private InClass inClass;
	private int num=100;
	
	public OutClass() {
		inClass=new InClass();
	}
	
	class InClass{
		
		int inNum=200;
		void inTest() {
			System.out.println(num); // private에 접근 가능
		}
	}
	public void usingInMethod() {
		inClass.inTest();
	}
}

// 내부클래스 기준 외부클래스
public class InnerclassTest {

	public static void main(String[] args) {
		OutClass outer=new OutClass();
		outer.usingInMethod();
		
		// 먼저 생성된 outer를 레퍼런스로 외부(InnerclassTest)에서도 내부 클래스를 만들 수 있다
		OutClass.InClass inClass =outer.new InClass();
		inClass.inTest();
	}

}

- static 이너클래스: 외부 클래스의 생성과 무관하게 생성되어 외부 클래스의 private 변수를 사용할 수 없음

 

class InClass 앞에 static 키워드를 붙여주면 num을 프린트할 수 없음

-> num은 외부클래스가 생성될 때 생성되기때문에 외부클래스가 생성되어야 사용할 수 있는데 정적 이너클래스는 외부클래스의 생성과 상관없이 생성되기때문

 

package innerclass;

class Outer {
	public Runnable getRunnable() {
		class MyRunnable implements Runnable {

			@Override
			public void run() {
				System.out.println("run()");

			}
		}
		return new MyRunnable();
	}
}

public class AnonymousInnerTest {

	public static void main(String[] args) {

		Outer outer = new Outer();
		Runnable runnable = outer.getRunnable();
		runnable.run();
	}

}

-> MyRunnable  클래스는 클래스 내부에서만 사용하기때문에 이름이 굳이 필요가 없음-> 익명 클래스를 사용할 수 있음

 

- MyRunnable  클래스를 익명 클래스로 대체

package innerclass;

class Outer {
	public Runnable getRunnable() {
		return new Runnable() {

			@Override
			public void run() {
				System.out.println("run() by anonymous class");
				
			}
			
		};
	}
}

public class AnonymousInnerTest {

	public static void main(String[] args) {

		Outer outer = new Outer();
		Runnable runnable = outer.getRunnable();
		runnable.run();
	}

}
package innerclass;

class Outer {
	public Runnable getRunnable() {
    	//int num=10;
		return new Runnable() {

			@Override
			public void run() {
            	// num=200; //에러: num은 지역 메서드 안에 선언된 변수이므로 상수와 마찬가지(final) -> 값을 변경할 수 없음 
				System.out.println("run() by anonymous class");
				
			}
			
		};
	}
	Runnable runner = new Runnable() {

		@Override
		public void run() {

			System.out.println("runner");
			
		}
		
	};
}

public class AnonymousInnerTest {

	public static void main(String[] args) {

		Outer outer = new Outer();
		Runnable runnable = outer.getRunnable();
		runnable.run();
		
		outer.runner.run();
	}

}

인터페이스 Runnable을 새로운 변수 runner의 타입을 선언할 때 바로 사용할 수 있음 

클래스당 하나만 사용할 수 있음


람다식 - 함수형 프로그래밍

외부 변수를 이용하지 않고 매개변수만을 이용하도록 만든 함수 -> 병렬 처리가 가능함-> 안정적, 확장성 증대

 

익명 함수 만들기

매개 변수와 매개변수를 활용한 실행문으로 구현

- 매개 변수가 하나인 경우 자료형, 괄호 생략 가능

str -> {System.out.println(str);}

-> 구현부가 한 문장인 경우 중괄호 생략 가능

str -> System.out.println(str);

- 구현부가 한문장이라도 return 문이라면 중괄호 생략 불가

-> 하지만 return 문이 한 문장이면 return을 생략할 수 있고 이때는 중괄호 생략 가능

(x,y) -> x+y
str -> str.length()

 


클래스를 만들지 않고 메서드를 호출하기 위해 functional interface 사용 @FunctionalInterface

인터페이스 안에는 하나의 메서드만 선언 가능

 

예제> 문자열 더하기

- 인터페이스 정의

package lambda;

@FunctionalInterface
public interface StringConcat {
		public void stringConcat(String s1, String s2);
}

- 인터페이스를 implements하는 클래스 정의(클래스로 구현하는 방식에만 사용됨)

package lambda;

public class StringConcatImpl implements StringConcat{

	@Override
	public void stringConcat(String s1, String s2) {
		
		System.out.println(s1+s2);
		
	}

}

- 인터페이스를 이용해서 클래스/ 람다/ 이너클래스 방식으로 구현

package lambda;

public class StringConcatImplTest {

	public static void main(String[] args) {
		// 클래스 사용
		StringConcatImpl impl=new StringConcatImpl();
		impl.stringConcat("hello", "world");
		
		//람다 사용(내부적으로 익명클래스가 만들어짐)
		//인터페이스
		StringConcat lambdaImpl=(s1,s2)->System.out.println(s1+s2+"using lambda");
		lambdaImpl.stringConcat("hello", "world");
		
		//익명 이너클래스 -> 인터페이스로 익명 클래스를 만듬
		StringConcat innerImpl=new StringConcat() {
			
			@Override
			public void stringConcat(String s1, String s2) {
				
				System.out.println(s1+s2+"using innerclass");
				
			}
		};
		innerImpl.stringConcat("hello", "world");
	}

}

예제2

package lesson13;

@FunctionalInterface
public interface Calc{
	public int add(int num1, int num2);
}
package lesson13;

public class CalcTest{
	public static void main(String[] args){
    
    	Calc sum=(x,y)->x+y;
        
        System.out.println(sum.add(20,30));
       
    }
}

'말하는 감자 탈출하기' 카테고리의 다른 글

데이터베이스 설계  (0) 2023.05.30
Java day11  (0) 2023.05.29
원리틀 투리틀 쓰리리틀 인디언  (0) 2023.05.20
화면 설계도 작성하기  (0) 2023.05.15
Java day9  (0) 2023.05.14