2014.07.26 ksug와 지앤선이 함께하는 테크니컬 세미나 - 자바8 람다 나머지...

Post on 30-Jul-2015

161 Views

Category:

Technology

4 Downloads

Preview:

Click to see full reader

TRANSCRIPT

나머지

박성철

자바8람다 이야기

SK Planet, 한국 스프링 사용자 모임(KSUG)

박성철(fupfin)

노땅 개발자(라고 착각하는 관리자)

엄청 망해봤어요

산만해요

람다에서 필요한 건 이미 다 배웠습니다

와~

뭐?!

메서드 참조method reference

람다는 뭘까?

Runnable����������� ������������������  task����������� ������������������  =����������� ������������������  ()����������� ������������������  ->����������� ������������������  {����������� ������������������  System.out.println(“Hello����������� ������������������  world”);};����������� ������������������  new����������� ������������������  Thread(task).start();

메서드?객체

람다는 무명 클래스를 쉽게 만들 수 있는 언어 장치?

void����������� ������������������  noname(){����������� ������������������  System.out.println(“Hello����������� ������������������  world”);};람다 ≃ 무명 메서드

public����������� ������������������  class����������� ������������������  MethodRefExample����������� ������������������  {����������� ������������������  !����������� ������������������   public����������� ������������������  static����������� ������������������  void����������� ������������������  main(String����������� ������������������  args[])����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   List<String>����������� ������������������  list����������� ������������������  =����������� ������������������  Arrays.asList("A",����������� ������������������  "B",����������� ������������������  "C",����������� ������������������  "D");����������� ������������������  ����������� ������������������   ����������� ������������������   list.forEach((e)����������� ������������������  ->����������� ������������������  printWithTime(e));����������� ������������������  ����������� ������������������   }����������� ������������������  ����������� ������������������   ����������� ������������������  ����������� ������������������   public����������� ������������������  static����������� ������������������  void����������� ������������������  printWithTime(String����������� ������������������  str)����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   out.println("["����������� ������������������  +����������� ������������������  currentTimeMillis()����������� ������������������  +����������� ������������������  "]����������� ������������������  "����������� ������������������  +����������� ������������������  str);����������� ������������������  ����������� ������������������   }����������� ������������������  }����������� ������������������  

void����������� ������������������  forEach(Consumer<?����������� ������������������  super����������� ������������������  T>����������� ������������������  action)

Consumer<T>����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  void����������� ������������������  accept(T����������� ������������������  t);����������� ������������������  }

동일 시그니처

메서드 참조

public����������� ������������������  class����������� ������������������  MethodRefExample����������� ������������������  {����������� ������������������  !����������� ������������������   public����������� ������������������  static����������� ������������������  void����������� ������������������  main(String����������� ������������������  args[])����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   List<String>����������� ������������������  list����������� ������������������  =����������� ������������������  Arrays.asList("A",����������� ������������������  "B",����������� ������������������  "C",����������� ������������������  "D");����������� ������������������  ����������� ������������������   ����������� ������������������   list.forEach(MethodRef::printWithTime);����������� ������������������  ����������� ������������������   }����������� ������������������  ����������� ������������������   ����������� ������������������  ����������� ������������������   public����������� ������������������  static����������� ������������������  void����������� ������������������  printWithTime(String����������� ������������������  str)����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   out.println("["����������� ������������������  +����������� ������������������  currentTimeMillis()����������� ������������������  +����������� ������������������  "]����������� ������������������  "����������� ������������������  +����������� ������������������  str);����������� ������������������  ����������� ������������������   }����������� ������������������  }����������� ������������������  

기존에 만들어진 메서드를 명칭을 사용해서 참조하는 표현

메서드 참조의 종류

1) 정적 메서드 참조2) 객체 메서드 참조3) 람다 인자 객체 메서드 참조4) 생성자 참조5) 상위 클래스의 메서드 참조6) 배열 생성자

정적 메서드 참조

public����������� ������������������  class����������� ������������������  MethodRef����������� ������������������  {����������� ������������������  !����������� ������������������   public����������� ������������������  static����������� ������������������  void����������� ������������������  main(String����������� ������������������  args[])����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   List<String>����������� ������������������  list����������� ������������������  =����������� ������������������  Arrays.asList("123",����������� ������������������  "241",����������� ������������������  "212");����������� ������������������  ����������� ������������������   ����������� ������������������   int����������� ������������������  sum����������� ������������������  =����������� ������������������  list.stream().mapToInt(Integer::parseInt).sum();����������� ������������������  ����������� ������������������   }����������� ������������������  }

