[18일차] enum,에노테이션,람다식,스트림

유태형·2022년 5월 19일
0

코드스테이츠

목록 보기
18/77

오늘의 목표

  1. Enum
  2. 에노테이션
  3. 람다식
  4. 람다식 기본 문법
  5. 함수형 인터페이스
  6. 메서드 레퍼런스
  7. 스트림
  8. 파이프라인 구성(.)
  9. Optional<T>



내용

Enum

Enum은 열거형으로 서로 관련있는 것들을 모아 번호를 모아 놓은 것을 의미합니다. 관련잇는 것들은 열거형으로 만들 수 있습니다.

  • 한식, 일식, 중식, 양식
  • 봄, 여름, 가을, 겨울
  • 상의, 하의, 양말, 모자

enum을 정의하는 방법

enum 열거형이름 {상수명1, 상수명2, 상수명3, ...}

사계절로 예를 들어 정의 한다면

enum Seasons {SPRING, SUMMER, FALL, WINTER} //상수는 관례적으로 모두 대문자

enumstatic을 사용하는 것과 동일하게 열거형이름.상수명으로 참조 가능합니다.

package JAVA_Effective;

enum Seasons {SPRING, SUMMER, FALL, WINTER} //열거형 정의

public class EnumExample {
    public static void main(String[] args) {
        System.out.println(Seasons.SPRING); //열거형명.상수명
    }
}
//Console
//Spring

enum열거형이름 타입의 변수에 할당 가능합니다.

	Seasons myBestSeason = Seasons.WINTER;
리턴 타입메서드(매개변수)설명
Stringname()열거 객체가 가지고 있는 문자열을 리턴하며, 리턴되는 문자열은 열거타입을 저의 할때 사용한 상수 이름과 동일합니다.
intordinal()열거 객체의 순번을 리턴합니다.
intcompareTo(비교 상수)비교 상수와 비교해서 순번 차이 리턴
열거 타입valueOf(String name)문자열의 열거 객체를 리턴합니다.
열거 배열values()모든 열거 객체들을 배열로 리턴합니다.


public static final의 한계

public static final int SPRING = 1;
public static final int SUMMER = 2;
public static final int FALL   = 3;
public static final int WINTER = 4;

//상수 값이 동일하다면 컴파일 에러 발생

public static final int DJANGO  = 1;
public static final int SPRING  = 2; 
public static final int NEST    = 3;
public static final int EXPRESS = 4;

인터페이스의 상수로 선언하여 임시로 구별할 수도 있지만 실수로 비교시 에러가 발생하지 않아 안정성의 문제가 있으므로 열거형을 사용 합니다.

enum Seasons {SPRING,SUMMER,FALL,WINTER}
enum Frameworks {DJANGO,SPRING,NEST,EXPRESS}

switch문은 기본 리터럴 타입과, enum 열거형만 구분할 수 있습니다. 사용자가 임의로 정의한 클래스는 구분할 수 없습니다.

package JAVA_Effective;
enum Seasons2 {SPRING, SUMMER, FALL, WINTER}

public class EnumExample3 {
    public static void main(String[] args) {
        Seasons2 seasons = Seasons2.FALL; //가을

        switch(seasons){ //enum 열거형은 switch 구분 가능
            case SPRING:
                System.out.println("봄");
                break;
            case SUMMER:
                System.out.println("여름");
                break;
            case FALL:
                System.out.println("가을");
                break;
            case WINTER:
                System.out.println("겨울");
                break;
        }
    }
}
//Console
가을

enum의 장점

  • 상수값의 중복을 피할 수 있습니다.
  • 타입에 대한 안정성 (비교할 수 없는 대상간 비교 하지 않음) 보장합니다.
  • 코드가 단순해지고 가독성이 좋습니다.
  • switch문에 사용 가능합니다.



에노테이션

에노테이션은 소스코드에는 아무런 영향을 미치지 않으면서 정보를 제공합니다. 누구에게 정보를 제공하는가에는 주석과 차이가 있습니다.

  • 주석 : 소스 코드를 읽는 사람에게 정보를 제공합니다.
  • 에노테이션 : 프로그램에게 정보를 제공합니다.

@에노테이션 //아래 메서드가 대상임을 프로그램에게 알리는 에노테이션
접근지정자 반환타입 메서드(매개변수) {...}

에노테이션은 프로그램에게 정보를 제공하기 위해 사용됩니다.

  1. 컴파일러에게 문법 에러를 체크하도록 정보를 제공합니다.
  2. 프로그램을 빌드할 때 코드를 자동으로 생성할 수 있도록 정보를 제공합니다.
  3. 런타임에 특정 기능을 실행하도록 정보를 제공합니다.


