Language/Java

'Do it 자바프로그래밍 입문' 13장 정리

ABCD 2022. 10. 5.

내부클래스

  • 클래스 내부에 선언하는 클래스
  • 대게 외부 클래스와 밀접한 관련이 있음
  • 다른 클래스와 협력할 일이 없는 경우 선언하여 사용
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 추상클래스를 바로 생성
  • 마지막에 세미콜론( ; )을 사용하여 익명 내부 클래스가 끝났음을 선언해주어야 함.
  • 익명 내부 클래스에서 사용 하는 지역변수는 상수화되어 메서드 호출 후에도 사용 가능
  • 사용법
    1. 변수에 직접 대입하는 경우
    2. 메서드 내부에서 인터페이스 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
반응형

댓글

💲 추천 글