특정 클래스의 정적 메서드 참조

클래스 이름::메서드 이름

객체 메서드 참조

public����������� ������������������  class����������� ������������������  MethodRefExample����������� ������������������  {����������� ������������������  !����������� ������������������  ����������� ������������������  ����������� ������������������  public����������� ������������������  static����������� ������������������  void����������� ������������������  main(String����������� ������������������  args[])����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������  ����������� ������������������  ����������� ������������������  List<String>����������� ������������������  list����������� ������������������  =����������� ������������������  Arrays.asList("A",����������� ������������������  "B",����������� ������������������  "C");����������� ������������������  ����������� ������������������   ����������� ������������������  ����������� ������������������  ����������� ������������������  list.forEach(System.out::println);����������� ������������������   ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  }����������� ������������������  }

특정 객체의 멤버 메서드 참조

객체 참조::메서드 이름

람다 인자 객체 메서드 참조

public����������� ������������������  class����������� ������������������  MethodRefExample����������� ������������������  {����������� ������������������  !����������� ������������������   public����������� ������������������  static����������� ������������������  void����������� ������������������  main(String����������� ������������������  args[])����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   Integer[]����������� ������������������  values����������� ������������������  =����������� ������������������  null;����������� ������������������  ����������� ������������������   ����������� ������������������   Arrays.sort(values,����������� ������������������  Integer::compare);����������� ������������������  ����������� ������������������   }����������� ������������������  }

람다의 인자로 넘어오는 객체의 멤버 메서드 참조

e����������� ������������������  ->����������� ������������������  e.someMethod();����������� ������������������  (e1,����������� ������������������  e2)����������� ������������������  ->����������� ������������������  e1.someMethod(e2);

SomeObject::someMethod����������� ������������������  SomeObject::someMethod

인자의 타입명::메서드 이름

생성자 참조

List<Integer>����������� ������������������  list����������� ������������������  =����������� ������������������  null;����������� ������������������  list.stream().mapToObject(Integer::new).…⋯…⋯����������� ������������������  

()����������� ������������������  ->����������� ������������������  new����������� ������������������  SomeObject();����������� ������������������  ����������� ������������������  e����������� ������������������  ->����������� ������������������  new����������� ������������������  SomeObject(e);����������� ������������������  (e1,����������� ������������������  e2)����������� ������������������  ->����������� ������������������  new����������� ������������������  SomeObject(e1,����������� ������������������  e2);

SomeObject::new����������� ������������������  SomeObject::new����������� ������������������  SomeObject::new

해당하는 인자를 받는 객체 생성자의 참조

클래스 이름::new

상위 클래스 메서드 참조

상속 관계의 상위 클래스 메서드 참조

super::메서드 이름

배열 생성자 참조

특정 타입의 배열 생성자 참조

타입명[]::new

정리

람다 표현 대신 메서드의 참조를 사용 가능클래스(또는 객체)::메서드 이름정적 메서드 참조, 객체 메서드 참조, 생성자 참조함수 인터페이스가 아니라도 기존 메서드를 람다 표현 대신 사용

this의 범위

public����������� ������������������  class����������� ������������������  LambdaExample����������� ������������������  {����������� ������������������  ����������� ������������������   public����������� ������������������  void����������� ������������������  sort(List<Integer>����������� ������������������  list)����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   list.sort(new����������� ������������������  Comparator<Integer>()����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   ����������� ������������������   @Override����������� ������������������  public����������� ������������������  int����������� ������������������  compare(Integer����������� ������������������  i1,����������� ������������������  Integer����������� ������������������  i2)����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   ����������� ������������������   ����������� ������������������   this.count();����������� ������������������  ����������� ������������������   ����������� ������������������   ����������� ������������������   ����������� ������������������   return����������� ������������������  i1.compareTo(i2);����������� ������������������  ����������� ������������������   ����������� ������������������   ����������� ������������������   }����������� ������������������  ����������� ������������������   ����������� ������������������   });����������� ������������������  ����������� ������������������   }����������� ������������������  ����������� ������������������   ����������� ������������������  ����������� ������������������   private����������� ������������������  void����������� ������������������  count()����������� ������������������  {…⋯}����������� ������������������  }

