하루가 지나면 지날수록 성장하는 느낌이다.
성격상 주변을 크게 의식한는 편은 아니지만
조금 더 빨리 공부를 시작했으면 좋았을 것 같다는
생각들이 든다.

몰라도 할 수 있다 생각하고
긍정의 마음가짐으로 오늘 하루도 시작!

image


어제는 자바의 컬렉션 프레임워크인
List, Set 그리고 Map에 대해 복습하는 시간을 가졌었다.
여러가지 문제를 풀면서 사용방법을 익혀보는!
유용한 시간이였다.

오늘은 어노테이션과 람다 문법
스트림, 파일의 입출력을 공부 해볼 예정이다.
위의 이름은 다 들어본적있고
두루뭉술하게 본적이 있어 어떤 느낌인지는 알 것 같다
정확한 개념을 다지기위해 공부해보자

Annotation

영어로 직역하면 주석이라는 뜻을 가진다.
우리는 코딩옆에 사람이 인지하기 쉽게 주석을 달아둔다.
애너테이션은 사람의 이해를 돕기 위한 주석과는 다르게
다른 프로그램에게 유용한 정보를 제공하기 위해 만들어졌다.

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

애너테이션의 종류는
표준 , 메타, 사용자 이렇게 크게 3가지로 나뉜다.
오늘은 표준과 메타에대해서만 공부해보려한다.
간단한 예시를 들어보자.

class man{
    int age;
    void name(){}
}
class babo extends man{
    @Override
    void name(){
        System.out.println("2");
    }
}

@Override라는 애너테이션이 있다.
name이라는 매서드를 오버라이드한다고 애너테이션이 붙어있다.
만약 babo라는 클래스 본문에 실수로 오타로 nema라고
적었을 경우 애너테이션이 붙어있기때문에
틀렸다고 아래의 사진처럼 알려준다.

image

그리고 실행시킬경우

error: method does not override or implement a method from a supertype
컴파일 에러가 발생하는 것을 볼 수있다.

만약에 애너테이션이 없을 경우에는 그냥 다른 메서드가 만들어진 것이다.

표준 애너테이션

표준 애너테이션은 자바에서 기본적으로 제공해주는 애너테이션이다.

종류 설명
@Override 컴파일러에게 메서드를 오버라이딩하는 것이라고 알림
@Deprecated 앞으로 사용하지 않을 대상을 알릴 때 사용
@FunctionalInterface 함수형 인터페이스라는 것을 알림
@SuppressWarning 컴파일러가 경고메세지를 나타내지 않음

메타 애너테이션

애너테이션에 붙이는 애너테이션이다.
애너테이션 정의하는 데에 사용한다.

종류 설명
@Target 애너테이션을 정의할 때 적용 대상을 지정하는데 사용한다.
@Documented 애너테이션 정보를 javadoc으로 작성된 문서에 포함시킨다.
@Inherited 애너테이션이 하위 클래스에 상속되도록 한다.
@Retention 애너테이션이 유지되는 기간을 정하는데 사용한다.
@Repeatable 애너테이션을 반복해서 적용할 수 있게 한다.

Lamda

람다식은 함수형 프로그래밍 기법을 지원하는 자바의 문법요소이다.
JDK 1.8이후 람다식 등 함수형 프로그래밍 문법 요소를 도입했다.

즉, 함수형 인터페이스를 구현한 객체이다.
함수형 인터페이스의 추상 메서드를 람다식으로 구현
인터페이스를 상속받은 클래스를 명시적으로 작성하지 않고 익명의 클래스가 만들어지는 방식

*함수형 인터페이스 : 추상 메서드 하나만 있는 인터페이스.

image

기본문법

  1. 반환타입과 메서드 이름을 생략할 수 있다. ex) int test() = ()
  2. return문과 뒤에오는 세미콜론(;) 생략할 수 있다. ex) () -> {x+y};
  3. 실행문이 하나일 경우에 중괄호를 생략할 수 있다. ex) () -> x+y;
  4. 매개변수가 하나일때 소괄호도 생략이 가능하다. ex) (x) -> 에서 x -> / (x, y) -> 소괄호 생략불가

많이 쓰는 함수형 인터페이스를 자바에서 따로 모아두었다.
자바8 에서 지원하는 함수형 인터페이스 API 문서이다.

Stream

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

Collection 인터페이스에는 stream()이 정의 되어있기 때문에
Collection 인터페이스를 구현한 객체들 (List,Set 등)은 모두 이 메서드를 이용해
스트림을 생성할 수 있다.

*List로부터 스트림을 생성하는 방법

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

*배열로부터 스트림을 생성하는 방법

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); //end 범위 미포함

여기서 스트림을 사용할 때 주의점은
1. 데이터 소스로 부터 데이터를 읽기만 하고 변경하지 않는다.
2. 일회용이다. 한번 만사용하면 닫히므로, 필요하다면 새로운 스트림을 만들어야한다.