표준 에너테이션

  • 표준 에너테이션 : 자바에서 기본적으로 제공하는 에너테이션입니다.
표준 에너테이션설명
@Override컴파일러에게 메서드를 오버라이딩하는 것이라고 알림
@Deprecated앞으로 사용하지 않을 대상을 알릴 때 사용
@FunctionalInterface함수형 인터페이스라는 것을 알림
@SuppressWarning컴파일러가 경고메세지를 나타내지 않음

@Override는 메서드 앞에만 붙일 수 있는 에너테이션이며, 상위 클래스의 메서드를 오버라이딩 한 메서드라는 것을 컴파일러에게 알려줍니다. 상위 클래스에서 @Override한 메서드와 이름이 동일한 메서드를 찾을 수 없다면 컴파일 에러를 발생 시킵니다.(메서드 이름 오타로 인한 버그 방지)

class Super{
	void run(){}
}
class Sub extends Super{
	@Override
    void rnu(){}
}

@Deprecated는 업데이트의 이유로 더 이상 사용하지 않는 필드나 메서드가 생겼을 때, 더 이상 사용하지 않음을 표시합니다. 호환의 이유로 삭제는 곤란하지만 권장하지 않을 때 @Deprecated를 사용합니다.

class Old{
	@Deprecated
    int oldField;
    
    @Deprecated
    int getOldField(){return oldField;}
}
//Console
Note: 파일명.java uses or overrides a deprecated API.
Note: Recomplie with -Xlint:deprecation for details.

@SuppressWarning는 컴파일 경고가 나타나지 않도록 합니다. 억제하고자 하는 경고메세지를 지정해 줄 수도 있습니다.

@SuppressWarnings("경고메시지")

  • all : 모든 경고를 억제
  • deprecation : @Deprecated 메서드를 사용한 경우 나오는 경고 억제
  • fallthrough : switch문에서 break 구문이 없을 때 경고 억제
  • finally : finally 관련 경고 억제
  • null : null 관련 경고 억제
  • unreached : 검증 되지 않은 연산자 관련 경고 억제
  • unused : 사용하지 않는 코드 관련 경고 억제

@FunctionalInterface는 함수형 인터페이스를 선언 할 때 올바르게 선언하였는지 확인합니다. 실수 방지확인 용이며 함수형 인터페이스는 추상메서드가 1개만 있어야 하는데 2개 이상인 경우 에러를 발생 시킵니다.



메타 에너테이션

  • 메타 에너테이션 : 에너테이션에 붙이는 에너테이션으로 에너테이션을 정의하는 데 사용
메타 에너테이션설명
@Target에너테이션을 정의할 때 적용 대상을 지정하는데 사용
@Documented에너테이션 정보를 javadoc으로 작성된 문서에 포함
@Inherited에너테이션이 하위 클래스에 상속되도록 함
@Retention에너테이션이 유지되는 기간을 지정
@Repeatable에너테이션ㅇ르 반복해서 적용할 수 있게 함

@Target에너테이션으로 적용범위를 정할 수 있습니다. 열거형으로 대상타입들을 복수 지정 가능합니다.

import static java.lang.annotation.ElementType.*;
//import 문을 이용하여 ElementType 생략 가능

@Target({FIELD,TYPE,TYPE_USE}) //적용 대상이 FIELD, TYPE
public @interface CustomAnnotation {} //CustomAnnotation 정의

@CustomAnnotation //적용대상이 TYPE인 경우
class Min{
	@CustomAnnotation //적용대상이 FIELD인 경우
    int i;
}

@Dcumented

@Documented
@Target(ElementType.Type)
public @interface CustomAnnotation{}

@Inherited는 하위 클래스가 에너테이션을 상속받도록 합니다. 상위클래스에 @Inherited에너테이션을 작성하면, 하위 클래스도 상위 클래스의 에너테이션이 적용됩니다.

@Inherited //상속 받는 하위클래스도 영향
@Interface SuperAnnotation{}

@SuperAnnotation
class Super{}

class Sub extends Super{} //@SuperAnnotation도 상속받음

@Retention에너테이션은 유지 정책입니다. 유지 정책은 에너테이션이 유지되는 기간을 정하는 속성입니다.