LambdaExample.this.count();

무명 클래스 vs 람다

public����������� ������������������  class����������� ������������������  LambdaExample����������� ������������������  {����������� ������������������  ����������� ������������������   public����������� ������������������  void����������� ������������������  sort(List<Integer>����������� ������������������  list)����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   list.sort((i1,����������� ������������������  i2)����������� ������������������  ->����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   ����������� ������������������   ����������� ������������������   this.count();����������� ������������������  ����������� ������������������   ����������� ������������������   ����������� ������������������   ����������� ������������������   return����������� ������������������  i1.compareTo(i2);����������� ������������������  ����������� ������������������   ����������� ������������������   ����������� ������������������   });����������� ������������������  ����������� ������������������   }����������� ������������������  ����������� ������������������   ����������� ������������������  ����������� ������������������   private����������� ������������������  void����������� ������������������  count()����������� ������������������  {…⋯}����������� ������������������  }

응? 람다도 객체

아닌가? 왜 자신을

안 가리키지?

public����������� ������������������  class����������� ������������������  LambdaExample����������� ������������������  {����������� ������������������  ����������� ������������������   public����������� ������������������  void����������� ������������������  sort(List<Integer>����������� ������������������  list)����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   list.sort(this::lambda$0);����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  }����������� ������������������  ����������� ������������������   ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  private����������� ������������������  void����������� ������������������  count()����������� ������������������  {…⋯}����������� ������������������  !����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  private����������� ������������������  int����������� ������������������  lambda$0(Integer����������� ������������������  i1,����������� ������������������  Integer����������� ������������������  i2)����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   this.count();����������� ������������������  ����������� ������������������   ����������� ������������������   return����������� ������������������  i1.compareTo(i2);����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  }����������� ������������������  }

public����������� ������������������  class����������� ������������������  LambdaExample����������� ������������������  {����������� ������������������  ����������� ������������������   public����������� ������������������  void����������� ������������������  sort(List<Integer>����������� ������������������  list)����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   list.sort((i1,����������� ������������������  i2)����������� ������������������  ->����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   ����������� ������������������   ����������� ������������������   this.count();����������� ������������������  ����������� ������������������   ����������� ������������������   ����������� ������������������   ����������� ������������������   return����������� ������������������  i1.compareTo(i2);����������� ������������������  ����������� ������������������   ����������� ������������������   ����������� ������������������   });����������� ������������������  ����������� ������������������   }����������� ������������������  ����������� ������������������   ����������� ������������������  ����������� ������������������   private����������� ������������������  void����������� ������������������  count()����������� ������������������  {…⋯}����������� ������������������  }

초간단 요약 람다의 처리

정리

람다는 새로운 객체를 만들지 않음this는 내가 알던 그 this비밀이 숨어 있지만… MethodHandle…

기본 메서드default method

API의 고민, 하위 호환성

“객체지향 모델은 신중히 설계해서 클래스 라이브러리가 변한다고 이미 컴파일된 애플리케이션이 망가지지 않도록 해야 한다. 정말로, 애플리케이션은 망가뜨리지 말아라.”

---Ira Forman, Michael Conner, Scott Danforth, and Larry Raper, "Release-to-Release Binary Compatibility in SOM", in Proceedings of OOPSLA '95.

"An object-oriented model must be carefully designed so that class-library transformations

that should not break already compiled applications, indeed, do not break such applications.”

API의 고민, 하위 호환성

Adding new fields, methods, or constructors to an existing class or interface.

기존 클래스나 인터페이스에 새 필드, 메서드, 생성자 추가

깨어진 하위 호환성

자바 인터페이스의 호환성 문제

자바 인터페이스의 모든 메서드는 공개(public) 추상(abstract)이스를 구현한 모든 클래스는 추가된 메서드를 구현해서 새로 컴

파일 해야 한다.

자바 인터페이스 개선 전략

1) 호환성 무시! 내가 고치겠다는데 뭐… (쓰는 사람도 없고)

2) 새 술은 새 부대에, 새 메서드는 새 인터페이스에… 기존 인터페이스를 확장한 새 인터페이스 생성, 버전 인터페이스

