티스토리 뷰

Academy

[210219]제네릭

VIRGIL ABLOH 2021. 2. 25. 02:40
반응형

- 학습 목표 달성 확인 목록

- [] 제네릭 문법이 적용된 경우 인스턴스와 레퍼런스의 사용법을 이해하는가?

public class Member {
  String name;
  int age;

  public Member(String name, int age) {
    this.name = name;
    this.age = age;
  }

  @Override
  public String toString() {
    return "Member [name=" + name + ", age=" + age + "]";
  }
}
public class r {
    public static void main(String[] args) {
    //<>안에 객체를 넣어서 해당 객체만 삽입할 수 있게 해준다.
        ArrayList<Member> list = new ArrayList<//Member *생략 가능//>();
        list.add(new Member("오은석", 29));//Member객체만 넣을 수 있다.
        list.add(new Member("이중섭", 41));
        list.add(new Member("이순신", 44));

        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }
}

 

- [] 제네릭의 wildcard(?) 문법을 사용할 수 있는가?

ArrayList<?> list1;//해당 List를 타입상관없이 다루고 싶다면 <?>로 선언하면!
        list1 = new ArrayList<>();
        list1 = new ArrayList<Object>();//슈퍼 클래스도 넣을 수 있고
        list1 = new ArrayList<String>();//서브 클래스들도 넣을 수 있다
        list1 = new ArrayList<Integer>();
        list1 = new ArrayList<Member>();

        //단 이경우에는 제네릭의 타입이 명확하게 선언되지 않았기 때문에 제네릭 검사가 필요한 코드를 컴파일 불가하다
//        list1.add(new String("오은석"));//컴파일 불가

 

- [] wildcard 문법에서 extends와 super 차이점을 이해하는가?

<? extends 상위타입>:상위 클래스 제한

매개변수의 자료형을 특정 클래스를 상속받은 클래스로만 제한한다.

class Person {
    String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}

class Man extends Person {
    // 생성자
    Man(String name) {
        super(name);
    }

    @Override
    public String toString() {
        return "Man{" +
                "name='" + name + '\'' +
                '}';
    }
}

class Woman extends Person {
    Woman(String name) {
        super(name);
    }

    @Override
    public String toString() {
        return "Woman{" +
                "name='" + name + '\'' +
                '}';
    }
}

public class sam {
    public static void main(String[] args) {
        ArrayList<Person> list1 = new ArrayList<>();
        list1.add(new Person("아인슈타인"));
        printData(list1);

        System.out.println("------------------");

        ArrayList<Man> list2 = new ArrayList<>();
        list2.add(new Man("게이브 뉴웰"));
        printData(list2);

        System.out.println("------------------");

        ArrayList<Woman> list3 = new ArrayList<>();
        list3.add(new Woman("퀴리 부인"));
        printData(list3);
    }

    //Person 클래스와 그 하위 클래소 생성된 인스턴스만 매개변수로 전달 가능하다
    public static void printData(ArrayList<? extends Person> list) {
        for (Person p : list) {
            System.out.println(p);
        }
    }
}

//결과
Person{name='아인슈타인'}
------------------
Man{name='게이브 뉴웰'}
------------------
Woman{name='퀴리 부인'}

<? super 하위타입>:하위 클래스 제한

매개변수의 자료형을 특정 클래스와 그 클래스의 상위 클래스로만 제한한다.

class Person_1 {
    String name;

    public Person_1(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person_1{" +
                "name='" + name + '\'' +
                '}';
    }
}

class Man_1 extends Person_1 {

    public Man_1(String name) {
        super(name);
    }

    @Override
    public String toString() {
        return "Man_1{" +
                "name='" + name + '\'' +
                '}';
    }
}

class Woman_1 extends Person_1 {

    public Woman_1(String name) {
        super(name);
    }

