[2021.01.18.월] TIL
😨 오늘 컨디션
- 새벽에 무리했더니 졸리다.
🔎 오늘 검색 한 키워드
⌛ 오늘 한 것
1. 자바의 정석
- 1장, 2장 꼼꼼히 정독
- 7장 간략히 정리함 (*나중에 다시보자)
- 7-5. 다형성
- 7-6. 추상 클래스
- 7-7. 인터페이스
- 14장 람다식 학습 및 실습
- 학습 정리는 아직 못함
2. 모던 자바 8 정리
- 개인 학습 정리용이라, 틀린 내용이 많을 수 있습니다.
- 케빈TV, 모던자바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급 객체가 아닌 이유
- 파라미터로 전달 할 수 있다. (X)
public String getName(){
...
}
findByName(getName); // getName()으로 return이 아닌 메소드 자체
- return값으로 method를 받을 수 있다. (X)
public doSomething(){
return getName; // 메소드 자체
}
- 변수나 데이터 구조안에 담을 수 있다. (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)
- Anonymous Method (익명 메소드) == Lambda Expression
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시간 주기로 스트레칭도 해주었다 ㅎㅎ
👎 부족한 부분
- 시간관리를 제대로 못했다.
- 오늘은 영어공부를 못했다.
- 순수함수, 고차함수에 관한 개념을 아직 탐색하지 못했다.
- 미션을 아직 못 건들였다.
🌙 느낀점
- 새로운 개념이 점점 많이 나오는데, 위축되지 않고 오히려 점점 프로그래밍 공부에 대한 흥미가 생기기 시작하고 있다. 오늘은 자발적으로 늦게까지 공부를 했다. 살아오면서 모든 평범하게 해오던 나였는데 변화가 생긴 것 같고 새롭다. 이 기분을 잘 간직하고 기억하자.
Author And Source
이 문제에 관하여([2021.01.18.월] TIL), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@san/2021.01.18.월-TIL저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)