람다 표현식,열거형,어노테이션

이영광·2022년 2월 9일

자바

목록 보기
12/34
  • 람다 : 자바 8이상에서 추가된 기능으로, 객체를 생성하지 않고 메소드를 수행하도록한다. 기본적으로 자바는 객체를 만든 후에 메소드를 호출해서 사용하는데, 람다는 그렇지 못해 객체 지향 개념에서 벗어난다고 이야기하는 사람들이 많다. 실제로 람다 표현식이 객체지향에서 맞는 표현이 아니라는 이유로 오라클에서 자바에 포함시켜야 하는지 오랜시간 고민했다고 한다.

  • 열거형 : 또한 유용한 자바 문법중 하나이며, 열거형은 상수 데이터가 여러개 필요할때 한번에 묶어서 관리할수 있다. 열거형이 언제 필요한지와 필요할 때 어떻게 사용할 수 있는지 알아보자.

  • 어노테이션은 부가적인 정보를 넣도록 하는 기능으로 코드의 가독성을 높일 수 있다.

람다 표현식(lambda expression)

람다 표현식은 나중에 한 번 이상 실행할 수 있도록 만들어 놓는 코드 블록이며, "이름없는 함수" 라고도 한다. 지금까지 모든 함수(메소드)는 반드시 이름을 가져야 했었는데 람다 표현식은 함수의 역할을 하지만 이름이 없다. 람다 표현식을 어떻게 작성하는지 알아보고, 다음으로 람다 표현식을 어떻게 사용하는지 알아보자

람다 표현식 만들기

람다 표현식의 형태는 다음과 같다. 기호 '->'는 람다 연산자라고 부르고 '->'왼쪽에는 함수의 매개변수를 적고 오른쪽에는 함수가 반환할 값 또는 식을 적어준다

자바 람다
(매개변수) -> {수행되어야 하는코드}
참고 js 람다
const test = () =>{}

함수표현식
int test(int x){ return x+ 1}

=>
람다표현식
(x) -> (x+1)

일반 함수를 람다 표현식으로 바꾼 예제

번호람다함수
1()->100int getValue(){return 100;}
2()->100.5double getValue(){return 100.5;}
3(n)->1.0/n or n->1.0/ndouble getValue(int n){return 1.0/n}
4(n)->(n%2) == 0 또는 n->(n%2)==0boolean getValue(int n){return (n%2) == 0;}
5(n,m)->(n*m) == 0int getValue(int n, int m){return n * m;}

'->' 기호 왼쪽에는 함수의 매개변수를 적고 오른쪽에는 함수가 반환하는 식을 적는다. 매개변수 1개인 경우에는 괄호 생략 할수 있다.

람다 표현식 사용하기

람다 표현식을 만들었으면 호출해서 사용해야 하는데, 인터페이스가 반드시 필요하다. 이때 인터페이스에 람다 표현식을 수행할수 수 있는 추상 메소드를 선언해야 한다. 이렇게 람다 표현식을 구현한 인터페이스는 함수형 인터페이스(functional interface)라고 부른다. 함수형 인터페이스에는 추상 메소드만 한개 있어야 한다.

함수형 인터페이스

interface MyValue(){
 double getValue()
}
매개변수 없음
double 데이터 반환함.



interface MyValue(){
 double getValue(double v);
}

매개 변수 1(v)
double 데이터 반환함.


interface NumericTest{
	
  boolean test(int n , int m);

}

매개변수 2 (n,m) boolean 데이터 반환

함수형 인터페이스를 적용하여 람다 표현식을 사용해보자

[예제1]

package lambdas;


interface MyValue1{
    int getValue();
}

public class Test1 {

    public static void main(String[] args){
        MyValue1 mv1; 
        mv1 = () -> 100;
        System.out.println(mv1.getValue());
    }
    
}

자바스크립트를 먼저 시작해서그런지 항상 비교하면서 하게되는데

인터페이스를 구현한 인스턴스를 함수화 해서 100을 리턴하게끔 만들고

인터페이스 안의 메소드로 구현한다.
mv1 은 결국 화살표함수의 명칭이 되는것인거 같다.

람다표현식의 순서

  1. 인터페이스만들기
  2. 인터페이스 참조 변수 만들기
  3. 인터페이스 참조 변수에 람다 표현식 할당하기
  4. 람다 표현식 수행시키기(지연처리)

