내부클래스
- 클래스 내부에 선언하는 클래스
- 대게 외부 클래스와 밀접한 관련이 있음
- 다른 클래스와 협력할 일이 없는 경우 선언하여 사용
class Out{
class In{
...
}
}
- 변수유형과 내부 클래스 유형 비교
인스턴스 내부 클래스
- 인스턴스 변수를 선언할 떄와 같은 위치에 선언
- 외부 클래스에서만 생성하여 사용하는 객체 선언시 사용
- 다른 외부 클래스에서 사용할 일이 없는 경우 인스턴스 내부 클래스로 정의
- 외부 클래스 생성 후 생성 -> 외부 클래스 생성없이 사용 불가
OutClass outClass = new OutClass();
OutClass.InClass inClass = outClass.new InClass();
- 내부 클래스를 private로 선언하지 않으면 다른 클래스에서도 사용 가능
정적 내부 클래스
- 인스턴스 내부 클래스와 같은 위치에 정의하며 static 예약어 사용
- 정저 내부 클래스에서 사용하는 메서드가 정적 메서드일 경우, 외부 클래스와 내부 클래스에 선언된 변수 중 정적변수만 사용 가능
- 외부 클래스를 생성하지 않아도 내부 클래스 자료형으로 선언하여 생성가능
OutClass.InStaticClass sInClass = new OutClass.InStaticClass();
- private로 선언된 메서드나 변수가 아니면 다른 클래스에서 사용 가능
OutClass.InStaaticClass.sTest();
지역 내부 클래스
- 메서드 내부에 클래스를 정의하여 사용 -> 메서드 안에서만 사용
- 지역 내부 클래스에서 사용하는 지역 번수는 상수로 처리된다.
package innerclass;
class Outer{
int outNum = 100;
static int sNum = 200;
Runnable getRunnable(int i) {
int num = 100;
class MyRunnable implements Runnable{
int localNum = 10;
@Override
public void run() {
//num = 200; 지역 변수는 상수로 바뀌므로 값을 변경할 수 없어 오류 발생
//= 100; 매개변수도 지역 변수처럼 상수로 바뀌므로 값을 변경할 수 없어 오류 발생
System.out.println("i = " + i);
System.out.println("num = " + num);
System.out.println("localNum = " + localNum);
System.out.println("outNum = " + outNum + "(외부 클래스 인스턴스 변수)");
System.out.println("Outer.sNum = " + Outer.sNum + "(외부 클래스 정적 변수)");
}
}
return new MyRunnable();
}
}
public class LocalInnerTest {
public static void main(String[] args) {
Outer out = new Outer();
Runnable runner = out.getRunnable(10);
runner.run();
}
}
- 7행 getRunnable( ) 메서드를 살펴보면 이 메서드의 반환형은 Runnable.
즉 이 메서드에서는 Runnable 자료형의 객체를 생성하여 반환해야함. - 메서드 안에 정의한 MyRunnable 클래스가 바로 지역 내부 클래스
- run( ) 메서드에서 Runnable 자료형을 반환해야 함으로 return MyRunnable( ); 문장으로 클래스를 생선한 후 반환
- 30~32행에 Outer 클래스를 생선한 후 Runnable형 객체로 getRunnable( ) 을 호출.
즉 클래스를 직접 생성하는게 아니라 getRunnable( ) 메서드를 통해 생선된 객체를 반환
Runnable Interface
- 자바에서 스레드를 만들 때 사용하는 인터페이스
- 반드시 run( ) 메서드를 구현해야 한다.
익명 내부 클래스
- 클래스 이름을 사용하지 않는 클래스
- 단 하나의 인터페이스 or 추상클래스를 바로 생성
- 마지막에 세미콜론( ; )을 사용하여 익명 내부 클래스가 끝났음을 선언해주어야 함.
- 익명 내부 클래스에서 사용 하는 지역변수는 상수화되어 메서드 호출 후에도 사용 가능
- 사용법
- 변수에 직접 대입하는 경우
- 메서드 내부에서 인터페이스 or 추상클래스를 구현하는 경우
** 내부 클래스 정리 **
함수형 프로그래밍
- 함수의 구현과 호출만으로 프로그램을 만들 수 있는 프로그래밍 방식
람다식(lambda expression)
- Java에서 제공하는 함수형 프로그래밍 방식
- 함수 이름이 없는 익명함수를 만드는 것!!
int add(int x, int y){
return x + y;
}
// 다음 코드를 람다식으로 변경
(int x, int y) -> {return x + y;}
람다식 문법
- 매개변수 자료형과 괄호생략하기
str -> {System.out.println(str);} //매개 변수가 하나인 경우는 괄호 생략 가능
x, y -> {System.out.println(x+y);} //오류 - x,y에서 매개변수가 2개이므로 괄호 필수
- 중괄호 생략하기
str -> System.out.println(str); //{ }괄호안의 구현부분이 한문장인 경우 { }괄호 생략 가능
str -> return str.length(); //한 문장이라도 return문 이면 { }괄호 생략 불가능
- return 생략하기
(x,y) -> x + y
str -> str.length( );
// return문 하나면 중괄호와 return 생략 가능!!
람다식 사용
- 람다식을 사용하려면 인터페이스를 먼저 만들고 인터페이스(함수형 인터페이스)에 람다식으로 구현할 메서드를 선언해야 함
함수형 프로그래밍은 순수 함수를 구현하고 호출함으로써 외부자료에 부수적인 영향을 주지 않도록 구현하는 방식이다.
순수함수
- 매개변수만을 사용하여 만든 함수
함수형 인터페이스
- 람다식을 구현하기 위해 람가식으로 구현할 메서드를 선언하는 곳
- 두개 이상의 메서드를 가져서는 안된다.
@functionalInterface 애노테이션
- 함수형 인터페이스를 의미
- 메서드를 둘이상 선언하면 오류가 남
- 반드시 사용해야 하는 것은 아니지만, 하는 것이 좋음
익명 객체를 생성하는 람다식
- Java는 객체지향 언어이지만, 람다식은 객체 없이 인터페이스의 구현만으로 메서드 소출 가능
함수를 변수처럼 사용하는 람다식
- 인터페이스형 변수에 람다식 대입 - Type 1
- 매개변수로 전달하는 람다식 - Type 2
- 반환 값으로 쓰이는 람다식 - Type 3
package lambda;
interface PrintString{
void showString(String str);
}
public class TestLambda {
public static void main(String[] args) {
PrintString lambda = s -> System.out.println(s);
lambda.showString("hello lambda_1");
showMyString(lambda);
PrintString reStr = returnString();
reStr.showString("Hello ");
}
public static void showMyString(PrintString p) {
p.showString("hello lambda_2");
}
public static PrintString returnString() {
return s -> System.out.println(s + "World");
}
}
hello lambda_1
hello lambda_2
hello world
스트림
- 여러자료의 처리에 대한 기능을 구현해 놓은 클래스
- 벼알, 컬렉션 등의 자료를 일관성 있게 처리 가능
- 자료를 추상화했다고 표현함
int[] arr = {1,2,3,4,5};
for(int i = 0; i < arr.length; i++){
System.out.println(arr[i]);
}
//이 배열에 대한 스트림을 생성
int[] arr = {1,2,3,4,5};
Arrays.stream(arr).forEach(n -> System.out.println(n));
스트림 연산
- 중간 연산 : 자료를 거르거나 변경하여 또 다른 자료를 내부적으로 생성
- 최종 연산 : 생성된 내부자료를 소모해 가면서 연산을 수행. 마지막에 한번 호출함.
- 최종연산이 호출되어야 중간연산의 결과가 만들어진다.
중간연산 filter( )
- 조건을 넣고 그에 맞는 참인 경우만 출력하는데 사용
- ex) 문자열의 길이가 5이상인 경우만 출력하는코드
중간연산 map( )
- 클래스가 가진 자료 중 이름만 출력하는 경우 사용
- 요소들을 순회하여 다른 형식으로 변환하기도 함
- ex)
최종연상 forEach( )
- 요소를 하나씩 꺼냄
최종연산 sum( )
- 요소의 합계를 구함
최종연산 count( )
- 요소의 개수를 출력
정수 배열에서 스트림 생성하고 사용하기 예시
Collection에서 스트림 생성하고 사용하기 예시(ArrayList 활용)
스트림의 특징
- 자료의 대상과 상관없이 동일한 연사을 수행
- 한번 생성하고 사용하는 스트림은 재사용 불가
- 스트림의 연산은 기존의 자료를 변경하지 않음
- 스트림의 연산은 중간연산과 최종 연산이 있다.
reduce( ) 연산
- 프로그래머가 기능을 지정
T reduce(T identify, BinaryOperator accumulator)
- T identify는 최초값을 의미
- BinaryOperator accumulator는 수행하야 할 기능을 의미
- BinaryOperator는 함수형 인터페이스로 apply( ) 메서드를 반드시 구현 해야함
BinaryOperator
- 두 매개변수로 람다식을 구현하며 이 람다식이 각 요사가 수행해야할 기능이 된다.
- 람다식을 직접 작성하거나, 인터페이스를 구현한 클래스를 생성하여 대입
apply( ) 메서드
- 두개의 메개변수와 한개의 반환 값을 가짐
- 위 세개의 값들은 모두 같은 자료형
728x90
반응형
'Language > Java' 카테고리의 다른 글
멀티캠퍼스 6일차 (0) | 2022.10.19 |
---|---|
'Do it 자바프로그래밍 입문' 14장 정리 (0) | 2022.10.06 |
'Do it 자바프로그래밍 입문' 12장 정리 (2) | 2022.09.30 |
'Do it 자바프로그래밍 입문' 11장 정리 (0) | 2022.09.27 |
'Do it 자바프로그래밍 입문' 10장 정리 (0) | 2022.09.23 |
댓글