파이프라인 구성(.)

image

우리는 Stream을 크게 3가지로 나눈다.

image

1. 오리지날 스트림
2. 중간 연산 스트림
3. 최종 연산 스트림

오리지날 스트림은 처음에 데이터가 생성되는 부분을 가르킨다.
그리고 중간 연산 스트림으로 가공한후
최종 연산 스트림으로 리턴하게 된다.

최종연산을 원하는 형태에 맞게 가공한 값을 반환하게되면
그 값으로 데이터를 추출해 활용할 수 도 있고
여러가지 응용이 가능해진다.
몇 가지 예제를 보면서 익숙해져보자

public static void main(String[] args) {
    List<String> name = Arrays.asList("이재혁","염승호","정용원","이종건","이재혁");
    System.out.println("List: "+name);

    //1번 : 리스트객체를 바로 스트림으로 사용.
    System.out.println("--------1번: 리스트객체를 바로사용--------");
    name.stream()
            .distinct()
            .forEach(s -> System.out.println(s));


    //2번 : 스트림 객체로 순환
    System.out.println("--------2번: 스트림 객체로 변환 후 사용--------");
    Stream<String> nameStream = name.stream(); // List 를 스트림 타입으로 변환한 객체
    nameStream
            .distinct() // 중복제거
            .forEach(s -> System.out.println(s));
}

중간 연산자로 .distinct()를 사용하고 있다.
이 연산자는 중복된 요소를 제거해 리턴해준다.
이제 그 리턴된값으로 최종 연산자인 .forEach문으로
요소를 출력해주는 프로그램이다.

1번과 2번 예제는 각각 Stream을 어떻게 객체를 만들어 쓰느냐를 나눈것이다.
더 자세한 stream에 대한 구현체들은
아래 자바 공식 문서에서 공부해보자.
내일 문제풀이하면서 사용해본 메서드들을 정리해볼 생각이다.

Stream (Java SE 11 & JDK 11 )

Optional

옵셔널은 NPE(NullPointerException)을 방지하고자 만들어진
Wrapper 클래스다. (모든 타입의 객체를 담을수있다)
간단한 예제를 보자.

Optional<String> optString = Optional.of("이재혁");
System.out.println(optString); //출력: Optional[고양이]
System.out.println(optString.get());//출력: 이재혁

String nullName = null;
String name = Optional.ofNullable(nullName).orElse("이재혁");
System.out.println(name); //출력: 이재혁

Optional의 String타입으로 “이재혁”이라는 요소를 추가한 객체를 만들었다.
객체를 바로 프린트할 경우 = Optional[이재혁] 이렇게 출력된다.
이 외에도 .get() 으로 요소만 뽑아올 수 있으며

객체 추가 메소드 : of , ofNullable
객체 비우기 : .empty();

등 여러가지 메소드들로 Optional로 데이터를 가공할 수 있다.
더많은 메소드들은 아래의 공식 문서를 참조해보자

Optional (Java Platform SE 8 )

파일의 입출력(I/O)

자바에서 입출력을 다루기위해
InputStream, OutputStream을 제공해준다.

스트림은 단방향으로만 데이터를 전송할 수 있어,
입력과 출력을 동시에 처리하기 위해선 각각의 스트림이 필요하다.
어떤 대상을 다루냐에 따라 종류가 나눠진다.

FIle : FileInputStream , FileOutputStream
Process : PipedInputStream, PipedOutputSteam
FileInputStream, FileOutputStream 둘다

1byte 입출력단위를 가지고 있다.
FileReader, FileWriter는 문자 데이터를 다룰떄 사용하고
문자 기반 스트림과 하위 클래스는 여러 종류의 인코딩과
자바에서 오니코드간의 변환을 자동으로 처리해준다.


마치며…

오늘은 정리가 조금 부실하다..
따로 정리할 것도 너무많고 (문법 사용법 정리중)
조금 자세한 내용들은 TIL에 천천히 적어보려한다.

stream… lamda….
하루만에 이해하려는게 욕심인 것 같다.
대략의 느낌은 알았다.

첫번째로 어려웠던점은 타입변환에 있어서
내가 자유롭지 못하다.
예를들어 List타입을 stream으로 변환해서
데이터를 가공해서 원하는 타입으로 뱉어주고싶은데
그 부분에서 알고있는 메서드 수도 적고
익숙하지 않으니 머리속이 복잡해지는 느낌이다….
최대한 내가아는방향으로 정리를 열심히해서
얼른 정복을 하고싶은 욕구가 솟아난다.

오늘은 첫날이니 찍먹했다치고 두고보자 스트림,,람다,,


오늘의 커피량: ☕️ ☕️ ☕️ ☕️️️️
오늘의 점심: 미역국, 스크럼블에그, 전, 공기밥