MyValue1 mv1; 이것을 인터페이스 참조 변수라고 부른다.

[예제2]

package lambdas;

interface MyValue3{
    double getValue(int n);
}

public class Test3 {

    public static void main(String[] args){
        MyValue3 testThree;
        testThree  = (n) ->1.0/n;

        System.out.println(testThree.getValue(5));
    }
    
}
매개변수 가 들어가있는 인터페이스 람다

0.2

[예제3]

package lambdas;

interface MyValue4{
    boolean getValue(int n);//no parameter?
}

public class Test4 {

    public static void main(String[] args){
        MyValue4 test4s;

        test4s = (n) ->(n%2) == 0;//지연처리
        System.out.println(test4s.getValue(50));
        System.out.println(test4s.getValue(23));
    }
    
}
true
false

람다 표현식은 결국 함수 호출이다.

함수형 인터페이스와 람다 표현식을 좀 더 효율적으로 사용한 예제를 보자. 다음 예제에서는 함수형 인터페이스 Test 안에 test() 메소드 한개가 있다. test() 메소드는 정수형 매개변수 2개를 받아서 true or false 반환하고, 여기에 맞는 람다 표현식 2개가 있다

Test t1 = (n,d) -> (n%d) == 0;
Test t2 = (n,m) -> (n<m);

[예제4]

package lambdas;

interface Test{
    boolean test(int n , int m);
}

public class Test5 {

    public static void main(String[] args){
        Test t1 = (n,d) ->(n%d) == 0;

        if(t1.test(10,5)){
            System.out.println("5는 10의 인수이다");
        }
        if(!t1.test(10,3)){ //펄스이면 0으로 되지않을때
            System.out.println("3은 10의 인수가 아니다");
        }
        System.out.println();

        Test t2 = (n,m) -> (n<m);
        if(t2.test(3,5)){
            System.out.println("3 is less than5");
        }
        if(!t2.test(5,3)){
            System.out.println("5 is not less than 3");
        }
        System.out.println();
    }
    
}
510의 인수이다
310의 인수가 아니다

3 is less than5
5 is not less than 3

블록 람다 표현식

이번에는 좀더 긴 람다 표현식을 살펴보자

interface Test{
	int getSum(int n);
}

public static void main(String[] args){
	...내용
	}
System.out.println(t.getSum(10)); //지연처리
}

예제[5]

package lambdas;

interface Test66{
    int getSum(int n);
}

public class Test6 {

    public static void main(String[] args){

        Test66 t = (n) ->{
            int result = 0;
            for(int i = 1; i<=n ; i++){
                result += i;
            }
            return result;
        };
        System.out.println("sum from 1 to 10 is" + t.getSum(10));
        System.out.println("sum from 1 to 20 is" + t.getSum(20));
        System.out.println("sum from 1 to 30 is" + t.getSum(30)); 
    }
    
}
sum from 1 to 10 is55
sum from 1 to 20 is210
sum from 1 to 30 is465

블록람다 표현식은 반드시 중괄호로 묶꼬 마지막에 세미콜론을 붙이자

제네릭 함수형 인터페이스

제네릭 함수형 인터페이스는 하나의 람도 표현식에 다양한 자료형을 적용할 수 있게 해준다. 제네릭은 다양한 자료형을 사용할 수 있도록 하는 기능이다. 제네릭을 이용하면 함수 인터페이스에도 다양한 자료형을 적용할 수 있다.

package lambdas;

interface TestT<T>{
    boolean test(T n, T m);
}

public class Test7 {
    public static void main(String[] args){
        TestT<Integer> x = (s,d) -> s<d;

        if(x.test(3,5)){
            System.out.println("3 은 5보다 작다");
        }else{
            System.out.println("1231321");
        }

        TestT<String> z = (a,b) -> a.equals(b);

        String str = "Java";
        if(z.test(str,"Java")){
            System.out.println("same string");
        }else{
            System.out.println("different string");
        }
      
    }
}
35보다 작다
same string
TestT<Integer> 에서는 T 가 Integer 타입으로 적용되고, Test<String>에서는 T가 문자열로 적용됨을 알 수가 있다. 제네릭으 ㄹ이용하면 하나의 함수형 인터페이스를 다양한 자료형에 이용할 수 있다.

