Java(7)

Jinny·2021년 6월 14일
0

JAVA

목록 보기
5/8

내부클래스

클래스 내부에 있는 클래스

  • 인스턴스 내부 클래스
    • 외부 클래스의 멤버 변수와 동일한 위치에 구현된다.
    • 외부 클래스를 먼저 만든 후 내부 클래스 생성된다.
    • static 변수와 메서드를 생성할 수 없다.
  • 정적 내부 클래스
    • 외부 클래스의 멤버 변수와 동일한 위치에 구현된다.
    • 외부 클래스의 정적 변수만 사용 가능하다.
    • 외부 클래스와 무관하게 생성된다.
  • 지역 내부 클래스
    • 메서드 내부에 구현된다.
    • 메서드를 호출할 때 생성된다.
  • 익명 내부 클래스(anonymous inner class)
    • 지역 내부 클래스는 클래스 이름이 사용될 일이 거의 없어 이름을 없애 구현한 것이 익명 내부 클래스이다.
    • 메서드 내부에 구현되거나, 변수에 대입하여 직접 구현된다.
    • 메서드 안에 구현했을땐 메서드를 호출할 때 생성되거나, 인터페이스 타입 변수에 대입할 때 new 예약어를 사용하여 생성

람다식(lambda expression)

자바는 객체지향 프로그램 언어이기 때문에 자바에서 함수형 프로그래밍을 구현하는 방식으로 람다식을 제공한다. 클래스를 생성하지 않고 함수의 호출만으로 기능을 수행하는 방식이다.

함수형 프로그래밍

순수 함수(pure function)를 구현하고 호출함.

  • 순수 함수

    • 안정적이다. (외부 자료에 부수적인 영향을 주고받지 않고 매개 변수만을 사용해서 동작하도록 만든 함수여서 동일한 입력에 대해 동일한 결과를 리턴한다.)
  • 병렬 처리가 가능하다. (외부 자료에 영향을 미치지 않기 때문에 side effect가 없어 여러 함수가 동시에 수행될 수 있다.)

람다식 구현

함수 이름과 반환 형을 없애고 ->를 사용한다. {}까지가 실행문을 의미

(int x, int y) -> {return x + y;}
  • 함수형 인터페이스

    • 람다식을 선언하기 위한 인터페이스
    • 익명 함수와 매개 변수만으로 구현되므로 단 하나의 메서드만 가져야 한다.
    • @FunctionalInterface 어노테이션을 사용해 컴파일 에러를 막을 수 있음
  • 자바는 객체 지향 언어로 객체를 생성해야 메서드가 호출된다. 따라서 람다식으로 메서드를 구현하고 호출하면 내부에서 익명 클래스가 생성된다. 이 람다식에서 외부 메서드의 지역변수는 상수로 처리 됨(지역 내부 클래스와 동일한 원리)

    @FunctionalInterface
    interface StringConcat {
        public void makeString(String s1, String s2);
    }
    
    public class TestStringConcat {
        public static void main(String[] args) {
            StringConcat concat = (s1, s2) -> System.out.println(s1 + ", " + s2);
            concat.makeString("hello", "java");
    		
            // 내부적으로 생성되는 구현부
            StringConcat concat = new StringConcat(){
                @Override
                public void makeString(String s1, String s2){
                    System.out.println(s1 + ", " + s2);
                }
            };
        }
    }

스트림

일관성 있는 연산을 처리할때, 자료를 더 효율적으로 연산할 수 있도록 제공되는 객체이다.

  • 자료의 대상과 관계 없이 동일한 연산을 수행한다.
    • 스트림이 제공하는 메서드들은 배열, 컬렉션 등에 상관 없이 동일한 연산을 수행함
    • 일관성 있는 연산으로 자료의 처리를 쉽고 간단하게 함
  • 한번 생성하고 사용한 스트림은 재사용 할 수 없음
    • 자료에 대한 스트림을 생성하여 연산을 수행하면 스트림은 소모됨
    • 다른 연산을 위해서는 새로운 스트림을 생성 함
  • 스트림 연산은 기존 자료를 변경하지 않음
    • 자료에 대한 스트림을 생성하면 별도의 메로리 공간을 사용하므로 기존 자료를 변경하지 않음
  • 스트림 연산은 중간 연산과 최종 연산으로 구분됨
    • 스트림에 대한 중간 연산은 여러 개 적용될 수 있지만 최종 연산은 마지막에 한번만 적용된다.
    • 최종 연산이 호출되어야 중간연산의 결과가 모두 적용된다.
    • 이를 '지연 연산(lazy evaluation)' 이라고 함
    • 중간 연산 - filter(), map() 등

reduce() 연산

정의된 연산이 아닌 프로그래머가 직접 지정하는 연산을 적용할 수 있다.

최종 연산으로 스트림의 요소를 소모하여 연산을 수행

String[] greetings = {"안녕", "hello", "Good morning", "hi"};

// 직접 람다식 구현하는 방법
System.out.println(Arrays.stream(greetings).reduce("", (s1, s2) -> {
    if(s1.getBytes().length >= s2.getBytes().length)
        return s1;
    else return s2;
}));

// 연산을 구현한 클래스를 사용하는 방법
String str = Arrays.stream(greetings).reduce(new CompareString()).get();   
profile
삐약 응애

0개의 댓글