    @Override
    public String toString() {
        return "Woman_1{" +
                "name='" + name + '\'' +
                '}';
    }
}

public class sam111 {
    public static void main(String[] args) {
        ArrayList<Person_1> list1 = new ArrayList<>();
        list1.add(new Person_1("인류"));
        printData(list1);

        System.out.println("------------------");

        ArrayList<Man_1> list2 = new ArrayList<>();
        list2.add(new Man_1("오펜하이머"));
        printData(list2);

        System.out.println("------------------");

        ArrayList<Woman_1> list3 = new ArrayList<>();
        list3.add(new Woman_1("빅토리아"));
//        printData(list3);//Man 클래스의 사우이 클래스가 아니기때문에 메소드 호출 불가
    }

    //Person 클래스와 그 하위 클래소 생성된 인스턴스만 매개변수로 전달 가능하다
    public static void printData(ArrayList<? super Man_1> list) {
        for (Object o : list) {
            System.out.println(o);
        }
    }
}

//결과
Person_1{name='인류'}
------------------
Man_1{name='오펜하이머'}
------------------

 

- [] 'funtional interface' 를 설명할 수 있는가?

추상 메서드가 한 개 있는 인터페이스를 'funtional interface'라고 부른다.

interface MP3 {
    void playMusic();
  }

 

- [] 람다(lambda) 문법을 사용할 수 있는가?

public class test {
    public interface MP3 {//1.먼저 인터페이스를 만든다
        void playMusic();//2.단 한개의 추상 매서드만 선언한다
    }

    public static void main(String[] args) {
        MP3 mp3 = new MP3() {//3.익명 클래스로 인터페이스를 구현한다
            @Override
            public void playMusic() {
                System.out.println("익명 클래스로 생성된 MP3이다.");
            }
        };
        mp3.playMusic();
        //여기서 람다문법으로 바꿔준다
        /*
        4.이렇게된 구간은 삭제한다
         */
        MP3 mp31 = /*new MP3*/ () -> {
            /*@Override
            public void playMusic() */{
                System.out.println("익명 클래스를 람다 문법으로 바꿔준 MP3이다.");
            }
        };//5.새미콜론 필수
        mp31.playMusic();

        //람다 완성
        //매서드 한 개짜리 인터페이스를 구현한 익명 클래스를 좀 더 간단히 표현하기 위해 만든 문법이다
        //즉 뻔한 코드를 생략하는 것이다
        MP3 mp311 =() -> { System.out.println("익명 클래스를 람다 문법으로 바꿔준 MP3이다.");};//새미콜론 필수
        mp311.playMusic();
        /*
        람다와 .class 파일
        람다는 해당 클래스의 멤버 메서드로 정의된다
        즉 별도의 .class 파일을 생성하지 않는다
        람다 문법이 초기에 등장했을 때는 익명 클래스로 변환되었다.
        하지만 최근에는 그냥 멤버 메서드로 변환된다.

        ->람다를 호출하는 코드는 자동 생성된 메서드를 호출하는 코드로 변환된다
         */
    }
}
public class test {
    public interface PMP {
        void PlayMovie(String fileName);
    }

    public static void main(String[] args) {
        PMP pmp = new PMP() {//인터페이스 구현
            @Override
            public void PlayMovie(String fileName) {
                System.out.println(fileName + "영화 시청중...");
            }
        };

        //1.파라미터는 괄호() 안에 선언한다
        PMP pmp1 = (String fileName) ->System.out.println(fileName + "영화 시청중...");
        
        pmp1.PlayMovie("터미네이터2");

        System.out.println("===============================");

        //2.파라미터 타입을 생략할 수 있다
        PMP pmp2 = (fileName) ->System.out.println(fileName + "영화 시청중...");
        
        pmp2.PlayMovie("백투더 퓨쳐2");

        System.out.println("===============================");

        //2.파라미터가 한 개일 때는 괄호도 생략할 수 있다
        PMP pmp3 = fileName -> System.out.println(fileName + "영화 시청중...");
        
        pmp3.PlayMovie("캐치미 이프 유캔");

        System.out.println("===============================");
    }
}
public class test_02 {
    public interface IPAD {
        void use(String gameName, double version);
    }