유지 정책설명
SOURCE.java 소스 파일까지는 에너테이션이 존재, 컴파일 시 클래스 파일이 되면 사라짐
CLASS.class 파일까지는 에너테이션이 존재, 런타임에서 사라짐
RUNTIME런타임 실행시까지 에너테이션이 남아있음

@Repeatable에너테이션이 붙은 에너테이션은 여러번 작성할 수 있습니다.

@Repeatable(ToDos.class) //Todos 에너테이션을 여러번 반복해서 사용할 수 있게 합니다.
@interface ToDo{
	String value()
}
//일반적인 에너테이션과 달리 여러번 적용 될 수 있기 때문에 에너테이션들을 하나로 묶어 주는 별도의 에너테이션도 별도로 작성해야 합니다.

@interface ToDos{ //여러개의 ToDo를 담는 컨테이너 에너테이션 ToDos
	ToDo[] value(); //ToDo 에너테이션 배열 타입의 요소 선언, 이름은 반드시 value여야함
}
@ToDo("update test codes.")
@ToDo("override test method")
class Main{
}
대상 타입적용 범위
ANNOTATION_TYPE에너테이션
CONSTRUCTOR생성자
FIELD필드(멤버,열거형)
LOCAL_VARIABLE지역변수
METHOD메서드
PACKAGE패키지
PARAMETER매개변수
TYPE타입
TYEP_PARAMETER타입매개변수
TYPE_USE타입이 사용되는 모든 대상


사용자 정의 에너테이션

  • 사용자 정의 에너테이션 : 사용자가 직접 정의하는 에너테이션 입니다. 에너테이션을 정의하는 방법은 java.lang.annotation인터페이스를 상속 받기 때문에 다른 클래스나 인터페이스를 상속받을 수 없으며, 인터페이스를 정의하는 것과 비슷 한 방법으로 정의할 수 있습니다.

@interface 에너테이션명{ //@interface 에너테이션으로 에너테이션을 정의할 수 있습니다.
타입 요소명(); //에너테이션 요소 선언합니다.
}




람다식

람다식은 객체 지향보단 함수 지향 언어에 가깝습니다. 객체지향인 자바에서 함수 지향인 람다식을 사용하는 이유는 매우 깔끔하고 간결한 코드를 작성할 수 있기 때문입니다. 또 요소를 필터링 하거나 매핑해서 원하는 결과를 집계할 수도 있습니다.

클래스타입 참조_변수 = new 클래스타입(매개변수){
	접근제어자 반환타입 메서드명(매개변수){...}
}

객체지향의 객체를 생성하는 전형적인 코드입니다.

클래스타입 참조_변수 = (매개변수) -> {...};

으로 람다식 (매개변수) -> {실행코드} 형태로 작성되는데 마치 함수 정의 형식을 띄지만 런타임때 익명 구현 객체로 생성됩니다. 어떤 인터페이스를 구현할 것인가는 대입되는 인터페이스에 달립니다.




람다식 기본 문법

//기본 방식
(매개변수) -> {...}

//매개변수가 1개일 때 괄호() 생략 가능
매개변수 -> {...}

//매개변수가 2개이상이고 리턴문만 존재할 때는 return 생략 가능
(매개변수1, 매개변수2,...) -> 리턴값
	(num1, num2) -> num1 + num2; //return 생략, 중괋호{}도 생략

//매개변수가 2개이상, 실행문 실행후 결과값 리턴
(매개변수1,매개변수2,...) -> {...}

(타입 매개변수)로 필요한 값을 제공하고 {실행문}으로 실행훈 리턴값이 있으면 리턴합니다. 각각 타입 매개변수가 1개이면 괄호()를 생략할 수 있고 실행문에서 return중괄호{}도 생략할 수 있습니다.




함수형 인터페이스

자바는 새로운 함수 문법을 정의하는 대신, 인터페이스 문법을 활용해 람다식을 표현합니다. 단 하나의 춧아 메서드만을 포함하는 인터페이스를 함수형 인터페이스라고 합니다.



타겟 타입과 함수형 인터페이스

람다식은 하나의 추상메서드만 존재하는 인터페이스만 타겟이 될 수 있습니다. 다라서 반드시 하나의 추상메서드만 선언되어야 하며 2개이상의 추상메서드가 있다면 람다식으로 사용하려 할때 에러를 발생 시켜야 합니다. @FunctionalInterface에너테이션 사용시 추상메서드가 2개 잇아이면 컴파일 시 오류를 발생시킵니다.

