Sparta/What I Learned

22.12.1

코딩하는 또롱이 2022. 12. 2. 02:17
더보기

<우연희 튜터님의 특강 1일차에 알려주셨던 (어제) 책들>

이펙티브 자바 3E.
스프링 입문을 위한 자바 객체지향의 원리와 이해
클린 코드

<김승민 튜터님의 우리 특별 강의! 저녁시간 내내 열강해주셔서 덕분에 얻어가는 것들이 많았음!)
쓰리티어 : 프리젠테이션(UI)-어플리케이션(Logic) -디비(data 저장, 조회)
레이어드 아키텍쳐

패키지로 만드는 순간 에러투성이일것이다
함수명 중요, public 붙이는거 중요(접근제어자)

static : 여러개의 accounts 생성 막아줌 모든 객체가 같은 accounts를 공유할 수 있게


*bankservice class 생성(튜터님 임의)
 Facade 패턴 (컨트롤 타워같은 느낌)
- Logic처리 :  Bank
- DB 저장 : AccountRepository 의 객체 사용

//
멀티스레드?

//
Entity ; private String id; 가 있음

VO = value Object = 불변객체 = 변하지않는다 = setter 없음 = 객체를 신뢰할 수 있음 = final로만 선언!


boolean 안좋다

자바 QUIZ
객체 지향에서 배운 개념과 문법을 이용해서 다음 요구 조건을 만족하는 클래스를 작성하시오.

Q) 다음 요구사항을 만족하는 클래스들을 바탕으로, Main 함수를 다음 동작을 출력(System.out.println)하며 실행하도록 작성하시오. 이동하는 동작은 각자 순서가 맞아야 한다.

<요구사항>
사람은 자식, 부모님, 조부모님이 있다.
모든 사람은 이름, 나이, 현재 장소정보(x,y좌표)가 있다.
모든 사람은 걸을 수 있다. 장소(x, y좌표)로 이동한다.
자식과 부모님은 뛸 수 있다. 장소(x, y좌표)로 이동한다.
조부모님의 기본속도는 1, 부모의 기본속도는 3, 자식의 기본속도는 5이다.
뛸 때는 속도가 기본속도대비 +2 빠르다.
수영할 때는 속도가 기본속도대비 +1 빠르다.
자식만 수영을 할 수 있다. 장소(x, y좌표)로 이동한다.

<Main  출력>
모든 종류의 사람의 인스턴스는 1개씩 생성한다.
모든 사람의 처음 위치는 x,y 좌표가 (0,0)이다.
모든 사람의 이름, 나이, 속도, 현재위치를 확인한다.
걸을 수 있는 모든 사람이 (1, 1) 위치로 걷는다.
뛸 수 있는 모든 사람은 (2,2) 위치로 뛰어간다.
수영할 수 있는 모든 사람은 (3, -1)위치로 수영해서 간다.

[Human.java]

더보기

public class Human {
    String name;
    int age;
    int speed;
    int x, y;

    public Human(String name, int age, int speed, int x, int y) {
        this.name = name;
        this.age = age;
        this.speed = speed;
        this.x = x;
        this.y = y;
    }

    public Human(String name, int age, int speed) {
        this(name, age, speed, 0, 0);
    }

    public String getLocation() {
        return "(" + x + ", " + y + ")";
    }
    protected void printWhoAmI() {
        System.out.println("My name is " + name + ". " + age + " aged.");
    }
}

[Walkable.java]

더보기

public interface Walkable {
    void walk(int x, int y);
}

[Runnable.java]

더보기

public interface Runnable {
    void run(int x, int y);
}

[Swimmable.java]

더보기

public interface Swimmable {
    void swim(int x, int y);
}

[GrandParent.java]

더보기

public class GrandParent extends Human implements Walkable {
    public GrandParent(String name, int age) {
        super(name, age, 1);
    }

