[2021.01.18.월] TIL

노을·2021년 1월 18일
1

TIL

목록 보기
22/81

😨 오늘 컨디션

  • 새벽에 무리했더니 졸리다.

🔎 오늘 검색 한 키워드

⌛ 오늘 한 것

1. 자바의 정석

  • 1장, 2장 꼼꼼히 정독
  • 7장 간략히 정리함 (*나중에 다시보자)
    • 7-5. 다형성
    • 7-6. 추상 클래스
    • 7-7. 인터페이스
  • 14장 람다식 학습 및 실습
    • 학습 정리는 아직 못함

2. 모던 자바 8 정리

(1). 코드 간결성, 가독성 등..


// 1 : 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 : 10 을 만드시오.
// <조건> 마지막 문자열 10 뒤에는 ":" 문자가 없어야 함.

// case 1
// 너무 복잡함.

final String separtor = " : ";
for(Integer number : numbers){
	StringBuilder.append(number).append(separator);
}
final int stringLength = strignBuilder.length();
if(stringLength > 0){
	stringBuilder.delete(stringLength - separator.length(), stringLength);
}
System.out.println(stringBuilder.toString());

// case 2
final String result = numbers.stream()
														 .map(String::valueof)
                             .collect(joining(" : "));

⇒ Map ≠ HashMap
⇒ 어떤 하나의 타입을 다른 타입으로 맵핑한다는 의미.

(2). 추가설명

  • 병렬 프로그래밍(Parallel Programming)을 쉽게 할 수 있는 장점이 있지만, 이번 세션에서는 그 이외에 장점에 대해 설명함.
  • 함수형 프로그래밍을 쉽게 얘기하고, 사용하게 된 것에는 GC와 Memory Allocation 기술 발달이 크다.

SOLID 원칙에 어긋남, 한 메소드에서 많은 기능을 하고 있음.

class CalculatorService {
    public int calculate(char cal, int num1, int num2) {
        if(cal == '+') {
            return num1 + num2;
        }
        else if(cal == '-'){
            return num1 - num2;
        }
        else if(cal == '*'){
            return num1 * num2;
        }
        else if(cal == '/'){
            return num1 / num2;
        }
        else
            throw new IllegalArgumentException("Unknown calculation: "+cal);
    }
}

public class OopAnotherExample{

    public static void main(String[] args) {

        final CalculatorService calculatorService = new CalculatorService();

        final int additionResult = calculatorService.calculate('+',1, 1);
        System.out.println(additionResult);

        //m 추가 요구 사항으로 뺄셈 기능이 필요하다면?
        final int subtractionResult = calculatorService.calculate('-',1, 1);
        System.out.println(subtractionResult);

        //m 요구사항이 자꾸 늘어나면 코드가 점점 길어짐
        final int multiplicationResult = calculatorService.calculate('*',1, 1);
        System.out.println(multiplicationResult);

        //m ...
        final int divisionResult = calculatorService.calculate('/',8, 4);
        System.out.println(divisionResult);

    }
}

전략패턴 사용

interface Calculation {
    int calculate(int num1, int num2);
}

//m 전략패턴
class Addition implements Calculation {
    @Override
    public int calculate(int num1, int num2) {
        return num1 + num2;
    }
}
class Subtraction implements Calculation {
    @Override
    public int calculate(int num1, int num2) {
        return num1 - num2;
    }
}
class Multiplication implements Calculation {
    @Override
    public int calculate(int num1, int num2) {
        return num1 * num2;
    }
}
class Division implements Calculation {
    @Override
    public int calculate(int num1, int num2) {
        return num1 / num2;
    }
}

public class OopAndFpExample{

    public static void main(String[] args) {

        FpCalculatorService fpCalculatorService =new FpCalculatorService();

        //m DI: Dependency Injection, It is Strategy Pattern of Design Pattern
        System.out.println(" addition: "+fpCalculatorService.calculate(new Addition(),11,4));
        System.out.println(" subtraction: "+fpCalculatorService.calculate(new Subtraction(),11,1));
        System.out.println(" Multiplication: "+fpCalculatorService.calculate(new Multiplication(),11,2));
        System.out.println(" Division: "+fpCalculatorService.calculate(new Division(),20,4));

    }
}

class FpCalculatorService{

    public int calculate(Calculation calculation, int num1, int num2) {
        if(num1 > 10 && num2 <num1){
            return calculation.calculate(num1,num2);
        }
        else{
            throw new IllegalArgumentException("Invalid input num1: "+num1+", num2: "+num2);
        }
    }

JAVA의 Method가 1급 객체가 아닌 이유

  1. 파라미터로 전달 할 수 있다. (X)
public String getName(){
			 ...
}

findByName(getName); // getName()으로 return이 아닌 메소드 자체
  1. return값으로 method를 받을 수 있다. (X)
public doSomething(){
	return getName; // 메소드 자체 
}
  1. 변수나 데이터 구조안에 담을 수 있다. (X)
List<> list = Arrays.asList(getName) // 메소드 자체

JAVA 8 이후 부터 함수형 프로그래밍을 지원하게 됨.

