내부 클래스(inner class)
- 말 그래도 클래스 내부에 클래스를 선언하는 경우
- 외부에서는 사용할 일이 없는 클래스
- 중첩 클래스라고도 함
- 익명(anonymous) 내부 클래스를 가장 많이 활용되고 있음
- 종류 : 인스턴스 내부 클래스, 정적(static) 내부 클래스, 지역(local) 내부 클래스, 익명 내부 클래스
- 인스턴스 내부 클래스(instance inner class)
- 내부적으로 선언 - private으로 보통 선언
- private이 아닌 경우도 있음 → 외부에서 생성할 수도 있음
- inner class는 outer class가 먼저 생성이 되고난 후에 생성이 됨
- inner class 내부에서는 정적 변수를 사용할 수 없음 (static 변수) → 사용하고자 한다면 정적 내부 클래스에서 사용해야 함
- 정적 내부 클래스(static inner class)
- 정적 클래스의 일반 메서드, static 메서드에서 외부 클래스의 인스턴스 변수를 사용할 수 없음 ⇒ 정적 클래스가 외부 클래스와 상관없이 만들어질 수도 있기 때문
- 대신 본인의 인스턴스 변수를 쓰는 것은 상관없음
- 하지만 static 메서드에서는 내부 클래스의 인스턴스 변수는 쓸 수 없음
- ⇒ static 메서드는 현재 클래스가 생성되지 않아도 호출될 수 있다라는 것이고 그때느 ㄴ내부 클래스의 인스턴스 변수가 생성되어 있지 않을 수도 있기 때문
- 지역 내부 클래스(local inner class)
- 메서드 내부에서 정의해 사용하는 클래스
- 메서드 호출이 끝나면 사용된 지역변수의 유효성 사라짐
- 지역 내부 클래스에서 사용하는 메서드의 지역 변수나 매개 변수는 final로 선언(자동)
- ⇒ 메서드 호출 이후에도 사용해야 하는 경우가 있을 수 있음
- Runnable interface : java.lang.Runnable → 클래스를 쓰레드화 할 때에 필요한 Run 메서드를 구현할 때 사용하는 인터페이스
- 클래스를 쓰레드로 만드는 방법
- 쓰레드 클래스에서 extends 받는 방법
- Runnable interface 를 implements
- Runnable getRunnable(){ class MyRunnable implements Runnable{ @Override public void run(){} } } return MyRunnable();
- 익명 내부 클래스(Anonymous inner class)
- 클래스 이름을 없애고 하나의 인터페이스나 추상 클래스를 구현하여 반환
- 익명 내부 클래스 예시위 코드에서 아래 코드와 같이 변환하여 사용 (MyRunnable 클래스 이름은 실제로 호출되는 경우는 없음)
- Runnable getRunnable(final int i) { final int i = 10; return new Runnable() { ... } }; 혹은 Runnable runnable = new Runnable(){ ... }
람다식(Lambda expression)
-
함수형 프로그래밍 방식 : 람다식
-
함수의 구현과 호출만으로 프로그래밍이 수행 됨
-
함수형 프로그래밍(Functional Programming : FP)
- 함수형 프로그래밍은 하나의 프로그래밍 패러다임으로 정의되는 일련의 코딩 접근 방식이며, 자료처리를 수학적 함수의 계산으로 취급하고 상태와 가변 데이터를 멀리하는 프로그래밍 패러다임
- 순수함수(pure function)를 구현하고 호출 → 외부 자료에 side effect를 주지 않도록 구현
- 순수함수란? ⇒ 매개변수만 사용해서 만드는 함수
-
람다식 문법
- 익명 함수 생성
- 매개 변수와 매개 변수를 이용한 실행문 (매개변수) → {실행문;}
- java는 class없이 메서드만 호출 할 수는 없음
- 이 함수에 대한 람다식을 제공하겠다는 interface에 메서드 선언 : functional interface
- Ex) add() 함수
public int add(int x, int y){
return x + y;
}를 람다식으로 구현
public static void main(String[] args) {
Add add1 = (x, y) -> {return x+y;};
System.out.println(add3.add(223, 864)); -> 호출
}
- 실행문이 하나인 경우 중괄호를 생략할 수 있음. But, 그 중 한 문장이라도 return문이 있으면 생략할 수 없음.
- 실행문의 한 문장이 return문인 경우엔? ⇒ 중괄호와 return 동시 생략 가능
- 매개 변수가 하나인 경우 자료형과 괄호 생략 가능. 두개 이상은 괄호 생략 불가
-
함수형 인터페이스와 람다식 구현
- @(애노테이션(annotation) 함수형 인터페이스 : 컴파일러에게 정보를 주는 역할 / 오류를 사전에 막아주는 역할
- @FunctionalInterface : 메서드를 두 개이상 선언하면 안됌
스트림(Stream) - 흐름
java.io 패키지에서 제공하는 클래스들을 사용하려면 스트림(stream)이라는 개념을 이해해야 함
- 연산의 처리를 일괄성있게 진행될 수 있도록 제공해줌
- 주로 배열, 컬렉션을 대상으로 연산 수행 Ex) 컬렉션에서 .stream → stream 객체가 생성이 됨
- 스트림은 재사용 불가 - 재사용하려면 재생성해야 함
- 스트임은 크게 중간 연산과 최종 연산으로 구분. 최종 연산이 호출되어야 중간 연산이 수행이 됨. ⇒ 중간 연산에 대한 결과를 연산 중에 알 수 없음(’지연 연산’)
int[] arr = {1,2,3,4,5}
IntStream is = Arrays.stream(arr);
is.ForEach(n->System.out.println(n));
혹은
int sum = Arrays.stream(arr).sum();
System.out.println(sum);
이러한 방식으로 사용
- 중간 연산
- filter(), map(), sorted() ...
- 최종 연산
- ForEach(), count(), sum() ...
reduce() 연산
- 프로그래머가 연산을 직접 구현할 수 있음
- 첫 번째 파라미터 : 기본값
- 두 번째 파라미터 : BinaryOperator 라는 인터페이스를 구현한 부분 , 람다식 사용 가능. 혹은 BinaryOperator 를 구현한(impelements)한 class를 넣으면 됌
- 반드시 apply() 라는 메소드를 구현해야 함 ⇒? 두개의 인자를 받아서 계속적으로 호출하며 elements를 소모할 때까지 두개씩 비교하는 일
- T reduce(T identify, BinaryOperator accumulator) :