    public static void main(String[] args) {
       IPAD ipad = new IPAD() {//1.인터페이스 구현
           @Override
           public void use(String gameName, double version) {
               System.out.printf("%s %.1f version 게임을 하고있습니다.\n", gameName, version);
           }
       };
        ipad.use("앵그리버드", 2.5);
        System.out.println("===============================");

        //1.파라미터는 괄호() 안에 선언한다
        IPAD ipad1 = (String gameName, double version) -> System.out.printf("%s %.1f version 게임을 하고있습니다.\n", gameName, version);

        ipad.use("모두의 마블", 5.0);
        System.out.println("===============================");

        //2.파라미터 타입을 생략할 수 있다
        IPAD ipad2 = (gameName, version) -> System.out.printf("%s %.1f version 게임을 하고있습니다.\n", gameName, version);

        ipad.use("리니지", 3.1);
        System.out.println("===============================");

        //3.파라미터가 여러 개일 때는 괄호를 생략할 수 없다
//        IPAD ipad3 = gameName, version -> System.out.printf("%s %d.version 게임을 하고있습니다.", gameName, version);

    }
}

 

- [] 로컬 클래스를 익명 클래스로 바꿀 수 있는가?

public class test_03 {
    static interface Player {
        void play();
    }

    static void testPlayer(Player player) {
        player.play();
    }

    public static void main(String[] args) {
        //로컬 클래스
        class MyPlayer implements Player {
            @Override
            public void play() {
                System.out.println("플레이!");
            }
        }
        MyPlayer myPlayer = new MyPlayer();

        testPlayer(myPlayer);

        //위의 로컬 클래스를 익명클래스로 바꾼다
       testPlayer(() -> System.out.println("플레이!"));
    }
}

 

- [] 익명 클래스를 람다 코드로 바꿀 수 있는가?

public class test_04 {
    static interface Calculator {
        int compute(int a, int b);
    }

    static void test(Calculator c) {
        System.out.println(c.compute(100, 200));
    }

    public static void main(String[] args) {
        test(new Calculator() {
            @Override
            public int compute(int a, int b) {
                return a + b;
            }
        });

        //위의 익명클래스를 람다로 바꿀수 있다
        test((a, b) -> a + b);
    }
}

 

- [] 스태틱 메서드를 '메서드 레퍼런스'로 활용할 수 있는가?

public class test {
    static class MyCalculator {
        public static int plus(int a, int b) {
            return a + b;
        }
        public static int minus(int a, int b) {
            return a - b;
        }
        public static int multiple(int a, int b) {
            return a * b;
        }
        public static int divide(int a, int b) {
            return a / b;
        }

        interface Calculator {
            int compute(int x, int y);
        }

        public static void main(String[] args) {
            /*
            메서드 한 개짜리 인터페이스의 구현체를 만들 때
            기존 스태틱 메서드를 람다 구현체로 사용할 수 있다
            단 인터페이스에 선언된 메서드의 규격과 일치해야 한다
            규격?파라미터 타입 및 개수,리턴 타입
            문법:
            클래스명.메서드명
             */
            Calculator c1 = MyCalculator::plus;
            Calculator c2 = MyCalculator::minus;
            Calculator c3 = MyCalculator::multiple;
            Calculator c4 = MyCalculator::divide;

            System.out.println(c1.compute(200,17));
            System.out.println(c2.compute(200,17));
            System.out.println(c3.compute(200,17));
            System.out.println(c4.compute(200,17));
        }
    }
}

//결과
217
183
3400
11
//상위의 코드의 내부는 다음과 같다
Calculator cc = new Calculator() {
                @Override
                public int compute(int x, int y) {
                    return MyCalculator.plus(x, y);
                }
            };
            System.out.println(cc.compute(200, 17));

- [] 인스턴스 메서드를 '메서드 레퍼런스'로 활용할 수 있는가?

public class test_05 {
    static class Calculator {
        double rate;