  • 익명 함수
  • 익명 함수을 구현하는 방법 중 하나가 람다 표현식
(*기존)

System.out.println(" addition: "+fpCalculatorService.calculate(new Addition(),11,4));
System.out.println(" subtraction: "+fpCalculatorService.calculate(new Subtraction(),11,1));
System.out.println(" Multiplication: "+fpCalculatorService.calculate(new Multiplication(),11,2));
System.out.println(" Division: "+fpCalculatorService.calculate(new Division(),20,4));

람다 표현식

System.out.println(" addition: "+fpCalculatorService.calculate((num1,num2)->{return num1+num2;},11,4));
System.out.println(" subtraction: "+fpCalculatorService.calculate((num1,num2)->num1-num2,11,1));
System.out.println(" Multiplication: "+fpCalculatorService.calculate((n1,n2)->n1*n2,11,2));
System.out.println(" Division: "+fpCalculatorService.calculate((int n1,int n2)->n1/n2,20,4));

System.out.println(" custom calc: "+fpCalculatorService.calculate((n1,n2)->((n1+n2)*2),20,4));

⇒ 사이드 이펙트가 제거되었고, 코드의 간결성과 유지보수가 좋아짐

람다 표현식을 통해 function이 variable에 할당이 됬음. 즉, 1급 객체

final Calculation addition = (num1,num2)->{return num1+num2;};     
System.out.println(" addition: "+fpCalculatorService.calculate(addition,11,4));

따라서, 1급 객체를 지원하게 되면, 메소드 자체에서 행동을 받아서 다양한 일을 할 수 있다!

9. Closure

  • Lambda Expression ≠ Closure

  • JAVA 8에 Functional Feature를 추가하게 된 이유는 First Class Function을 가지기 위함.

  • First Class Function

     ⇒ Function == First Class Citizen
  • 자바에서 First Class Function 를 표현하기 위한 방법

    • Anonymous Method (익명 메소드) == Lambda Expression method(i->i+1)
void method()
{
	int i = 100;

	someMethod(x->x*2+i)  // x: 파라미터,  i: non-local variable == Free variable
}
  • i 는 Lambda Expression 함수 외부에 존재함 == non-local variable == Free variable
  • 익명 함수가 non-local variable에 접근을 하면 이런 함수를 Closure라고 부름.
  • Closure라고 부르는 이유는 람다 함수 자체 스코프를 외부로 확장해서 Close Over 한다해서 Closure임.

예제) 가독성이 훨씬 좋아짐

public class ClosureExample {

    public static void main(String[] args) {
        final int number = 100;
        
        final Runnable runnable = new Runnable() { //m 익명함수
            @Override
            public void run() {
                System.out.println(number);
            }
        };
        runnable.run();
        
        Runnable runnable2 = ()-> System.out.println(number);  //m 람다 표현식
        runnable2.run();

    }

}

(주의) JAVA 8 부터 익명 클래스는 non-local variable이 final이 아니어도 접근이 가능해짐.

public class ClosureExample {

    public static void main(String[] args) {
        int number = 100;
        
        final Runnable runnable = new Runnable() { //m 익명함수
            @Override
            public void run() {
								~~number = 99;~~   *에러 발생!
                System.out.println(number);
            }
        };
        runnable.run();
        
        Runnable runnable2 = ()-> System.out.println(number);  //m 람다 표현식
        runnable2.run();

    }

}
  • int number는 final이 아니지만 수정하게 될 경우 에러가 발생함.
  • 따라서, Effectively Final 이라고 부름
  • 결국은 final인데 편의를 위해 생략이 가능해진 것임.

final인 이유

  • 멀티 스레딩에서 Race Condition이 발생할 수 있어서 금지 시킨 것

자바의 람다 표현식은 free variable을 캡쳐하지 않고 value를 캡쳐한다.

  • 그렇기 때문에 값이 바뀌면 안되고 final or Effectively final 이어야함.

👍 잘한 부분

  • 상속과 인터페이스 개념을 훑어보았다.
  • 미션에 필요한 지식들을 나열 해보았고, 그에 맞게 정보 탐색을 해보았다.
  • 아침부터 새벽까지 의자에 앉아있었다.
  • 1시간 주기로 스트레칭도 해주었다 ㅎㅎ

👎 부족한 부분

  • 시간관리를 제대로 못했다.
  • 오늘은 영어공부를 못했다.
  • 순수함수, 고차함수에 관한 개념을 아직 탐색하지 못했다.
  • 미션을 아직 못 건들였다.

🌙 느낀점

  • 새로운 개념이 점점 많이 나오는데, 위축되지 않고 오히려 점점 프로그래밍 공부에 대한 흥미가 생기기 시작하고 있다. 오늘은 자발적으로 늦게까지 공부를 했다. 살아오면서 모든 평범하게 해오던 나였는데 변화가 생긴 것 같고 새롭다. 이 기분을 잘 간직하고 기억하자.
profile
카르페디엠

3개의 댓글

comment-user-thumbnail
2021년 1월 18일

마인드맵으로 개념 정리하신거 인상깊네요. 😀

1개의 답글