    @Override
    public void walk(int x, int y) {
        printWhoAmI();
        System.out.println("walk speed: " + speed);
        this.x = x;
        this.y = y;
        System.out.println("Walked to " + getLocation());
    }
}

[Parent.java]

더보기

public class Parent extends Human implements Walkable, Runnable{
    public Parent(String name, int age) {
        super(name, age, 3);
    }

    @Override
    public void run(int x, int y) {
        printWhoAmI();
        System.out.println("run speed: " + (speed + 2));
        this.x = x;
        this.y = y;
        System.out.println("Ran to " + getLocation());
    }

    @Override
    public void walk(int x, int y) {
        printWhoAmI();
        System.out.println("walk speed: " + speed);
        this.x = x;
        this.y = y;
        System.out.println("Walked to " + getLocation());
    }
}

[Child.java]

더보기

public class Child extends Human implements Walkable, Runnable, Swimmable{
    public Child(String name, int age) {
        super(name, age, 5);
    }

    @Override
    public void swim(int x, int y) {
        printWhoAmI();
        System.out.println("swimming speed: " + (speed + 1));
        this.x = x;
        this.y = y;
        System.out.println("Swum to " + getLocation());
    }

    @Override
    public void run(int x, int y) {
        printWhoAmI();
        System.out.println("run speed: " + (speed + +2));
        this.x = x;
        this.y = y;
        System.out.println("Ran to " + getLocation());
    }

    @Override
    public void walk(int x, int y) {
        printWhoAmI();
        System.out.println("walk speed: " + speed);
        this.x = x;
        this.y = y;
        System.out.println("Walked to " + getLocation());
    }
}

[Main.java]

더보기

public class Main {
    public static void main(String[] args) {
        Human grandParent = new GrandParent("할아버지", 70);
        Human parent = new Parent("엄마", 50);
        Human child = new Child("나", 20);

        Human[] humans = { grandParent, parent, child };
        for (Human human : humans) {
            System.out.println(human.name + ", 나이: " + human.age + ", 속도: " + human.speed + ", 장소: " + human
                    .getLocation());
        }
        System.out.println("<활동 시작>");
        for (Human human : humans) {
            if (human instanceof Walkable) {
                ((Walkable) human).walk(1, 1);
                System.out.println(" - - - - - - ");
            }
            if (human instanceof Runnable) {
                ((Runnable) human).run(2, 2);
                System.out.println(" - - - - - - ");
            }
            if (human instanceof Swimmable) {
                ((Swimmable) human).swim(3, -1);
                System.out.println(" - - - - - - ");
            }
        }
    }
}

 


특강 2일차
❣️ 인터페이스

인터페이스를 기준으로 앞, 뒤의 개발 코드가 서로 통신하는 접점. 앞, 뒤의 통신 규약 → 동시 개발 가능.

 

interface Practice {
       // 상수
	  (final/static : 지우라고뜸) 타입 상수명(대문자 convention) = 값;
       String HI = "Hi~";

       // 추상 메서드
       List<String> findAllName();

       // Default 메소드
       default 타입 메소드명(파라미터,...) {...}
       default void printHi() {
           System.out.println(HI);
       }

       // static 메소드
       static void printHi() {
           System.out.println(HI);
       }
   }
  • 상수타입으로 선언 했을 때 클래스 로드 시점에서 초기화 된다! 즉 public static final이 컴파일 때 자동으로 붙는다.
  • 추상 메서드로 구현체에게 강제로 구현시킨다.
  • 기본 메서드 제공
    • 자바는 단일 상속, 인터페이스는 다중 구현이 가능하다. → 충돌나는 메서드 시그니처는 오버라이딩강제한다.
    • 오버라이딩 가능.
    • 기본 public . 생략시 컴파일 과정에서 붙음
  • static 메소드 → 헬퍼 또는 유틸리티 메소드를 제공할 때 사용
    • static 블록 작성 불가.
  • 다형성을 구현하는 기술
    • 상속 또는 인터페이스의 자동 타입 변환(Promotion)
    • Promotion Memory 구조
      인터페이스 변수 = 구현객체; ← 자동 타입 변환
      Interface class = new InterfaceImplementClass();
      상위 인터페이스, 클래스, 추상 클래스로 Upcasting 가능
      모든 클래스는 extends Object 생략
       모든 클래스는 Object로 Upcasting 가능
    • Dynamic Dispatch 동작
      자바는 Promotion으로 Upcasting된 객체의 메소드를 런타임 시점에서 오버라이딩된 메소드에 대한 호출이 확인된다.
      → Dynamic Method Dispatch
      → 실시간 다형성