@FunctionalInterface
public interface MyFunctionalInterface{
	public void one(); //추상 메서드 1개 가능
    //public void another(); //추상 메서들 2개이상은 함수형 인터페이스 불가능
}
MyFunctionalInterface example = () -> {...} //람다식으로 구현한 객체

매개변수는 인터페이스의 추상 메서드의 매개변수와 일치 시켜야 합니다.

만약 매개변수가 존재한다면

@FunctionalInterface
interface MyFunctionalInterface{
	publci void one(int x); //int형 매개변수 1개
}

매개변수를 고려하여 추상메서드를 선언해야 하고

MyFunctionalInterface example = (x) -> {
	int result = x * 5;
};
example.one(2);

(매개변수)에 자료형 없이 매개변수를 입력 하여야 사용할 수 있습니다.




메서드 레퍼런스

(left,right) -> Math.max(left,right);

람다식은 두개의 매개변수로 단순히 Math.max() 메서드의 매개값으로 전달하는 역할만 하기 때문에 비효율적으로 보입니다. 이럴때 메서드 레퍼런스로 깔금하게 처리 간으합니다.

MyOperator operato = Math :: max; //메서드 레퍼런스

클래스(정적) 메서드를 참조할 경우

클래스 :: 메서드

인스턴스 메서드를 참조할 경우

참조_변수 :: 메서드

IntBinaryOperator operator; //2개의 매개변수를 가지는 메서드 레퍼런스를 담는 변수

Calculator calculator = new Calculator();
operator = calculator :: instanceMethod; //메서드 레퍼런스 받아 옵니다.
System.out.println("인스턴스 메서드 결과 : " + operator.applyAsInt(3,5)); //메서드 실행

생성자를 참조하는 경우

(a,b) -> {return new 클래스(a,b);};

단순히 객체를 생성하고 리턴하도록 구성된 람다식은 생성자 참조로 대치 가능합니다.

클래스 :: new

함수형 인터페이스의 추상메서드와 동일한 매개변수 타입과 갯수를 가진 생성자를 찾아 실행합니다. 만약 해당 생성자가 존재하지 않는다면 컴파일 에러를 발생시킵니다.

Function<T t,G g> 참조_변수 = 클래스 :: new; //매개변수 t를 g에 매핑
G g1 = 참조_변수.apply(매개변수); //객체 생성
BiFunction<T t,S s,G g> 참조_변수 = 클래스 :: new; //매개변수 t와s를 g에 매핑
G g2 = 참조_변수.apply(매개변수1,매개변수2); //객체 생성



스트림

스트림(Stream)은 배열 컬랙션의 저장 요소를 하나씩 참조해서 람다식으로 처리할 수 있도록 해주는 반복자 입니다. 스트림을 사용하면 List,Set,Map,배열등 다양한 데이터 소스로부터 스트림을 만들 수 있고, 이를 표준화된 방법으로 다룰 수 있습니다.



선언형으로 데이터 처리

package JAVA_Effective;

import java.util.List;

public class DeclarativeProgrammingExample {
    public static void main(String[] args) {
        List<Integer> numbers = List.of(1,3,6,7,8,11); //리스트 생성

        int sum =
                numbers.stream() //스트림 원본
                        .filter(number -> number > 4 && (number % 2 == 0)) //필터링
                        .mapToInt(number -> number) //매핑
                        .sum(); //집계함수
        System.out.println("선언형 프로그램잉 : " + sum);
    }
}
//Console
선언형 프로그램잉 : 14
  • .stream() : 컬렉션을 스트림 객체로 생성합니다.
  • .filter(요소 -> 조건) : 특정 조건에 부합하는 요소들로만 걸러낼 수 있습니다.
  • .mapToInt(요소 -> 요소) : 스트림을 Integer 타입에서 int타입으로 바꾸어줍니다.
  • .sum() : 스트림 내 모든 요소들의 합을 반환합니다.
package JAVA_Effective;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class StreamLambdaExample {
    public static void main(String[] args) {
        List<Student> list = Arrays.asList( //리스트 생성
                new Student("김코딩",95),
                new Student("이자바",92)
        );

        Stream<Student> stream = list.stream(); //스트림 반환
        stream.forEach(s -> { //for-each문 (내부 반복)
            String name = s.getName();
            int score = s.getScore();
            System.out.println(name + " - " + score);
        });
    }
}
//Console
김코딩 - 95
이자바 - 92
  • .forEach(s -> {}) : 이 스트림의 각 요소에 대해 for-each문을 수행합니다.



파이프라인 구성(.)