3) 기본 추상 클래스 제공고객이 인터페이스를 구현하는 대신 기본 제공되는 추상 객체를 확장하도록 권장

4) 그리고 전통적인 자바 API의 방법…

고치지 않는다…

하위 호환성을 버려야 할 위기

람다의 도입은 단순한 표현 방법 추가 이상의 의미“OOP 방식 외 새로운 추상화 기법 도입”자바 SDK의 기본 API의 대대적인 변형 필수

하지만 자바가 하위 호환성을 버릴 수는…

기본 메서드 구현

새로 추가하는 메서드에 기본 구현을 넣자!!

interface����������� ������������������  MyInterface����������� ������������������  {����������� ������������������  !����������� ������������������   ����������� ������������������   int����������� ������������������  existingMethod();����������� ������������������  ����������� ������������������   ����������� ������������������   ����������� ������������������  ����������� ������������������   ����������� ������������������   default����������� ������������������  void����������� ������������������  newMethod()����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   ����������� ������������������   //����������� ������������������  기본으로����������� ������������������  수행할����������� ������������������  로직����������� ������������������  ����������� ������������������   ����������� ������������������   }����������� ������������������  ����������� ������������������   }����������� ������������������  }

기본 메서드

기본 메서드 사용

기본 메서드는 클래스에서 구현하지 않아도 사용 가능

interface����������� ������������������  Foo����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  default����������� ������������������  void����������� ������������������  newMethod()����������� ������������������  {����������� ������������������  }����������� ������������������  }����������� ������������������  ����������� ������������������   ����������� ������������������  class����������� ������������������  FooImpl����������� ������������������  implements����������� ������������������  Foo����������� ������������������  {����������� ������������������  }����������� ������������������  !!new����������� ������������������  FooImpl().newMethod();

상속

기본 메서드 상속

인터페이스 상속시 기본 메서드 구현도 상속하위 인터페이스가 재정의(override) 가능

interface����������� ������������������  Foo����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  default����������� ������������������  void����������� ������������������  newMethod()����������� ������������������  {…⋯}����������� ������������������  }����������� ������������������  ����������� ������������������   ����������� ������������������  interface����������� ������������������  Bar����������� ������������������  extends����������� ������������������  Foo����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  @Override����������� ������������������  default����������� ������������������  void����������� ������������������  newMethod()����������� ������������������  {…⋯}����������� ������������������  }����������� ������������������  !class����������� ������������������  BarImpl����������� ������������������  implements����������� ������������������  Bar����������� ������������������  {����������� ������������������  }����������� ������������������  !!new����������� ������������������  BarImpl().newMethod();

다중 상속

객체메세지

행위

상태 추상/구상클래스

자바7이전인터페이스

자바8인터페이스

단일 상속만 허용 다중 상속 허용 다중 상속 허용

메시지의 다중 상속 메시지와 구현의다중 상속

충돌 발생

다중 상속 구현 충돌

자바 7 이전: 구현의 다중 상속 불가자바 8부터: 기본 메서드로 인해 구현 충돌 문제 발생

interface����������� ������������������  Foo����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  default����������� ������������������  void����������� ������������������  newMethod()����������� ������������������  {…⋯}����������� ������������������  }����������� ������������������  ����������� ������������������   ����������� ������������������  interface����������� ������������������  Bar1����������� ������������������  extends����������� ������������������  Foo����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  @Override����������� ������������������  default����������� ������������������  void����������� ������������������  newMethod()����������� ������������������  {…⋯}����������� ������������������  }����������� ������������������  !interface����������� ������������������  Bar2����������� ������������������  extends����������� ������������������  Foo����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  @Override����������� ������������������  default����������� ������������������  void����������� ������������������  newMethod()����������� ������������������  {…⋯}����������� ������������������  }����������� ������������������  ����������� ������������������   ����������� ������������������  class����������� ������������������  BarImpl����������� ������������������  implements����������� ������������������  Bar1,����������� ������������������  Bar2����������� ������������������  {����������� ������������������  }

Foo

Bar1 Bar2

BarImpl

다이아몬드 문제

컴파일 에러!!!