더보기
Promotion Memory 구조
매커니즘 이해

 

 

 

함수형 인터페이스와 람다 표현식
❣️함수형 인터페이스
  1. 추상 메서드를 하나만 가지고있는 인터페이스
  2. @FuntionalInterface 애노테이션을 인터페이스에 선언하면 컴파일 시점에서 추상 메서드를 하나만 갖는지 체크해 준다.
@FunctionalInterface
public interface Sum {
    int intSum(int x, int y);
}
❣️ 람다 표현식

익명 객체.메소드를 하나의 식으로 표현한 것.

int sum(int x, int y) {
    return x + y;
}

이러한 코드를

(x, y) -> x + y;

이렇게 표현한 것을 람다 표현식이라고 한다.

 

ex)

...

 @FunctionalInterface
 public interface Sum {
     int intSum(int x, int y);
 }

이와 같은 정규 코드(?)를 아래처럼 바꾼 게 람다!

...
 import ...Sum;

 public class Main {
     Sum sum = (a, b) -> a + b;

 System.out.println(sum.intSum(1, 2));
 }

 

 

스트림

배열이나 컬렉션에 담긴 데이터를 다룰 때, 반복문이나, iterator를 사용하면 코드가 길어지고, 가독성이 떨어진다.

이 문제를 해결하기위해 Stream API가 등장! 빠밤~

 

 ▶️ 특징

  • 스트림은 데이터를 변경하지 않는다.
  • 스트림은 재사용이 불가. → 최종 연산이 실행된 후 재사용 불가.

▶️스트림 파이프라인

  • 0 ~ N 개의 중개 연산과 1개의 종료 연산으로 구성.

▶️중개 연산

  • Stream을 리턴한다.

▶️종료 연산

  • Stream을 리턴하지 않는다

▶️대표 스트림 연습

  • 중개 연산자
  • 필터링 : filter , distinct
  • 변환 : map , flatMap
  • 제한 : limit , skip
  • 정렬 : sorted
  • 최종 연산
  • 요소 출력 : forEach
  • 요소 검색 : findFirst, findAny
  • 요소 통계 : count, min, max
  • 요소 연산 : sum, average
  • 요소 수집 : collect
  1.  

 

 

 

Optional

NPE(Null Pointer Exception) 예외를 Optional이 제공하는 메소드로 간단하게 회피할 수 있다.

 

 

⚠️ 잘못 사용하면 오히려 코드가 오히려 지저분해지고, 의미 없는 동작, Side-Effect 유발이 많이 발생할 수 있음.

→ NPE는 물론 NoSuchElementException이 발생
→ 잘못된 Optional 사용으로 새로운 문제들이 발생
→ 코드의 가독성을 파괴
→ 시간, 공간적 비용이 증가함

⚠️  null을 반환하면 오류가 발생할 가능성이 매우 높은 경우에 쓴다.

즉, “결과 없음”을 명확하기 드러내기 위해 메소드의 반환 타입으로 사용되도록 매우 제한적인 경우로 설계됨.
- Java 언어 아키텍트 Brian Goetz

 Optional은 메소드 반환 타입으로만 사용해야한다.

 