스트림의 데이터를 바로 가공해서 결과물로 바로 낼 수 없을 때 중간 연산들의 결과들을 이어 붙혀 최종 결과물을 얻는 것을 파이프라인이라 합니다. 필터링, 매핑, 그루핑 등을 중간연산이라 합니다.

예를 들어 남자의 평균 나이를 구한다고 가정합시다.
그러면 먼저 남자만으로 구성되도록 필터링을 해야하고, 그 다음 남자들의 나이를 구하는 매핑을 해야하고 마지막으로 평균을 구하는 집계처리를 수행해야 할 것입니다. 일련의 순서들을 이어 붙히는걸 파이프라인이라고 합니다.

double ageAvg = list.stream() //오리지날
.filter(m -> m.getGender() == Member.MALE) //필터링
.mapToInt(Member::getAge) //매핑
.average() //집계 처리(최종)
.getAsDouble();


스트림 생성

Collection 인터페이스에는 stream() 메서드가 정의되어있기 때문에 Collection 인터페이스를 구현한 객체들은 모두 stream()메서드를 이용하여 스트림을 ㅅ생성할 수 있습니다. stream()메서드는 스트림 객체를 반환합니다.

//List에서 스트림을 생성
List<String> list = Arrays.asList("a","b","c");
Stream<String> listStream = list.stream();
listStream.forEach(System.out::println); //스트림의 모든 요소 출력

스트림을 생성하기 위해서는 Stream.of()Arrays.stream()메서드를 사용합니다.

Stream<String> stream = Stream.of("a","b","c"); //가변인자
Stream<String> stream = Stream.of(new String[] {"a","b","c"});
Stream<String> stream = Arrays.stream(new String[] {"a","b","c"});
Stream<String> stream = Arrays.stream(new String[] {"a","b","c"},0,3);


필터링

  • distinct() : 스트림 내 요소들에서 중복된 데이터가 존재하는 경우 중복을 제거합니다.
  • filter(요소->조건) : 스트림 내에서 조건을 만족하는 요소만 남기고 나머지는 필터링합니다.


매핑

  • map000() : map은 기존의 Stream요소들을 대체하는 새로운 요소들로 구성된 Stream을 형성합니다.

대문자로 바뀌는 매핑

컬랙션.stream().map(s->s.toUpperCase()).forEach(n->System.out.println(n));

map()이외에도 mapToInt(), mapToLong(), mapToDouble()등의 메서드가 있습니다.



정렬

Stream의 요소들을 정렬하기 위해서는 .sorted()를 사용해야 하며 파라미터로 Comparator를 넘길 수 있습니다. Comparator인자 없이 호출할 경우 오름차순으로 정렬이 되며, 내림차순 정렬을 위해선 Comparator의 reverseOrder를 이용합니다.

컬렉션.stream().sorted().forEach(n->System.out.println(n)); //오름차순 정렬
컬렉션.stream().sorted(Comparator.reverseOrder()).forEach(n->System.out.println(n)); //내림차순
컬랙션.stream().sorted(Comparator.comparing(클래스::getter)).forEach(n->System.out.println(n)); //오름차순 정렬



연산 결과 확인

  • .peek() : 최종 연산 메서드가 아니고 중간 연산 메서드입니다. 다시 스트림을 반환합니다. 주로 중간 연산 디버깅용으로 많이 사용됩니다.
  • .forEach() : 최종 연산 메서드입니다. 스트림을 반환하지 않습니다.


매칭

Stream의 요소들이 특정한 조건을 만족하는지 확인하고 싶은 경우에 000match()메서드를 이용합니다. match()메서드는 크게 3가지가 존재합니다.

  • allMatch() : 모든 요소들이 매개값으로 주어진 조건을 만족하는 지 조사
  • anyMatch() : 한개 이상의 요소들이 매개값으로 주어진 조건을 만족하는 지 조사
  • noneMatch() : 모든 요소들이 매개값으로 주어진 조건을 만족하지 않는지 조사
package JAVA_Effective;

import java.util.Arrays;

public class MatchesExample {
    public static void main(String[] args) {
        int[] intArr = {2,4,6}; //배열
        boolean result = Arrays.stream(intArr).allMatch(a->a%2==0);//모든요소가 true인지
        System.out.println("모두 2의 배수 : " +result);

        result = Arrays.stream(intArr).anyMatch(a->a%3==0); //하나이상이 true인지
        System.out.println("한개이상 3의 배수 : " + result);

        result = Arrays.stream(intArr).noneMatch(a->a%3==0); //모두 false인지
        System.out.println("어떤것도 3의 배수 아님 : " + result);
    }
}
//Console
모두 2의 배수 : true
한개이상 3의 배수 : true
어떤것도 3의 배수 아님 : false


