출처 : https://velog.io/@namezin/GoF-design-pattern
A B A B
0.1 0.1 0.1(0.2) 0.1(0.2).....
class MyRunnable implements Runnable {
@Override
public void run() {
for(int i=1; i<=10; i++)
System.out.println("### MyRunnable 실행 중 : " + (i*10) + "% 완료 ###");
}
}
public class Test2 {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
// new Thread하는데 왜 객체를 넘긴다? 실제로는 메소드를 넘긴 것
// js에서는 함수만 넘길 수 있다. new Thread(function() { });
new Thread(myRunnable).start();
System.out.println("메인 스레드 종료");
}
}
public class Test3 {
public static void main(String[] args) {
// Runnable은 만들어야 하는데...클래스까지 만들 필요는 없잖아...파라미터로 Runnable을 넘기자
// Thread 생성자의 파라미터가 Runnable이라는 사실을 자바가 알고 있다
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("익명 객체를 이용한 스레드");
}
}).start();
// 그렇다면 프로그래머는 run()의 내부만 만들자 -> 객체는 자바가 만들면 되잖아 : 자바 Lambda
// 메소드만 만들면 자바가 객체를 알아서 생성해준다 -> 전제조건 : 인터페이스가 존재해야만 한다
new Thread(
()->{System.out.println("익명 객체를 이용한 스레드");}
);
}
}
// 람다식을 이용해 간편하게 함수를 작성하려면...많은 작업이 필요하다
// 람다식을 사용하려면 추상 메소드를 하나가진 인터페이스가 바람직
@FunctionalInterface
interface 인사 {
public void hello();
}
class 학생 {
public void 꾸벅(인사 insa) {
insa.hello();
}
}
public class Test4 {
public static void main(String[] args) {
// 인터페이스가 있고 그 인터페이스를 이용하는 클래스가 있어야만 람다식을 사용할 수 있다
// 람다를 사용하려니 배보다 배꼽이 크다 -> 자바는 java.util.function 패키지를 이용해 FunctionInterface를 제공
학생 s = new 학생();
s.꾸벅(()->{ System.out.println("안녕하세요"); });
}
}
입력은 있고 리턴은 없다
class ConsumerSample implements Consumer<Integer> {
@Override
public void accept(Integer t) {
System.out.println(t);
}
}
public class Test5 {
public static void main(String[] args) {
// Arrays.asList는 배열을 리스트로 변환하는 함수. 읽기전용이다
List<Integer> list = Arrays.asList(11,22,33,44,55);
// ConsumerSample을 사용한 예 : ?의 구체적 의미가 궁금해서 iilii.eloos.com에서 generic 강좌를 보세요
list.forEach(new ConsumerSample());
// 람다식을 사용한 예
// list.forEach((xx)->{ System.out.println(xx); });
// 처리하는 코드가 한 줄이면 {}를 생략할 수 있다. {}를 생략하면 ;이 오면 안된다
//list.forEach((xx)->System.out.println(xx));
// 파라미터가 하나면 ()를 생략할 수 있다(하나일때만 생략 가능)
//list.forEach(a->System.out.println(a));
// 파라미터에 대해 어떤 처리도 하지 않는다면....윗줄의 경우 xx가 들어와서 그대로 xx를 출력한다...생략하자
// 이렇게 파라미터를 생략하고 함수를 사용하는 것을 "메소드 참조"라고 한다
list.forEach(System.out::println);
}
}
입력이 있고 출력은 boolean → 조건 체크
class SamplePredicator implements Predicate<Integer> {
@Override
public boolean test(Integer t) {
return t%2==0;
}
}
public class Test6 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(11,22,33,44,55);
// 람다식을 이용해 작업하도록 만들어진 자바 기술이 Java Stream API
// 리스트를 스트림을 변환하면 자바가 제공하는 함수를 이용해 람다식을 연속으로 사용할 수 있다
// filter는 list를 모든 원소를 차례로 입력받아 조건을 만족하는 것만 걸러낸다
// 스트림에는 메소드에는 중간에서 필터링 또는 변경하는 중간 메소드가 있고 최종 소비를 하는 메소드가 있다
list.stream().filter(a->a%2==0).forEach(System.out::println);
// list로 부터 조건을 만족하는 원소만 뽑아서 리스트를 작성하고 싶다면
List<Integer> result = list.stream().filter(a->a%2==0).collect(Collectors.toList());
System.out.println(list.stream().filter(a->a%2==0).count());
}
}
입력은 없고 출력은 있다
import java.util.*;
import java.util.function.*;
class SupplierSample1 implements Supplier<Integer> {
@Override
public Integer get() {
// 입력은 없고 출력은 있다
return 1;
}
}
// 우리가 사용할 서플라이어 형식 :
class SupplierSample2 implements Supplier<RuntimeException> {
@Override
public RuntimeException get() {
return new RuntimeException();
}
}
public class Test7 {
public static void main(String[] args) {
// java.util.Optional : NullPointerException에 대한 자바의 대응
// 리턴값이 반드시 존재할 경우 : public User searchUser(String username) { }
// 리턴값이 존재하지 않을 수 있는 경우 : public Optional<User> searchUser(String username) { }
// dao에서 Optional로 result가 리턴되어 왔다고 하자
Optional<Integer> result = Optional.ofNullable(null);
// result에 들어있을 수 있는 Integer를 꺼내려면 get() -> 단 값이 없으면 NoSuchElementException 예외 발생
// Integer value1 = result.get();
// 예외를 내가 원하는 예외로 바꿔주자
// 스프링에는 예외를 전담하는 컨트롤러가 있다(@ControllerAdvice)
// 검색 실패와 같이 내가 원하지 않는 결과가 나왔을 때 적절한 예외를 발생시켜 ControllerAdvice를 부르자
// 즉 작업을 할 때 바람직한 상황은 Controller에 작성, 원하지않는 상황은 ControllerAdvice에 작성하자
result.orElseThrow(()->new RuntimeException());
result.orElseThrow(RuntimeException::new);
}
}
public class BoardNotFoundException extends RuntimeException {
}
백엔드에서 View를 포함하고 있다 → 백엔드와 뷰가 함께 작업한다. 즉 자바 객체를 보내줘도 타임리프나 jsp는 처리할 수 있다
@GetMapping("/test1")
public ModelAndView test1(Integer pno) {
return new ModelAndView("test1").addObject(new Product(pno, pno+"번 상품"));
}
데이터만 있다 → 그러면 데이터를 어떻게 클라이언트쪽으로 출력할까? (자바 객체는 안된다), 스프링 부트의 경우 JSON으로 내보낸다.
@GetMapping(value="/test2", produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody Product test2(Integer pno) {
return new Product(pno, pno+"번 상품");
}
// @RequestBody, @ResponseBody
// request, response를 편지에 비유하자면 편지봉투가 있고 편지지가 있다
// (보내는 주소, 요청 주소, 데이터의 길이) 등 편지봉투에 해당하는 것이 헤더, 내용에 해당하는 것이 바디
// urlencoded로 요청, 응답 바디에 여러개의 값을 담아서 보낼 수 있다
// json의 경우는 단일 json이 요청 객체, 또는 응답 객체의 바디를 가득 채운다
// @RequestBody는 요청 객체의 바디 전체를 꺼내서 JSON으로 바꿔라
@GetMapping("/example01")
public void test2View() {
}