▶️ Optional의 객체 꺼내는 방법

Optional<String> opt = Optional.ofNullable("Optional은 Wrapper Class");
System.out.println(opt.get());

🚨 Optional 훈련

  • empty()
더보기
Optional<String> empty = Optional.empty();
System.out.println(empty.isPresent()); // ?
  • of()
더보기
Optional<String> empty = Optional.of("assert NotNull");
System.out.println(empty.isPresent()); // ?
Optional.of(null); // ?

→ NPE 발생. of는 null이 아님을 확신할때 사용.

  • ofNullable()
더보기
Optional<String> empty = Optional.ofNullable(null);
System.out.println(empty.isPresent()); // ?
  • ifPresent() : Optional에서 꺼낸 객체가 존재한다면, 구문수행.
더보기
String name = null;
Optional<String> opt = Optional.ofNullable(name);

opt.ifPresent(n -> System.out.println(n.length()));
  • orElse() : Optional에서 꺼낸 객체가 존재한다면 꺼내고, 그렇지 않다면? orElse의 인자값을 반환
더보기
System.out.println(Optional.ofNullable(null).orElse("냐옹"));

System.out.println(Optional.ofNullable("Hey!").orElse("냐옹"));
  • orElseGet() : orElse()와 비슷하지만, 인자값으로 람다 표현식의 결과값을 출력
더보기
System.out.println(Optional.ofNullable(null).orElseGet(String::new));
System.out.println(Optional.ofNullable(null).orElseGet(() -> "냐옹"));
System.out.println(Optional.ofNullable("Hey!").orElseGet(() -> "냐옹"));
  • orElseThrow() : Optional에서 꺼낸 객체가 존재한다면 꺼내고, 그렇지 않다면? Exception 던지기
더보기
String nullName = null;
String name = Optional.ofNullable(nullName).orElseThrow(
    IllegalArgumentException::new);
참고 사이트 : https://www.baeldung.com/java-optional

 

🚨 Stream 훈련

  • filter + anyElement / firstElement
더보기
List<String> elements = Stream.of("a", "b", "c")
        .filter(element -> element.contains("b"))
        .collect(Collectors.toList());

        Optional<String> anyElement = elements.stream().findAny();
        System.out.println(anyElement.orElse("암것두 없어"));

        Optional<String> firstElement = elements.stream().findFirst();
        System.out.println(firstElement.orElse("한개두 없어"));
  • N개의 중개 연산자
더보기
Stream<String> onceModifiedStream = Stream.of("abcd", "bbcd", "cbcd");

        Stream<String> twiceModifiedStream = onceModifiedStream
        .skip(1)
        .map(element -> element.substring(0, 3));

        System.out.println(twiceModifiedStream); //?
        System.out.println(twiceModifiedStream.collect(Collectors.toList()));
  • map 활용
더보기

[class Product]

class Product {
    private int age;
    private String name;

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

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }
}

 

List<String> collectorCollection = productList.stream()
        .map(Product::getName)
        .collect(Collectors.toList());

System.out.println(collectorCollection);

double averageAge = productList.stream()
.collect(Collectors.averagingInt(Product::getAge));
System.out.println("나이 평균 : " + averageAge);

int summingAge = productList.stream().mapToInt(Product::getAge).sum();
System.out.println("나이 총합 : " + summingAge);

 

참고 사이트 : https://www.baeldung.com/java-8-streams

 

 

 

튜터님 강의는 optinal 부터 솔직히 헤롱헤롱 하면서 제대로 이해 못했지만 ,,, 보다보면 하다보면 알게 되겠지 뭐~!

 

 

 

 

'Sparta > What I Learned' 카테고리의 다른 글

22.12.4  (0) 2022.12.05
22.12.2  (0) 2022.12.03
22.11.30  (0) 2022.11.30
22.11.29  (0) 2022.11.29
22.11.28  (0) 2022.11.29