기본 집계

최종 연산 기능으로 주로 평소에 많이 사용하던 count(), sum(), average(), max(), min()등을 하나의 값으로 산출하는 것을 의미합니다.



Collect

stream의 요소들을 다른 종류의 결과로 수집하고 싶은 경우에 collect메서드를 이용할 수 있습니다. collect 메서드는 어떻게 stream의 요소들을 수집할 것인가를 정의한 Collector 타입의 인자로 받습니다.

package JAVA_Effective;

public class Student2 {
    public enum Gender {Male, Female};
    private String name;
    private int score;
    private Gender gender;

    public Student2(String name, int score, Gender gender) {
        this.name = name;
        this.score = score;
        this.gender = gender;
    }

    public Gender getGender(){
        return gender;
    }

    public String getName(){
        return name;
    }

    public int getScore(){
        return score;
    }
}
package JAVA_Effective;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class CollectExample {
    public static void main(String[] args) {
        List<Student2> totalList = Arrays.asList( //리스트 생성
                new Student2("김코딩", 10, Student2.Gender.Male),
                new Student2("김인기", 8, Student2.Gender.Male),
                new Student2("이자바", 9, Student2.Gender.Female),
                new Student2("최민선", 10, Student2.Gender.Female)
        );

        List<Student2> maleList = totalList.stream() //스트림 생성
                .filter(s -> s.getGender() == Student2.Gender.Male) //남자만 필터링
                .collect(Collectors.toList()); //리스트로 반환

        maleList.stream().forEach(n-> System.out.println(n.getName())); //출력

        Set<Student2> femaleSet = totalList.stream() //스트림 생성
                .filter(s -> s.getGender() == Student2.Gender.Female) //여자만 필터링
                .collect(Collectors.toCollection(HashSet::new));

        femaleSet.stream().forEach(n-> System.out.println(n.getName())); //출력
    }
}
//Console
김코딩
김인기
이자바
최민선



Optional<T>

연산 결과를 Optional에 담아서 반환하면, 따로 조건문을 작성해 주지 않아도 NPE가 발생하지 않도록 코드를 작성할 수 있습니다.

Optional 클래스는 모든 타입의 객체를 담을 수 있는 래퍼(Wrapper)클래스입니다.

public final class Optional<T>{
	private final T value; //T타입의 참조변수
}

Optional 객체를 생성하려면 of()ofNullable()메서드를 사용해서 생성합니다.

Optional<String> opt1 = Optional.ofNullable(null);
Optional<String> opt2 = Optional.ofNullable("123");
System.out.println(opt1.isPresent());
System.out.println(opt2.isPresent());

참조 변수의 기본값을 초기화하려면 empty()메서드를 호출합니다.

Optional<String> opt3 = Optional.<String>empty();
  • get() : 객체에 저장된 값을 가져옵니다.
  • orElse() : null일때 디폴트 값을 지정합니다.
Optional<String> optString = Optional.of("코딩자투리");
System.out.println(optString);
System.out.println(optString.get());

String nullName = null
String name = Optional.getNullable(nullName).orElse("코딩자투리");
System.out.println(name);



찾아 본것

(Class<?> InfoExample) //질문하기
InfoExample.getDeclaredFields(); //클래스의 필드 목록 반환

Field //클래스에 있는 변수들의 정보를 제공하기 위해 사용
Field.isAnnotationPresnent(에노테이션 타입) //특정 에노테이션 타입인지 확인
Field.getAnnotation(BackendFramework.class) //특정 에노테이션 타입이 있으면 해당 에노테이션 반환 없으면 null
IntBinaryOperator operator; //2개의 매개변수를 가지는 메서드 레퍼런스를 담는 변수
operator.applyAsInt(3,5) //메서드 실행



후기

알고리즘 문제를 푸는 싸이트에서 문제를 풀다보면 Collection을 사용하다가 int나 double 배열로 반환해야 하는 경우가 많다. 그럴때 마다 스트림을 사용하였지만 정작 스트림이 어떻게 동작하는지, 또 내부에서 람다식이 어떻게 동작하는지 모르고 썼었지만 오늘 제대로 알차게 알게 되어 너무 뿌듯하다.




GitHub

https://github.com/ds02168/CodeStates/tree/main/src/JAVA_Effective

profile
오늘도 내일도 화이팅!

0개의 댓글