다이아몬드 문제 회피법충돌 기본 메서드 재정의(Override)class����������� ������������������  BarImpl����������� ������������������  implements����������� ������������������  Bar1,����������� ������������������  Bar2����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  @Override����������� ������������������  default����������� ������������������  void����������� ������������������  newMethod()����������� ������������������  {…⋯}����������� ������������������  }

Foo

Bar1 Bar2

BarImpl상속 방향 선택class����������� ������������������  BarImpl����������� ������������������  implements����������� ������������������  Bar1,����������� ������������������  Bar2����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  @Override����������� ������������������  default����������� ������������������  void����������� ������������������  newMethod()����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  Bar1.super.newMethod();����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  …⋯����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  }����������� ������������������  }

Foo

Bar1 Bar2

BarImpl

상속 순서 선택class����������� ������������������  BarImpl����������� ������������������  implements����������� ������������������  Bar1,����������� ������������������  Bar2����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  @Override����������� ������������������  default����������� ������������������  void����������� ������������������  newMethod()����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  Bar1.super.newMethod();����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  Bar2.super.newMethod();����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  }����������� ������������������  }

Foo

Bar1 Bar2

BarImpl1 2

기본 메서드와 트레잇(Trait)

OOP에서 다른 클래스의 기능을 확장하는데 사용되는 메서드의 집합보통 인터페이스와 믹스인 중간에 해당한다. 인터페이스는 메서드 선언만 있고, 트레잇은 정의까지 포함한다. 믹스인은 상태를 가지지만 트레잇은 보통 상태를 가지지 않는다.

기본 메서드와 트레잇(Trait)

OOP의 집합보통 인터페이스와 믹스인 중간에 해당한다. 인터페이스는 메서드 선언만 있고, 트레잇은 정의까지 포함한다. 믹스인은 상태를 가지지만 트레잇은 보통 상태를 가지지 않는다.

인터페이스 정적 메서드

기본 구현과 함께 인터페이스에도 정적 메서드 정의 가능편의 메서드(utility method)를 위한 이름 공간(Name space)로서의 인터페이스

interface����������� ������������������  StringUtils����������� ������������������  {����������� ������������������  !����������� ������������������  ����������� ������������������  ����������� ������������������  static����������� ������������������  String����������� ������������������  reverse(String����������� ������������������  str){…⋯}����������� ������������������  !����������� ������������������  ����������� ������������������  ����������� ������������������  static����������� ������������������  String����������� ������������������  capitalize(String����������� ������������������  str)����������� ������������������  {…⋯}����������� ������������������  !����������� ������������������  ����������� ������������������  ����������� ������������������  static����������� ������������������  String����������� ������������������  delete(String����������� ������������������  inString,����������� ������������������  String����������� ������������������  pattern)����������� ������������������  {…⋯}����������� ������������������  !����������� ������������������  ����������� ������������������  ����������� ������������������  …⋯…⋯����������� ������������������  }

정리

인터페이스에 메서드 구현 가능기본 메서드는 상속, 재정의 가능바이너리 하위 호환성을 유지하고 기존 인터페이스에 메서드 추가다중 상속시 재정의, 상속 방향 선택 등으로 충돌 회피정적 메서드 정의 가능

기본 제공 함수 인터페이스java.util.function.*

범용 함수형 인터페이스

java.util.function 패키지에 범용으로 사용될 다양한 함수형 인터페이스 기본 제공

Consumer<T>BiConsumer<T,U>Function<T,R>BiFunction<T,U,R>Predicate<T>Supplier<T>UnaryOperator<T>BinaryOperator<T>

void accept(T t)void accept(T t, U u)R apply(T t)R apply(T t, U u)boolean test(T t)T get()T apply(T t)T apply(T t1, T t2)

기본 타입용 변종

Consumer<T>

Function<T,R>

Predicate<T>

Supplier<T>

UnaryOperator<T>

Int

Double

Long

기본 타입 변환 함수 인터페이스

Double

Function<T,R>: T 타입을 R타입으로 바꾸는 함수 인터페이스

Int

Long

Double

Int

Long

IntToDoubleFunctionLongToDoubleFunction

DoubleToIntFunctionLongToIntFunction

DoubleToLongFunctionIntToLongFunction

정리

다양한 범용 함수 인터페이스를 기본으로 제공삽질하지 말자

END_OF_THIRD_WAVE

top related