        public Calculator(double rate) {
            this.rate = rate;
        }

        public double year(int money) {
            return money * rate / 100;
        }

        public double month(int money) {
            return money * rate / 100 / 12;
        }

        public double day(int moeny) {
            return moeny * rate / 100 / 365;
        }
    }

    static interface Interest {
        double compute(int money);
    }

    public static void main(String[] args) {
        Calculator 보통예금 = new Calculator(0.5);
        Calculator 정기예금 = new Calculator(1.5);
        Calculator 청년행복예금 = new Calculator(10);

        System.out.println("보통예금");
        Interest i1 = 보통예금::year;

        //코드의 내부
//        Interest i1 = new Interest() {
//            @Override
//            public double compute(int money) {
//                return 보통예금.year(money);
//            }
//        };
        System.out.printf("년 이자: %.1f\n", i1.compute(10_0000_0000));

        i1 = 보통예금::month;
        System.out.printf("월 이자: %.1f\n", i1.compute(10_0000_0000));

        i1 = 보통예금::day;
        System.out.printf("일 이자: %.1f\n", i1.compute(10_0000_0000));

        System.out.println("------------------------------");

        System.out.println("정기예금");
        Interest i2 = 정기예금::year;
        System.out.printf("년 이자: %.1f\n", i1.compute(10_0000_0000));

        i2 = 정기예금::month;
        System.out.printf("월 이자: %.1f\n", i1.compute(10_0000_0000));

        i2 = 정기예금::day;
        System.out.printf("일 이자: %.1f\n", i1.compute(10_0000_0000));
    }
}

 

- [] 생성자를 '메서드 레퍼런스'로 활용할 수 있는가?

public class test_06 {

    static class Message {
        String name;
        int age;

        public Message() {
            this.name = "이름없음";
        }

        public Message(String name) {
            this.name = name;
        }

        public Message(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public static void print(Message message) {
            if (message.name.equals("이름없음")) {
                System.out.println("이름없음");
            } else {
                System.out.printf("%s님 반갑습니다.\n", message.name);
            }
        }
    }

    static interface Factory1 {
        Message get();
    }

    static interface Factory2 {
        Message get(String name);
    }

    static interface Factory3 {
        Message get(String name, int age);
    }

    public static void main(String[] args) {
        Factory1 f1 = Message::new;//public Message() 생성자
        Message.print(f1.get());
        
        Factory2 f2 = Message::new;//public Message(String name) 생성자
        Message.print(f2.get("고든 프리맨"));

        Factory3 f3 = Message::new;//public Message(String name, int age) 생성자
        Message.print(f3.get("G맨", 100));
    }
}

 

- [] List의 forEach() 메서드를 활용하여 목록을 조회할 수 있는가?

public class test_07 {
    public static void main(String[] args) {
        ArrayList<String> names = new ArrayList<>();
        names.add("브루스웨인");
        names.add("조커");
        names.add("제임스고든");
        names.add("하비덴트");
        names.add("알프레드");

        //forEach() 사용 전
//        for (String name : names) {
//            System.out.println(name);
//        }

        //forEach() 사용 후
        class MyConsumer<T> implements Consumer<T> {
            @Override
            public void accept(T t) {
                System.out.println(t);
            }
        }
        names.forEach(new MyConsumer<String>());
    }
}

 

 

반응형

'Academy' 카테고리의 다른 글

[210224]File I/O API  (0) 2021.03.01
[210222]예외  (0) 2021.02.28
[210218]Command Design Pattern  (0) 2021.02.24
[210217]자바 API  (0) 2021.02.24
[210216]제네릭  (0) 2021.02.23
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2026/06   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함