열거형

열거형은 여러 개의 상수 데이터를 선언하는데 유횽하다. 클래스 멤버 중에서 상수 데이터는 public static 데이터인데. 이를 한꺼번에 선언할 수 있도록 해준다.

enum Cards{
 a,b,c,d;
 1 2 3 4
}

다음과 같은 상수들의 모임

final int a = 0;
final int b = 1;
final int c = 2;
final int d = 3;
1.카드 정보를 저장한 열거형

enum Cards{
	HEART,CLUB,SPADE,DIAMONS
}

2.요일을 저장한 열거형

enum Weekdays{
 Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday;
}

3.대학교 학년 정보를 저장한 열거형

enum Years{
	Freshman, Sophomore, Junior, Senior;
}

예를 들어서, 카드를 이용한 프로그램을 작성하는 경우 네 장의 카드 'SPADE', 'HEART', 'CLUB', 'DIAMOND'를 데이터로 저장해서 사용해야 한다. 이때 카드 정보를 열거형으로 묶는다. 열거형의 키워드는 enum이다. 다음 예제를 통해 열거형으로 정의된 데이터를 살펴보자

package enums;


enum Cardee{
   
        HEART,CLUB,SPADE,DIAMOND;

}


public class Cards{

private static final Cardee SPADE = null;

public static void main(String[] args){
    Cardee cd = Cardee.DIAMOND;
    System.out.println("Value of cd ; " + cd);

    cd = Cardee.SPADE;
    if(cd == Cardee.SPADE) System.out.println("cd is SPADE");

    switch(cd){
        case HEART:
        System.out.println("Heart card");
        break;
        case CLUB:
        System.out.println("Club card");
        break;
        case SPADE:
        System.out.println("Spade card");
        break;
        case DIAMOND:
        System.out.println("Diamond card");
        break;
    }

}
}
Value of cd ; DIAMOND
cd is SPADE
Spade card
    Cardee cd;
    System.out.println("print out all cards");
    System.out.println("-------------------");
    Cardee all[] = Cardee.values();
    for(Cardee c: all) System.out. println(c);
    System.out.println("-------------------");
    cd= Cardee.valueOf("CLUB");
    System.out.println("cd == " + cd);


print out all cards
-------------------
HEART
CLUB
SPADE
DIAMOND
-------------------
cd == CLUB

values() , valueOf() ?

생성자를 갖고 있는 enum 타입을 보자

enum Cardee{
   
        // HEART,CLUB,SPADE,DIAMOND;
        HEART(10),CLUB(20),SPADE(30),DIAMOND(40);

        private int val;
        Cardee(int v){val =v;}
        int getVal(){return val;}

}

...

    System.out.println("Value of SPADE : " + Cardee.SPADE.getVal());
    System.out.println("-----------------------------------");
    System.out.println("All values of Cards");
    for(Cardee c : Cardee.values()) System.out.println(c+"value: " + c.getVal());

enum 의 상수에 벨류값을 입력해준걸 getValue()로 가져왔다.

final int HEART = 10;
final int CLUB = 20;
fianl int SPADE = 30;
final int DIAMOND = 40; 

과 마찬가지로 열거로 편하게 쓰이고 있다.

모든 enum은 java.lang.Enum 클래스를 상속받고 있으며, Enum 클래스의 ordinal() 메소드와 compareTO()메소드를 사용한 예제를 만들어보자

enum Cardee{
   
        HEART,CLUB,SPADE,DIAMOND;
   
}
...

    Cardee cd1,cd2,cd3;

    for(Cardee c : Cardee.values()) System.out.println(c + ": " + c.ordinal());

    cd1= Cardee.HEART;
    cd2= Cardee.SPADE;
    cd3= Cardee.HEART;

    if(cd1.compareTo(cd2) < 0){
        System.out.println("cd1 <cd2");
    }else{
        System.out.println("cd1>cd2");
    }
    
    if(cd1.compareTo(cd3)==0){
        System.out.println("cd1==cd3");

    }else{
        System.out.println("cd1 != cd3");
    }
profile
《REACT》《JAVASCRIPT 》 만지고있어욤

0개의 댓글