no image
패스트캠퍼스X야놀자: 백엔드 개발 부트캠프_2차 과제 후기
1차 과제와 비슷하게 Kakao API를 활용해서 HTTP 요청을 보내고, 응답을 받는 주제로 과제를 진행했다. 동작 - 데이터 - 객체 - 클래스 순서로 객체를 모델링 해야하는데 아직 참 어렵다. 그래도 더 나아질 부분만 남았다는 뜻이니깐 객체지향 공부를 더 해야겠다. 문제 1 JDBC를 사용하기 위해 Driver에 연결된 Connection을 인자로 받고, List list를 DB 저장소로 저장하는 메서드 이다. PreparedStatement 객체를 생성해서 사용을 하는데 Price와 Sale_price를 넣는 과정에서 SQL 문 ? 자리에 매칭이 되지 않는 문제가 있었다. intValue를 붙여줘서 잘 동작하긴 하지만 IDE에서 필요 없는 변환이라고 도움말이 뜨긴 한다. 이 부분에 대해서는 Pre..
2023.09.03
no image
패스트캠퍼스X야놀자: 백엔드 개발 부트캠프_1차 과제 후기
문제 1 과제를 처음 진행할 때 출력 반복문의 인덱스를 정하기 위해서 객체의 수를 알아내기 위해 공식 API를 참고했다. 응답내용에 meta -> total_count가 응답받은 결과의 갯수인 줄 알고 그 값을 기준으로 출력할 수 있도록 반복문을 작성했다. 결과는 아래의 표와 같다. 반경(km) total_count 실제 응답 받은 객체 수 0.3 2 2 0.5 20 15 공식 문서에는 검색 된 문서의 총 수를 응답받지만 결과가 달라서 내 코드를 신뢰할 수 없었다. HTTP 요청 테스트 방법이 익숙치 않아서 시간을 아끼고자 다른 방법을 사용했다. (추후에 HTTP 요청 테스트 하는법 공부하기) 원래는 오브젝트 정보를 받아오자마자 날 것으로 프린트하려고 했지만 List에 담아서 size()를 활용했다. 아..
2023.08.23
no image
Spring Boot 예외처리
Spring Boot의 예외 처리는 @RestControllerAdvice 를 사용한다. @RestControllerAdvice = ControllerAdvice + ResponseBody 따라서, ResponseBody와 같이 리턴하는 응답 값이 body로 설정되어 클라이언트에게 전달된다. 아래와 같이 IndexOutOfBoundsException을 발생하도록 설정하고 HTTP Get요청을 보내면 아래 그림과 같이 Http Status Code 500번과 Internal Server Error이 반환된다. @Slf4j @RestController @RequestMapping("/api") public class RestApiBController { @GetMapping(path = "") public ..
2023.08.01
no image
자바 Optional<T>
Optional이 등장한 계기 : 메소드가 반환할 결과 값이 '없음'을 명백하게 표현할 필요가 있고, null 을 반환하면 에러가 발생할 가능성이 높은 상황에서 메소드의 반환 타입으로 Optional 을 사용하자는 것이 Optional 을 만든 주된 목적이다. Optional 타입의 변수의 값은 절대 null 이어서는 안 되며, 항상 Optional 인스턴스를 가리켜야 한다. Optional 생성, 선언 @Override public Optional findById(Long id) { return Optional.ofNullable(store.get(id)); //Null값 까지 받을 수 있음-> Null이면 Empty 객체 생성 //Optional.of(T) -> 명시한 T값을 가지고 있는 객체 생성,..
2023.07.28
no image
접근제어자 Protected
protected의 핵심을 요약하자면 아래와 같다. 접근제어자가 protected로 설정되었다면, 동일 패키지의 클래스 또는 해당 클래스를 상속받은 다른 패키지의 클래스에서만 접근이 가능하다. public vs protected public은 외부에서 접근할 수 있지만 protected는 외부에서 접근할 수 없다. 어떻게보면 public와 protected는 비슷하다고 볼 수 있다. protected는 원하는 클래스의 메소드를 직접 instance를 만들어 사용할 순 없지만, 상속 관계가 되는 경우 자유롭게 이용이 가능하기 때문이다. 그럼 오직 외부에서의 접근을 막기 위해 protected를 써야 하는지에 대한 궁금증이 생겼기에 구글링을 통해 OOP에서의 protected의 역할을 찾아봤다. protec..
2023.07.25
no image
LinkedList관련 for문
for each 특징 1. 배열의 값을 가져다만 사용할 수 있고 수정할 수 없다. Only read 2. 내부적인 Iterator을 생성해서 사용 3. for문과 구현 방식에 대한 성능 차이는 없다.(List 제외) 4. 인덱스를 사용할 수 없다. 평범한 for문 구조 String[] numbers = {"one", "two", "three"}; for(int i=0; i
2023.07.21
no image
자바의 연산자
연산자 : 연산을 수행하는 기호 피연산자 : 연산자의 작업 대상 연산자의 종류 - 산술 연산자 - 비교 연산자 - 논리 연산자 - 대입 연산자 - 형 변환, 삼항, instanceof 연산자 종류 연산자 설명 산술 연산자 + - * / % > 사칙, 비트, 나머지 연산자 비교 연산자 > OR 이므로 ||기호의 오른쪽 항부터 수행된다. https://johngrib.github.io/wiki/ternary-ope..
2023.07.19
no image
자바 변수, 자료형의 종류
프로그래밍에서 변수(Variable)란 하나의 값을 저장할 수 있는 저장공간을 의미한다. 변수의 이름을 지을 때 주의할 점 - 숫자로 변수의 이름을 시작할 수 없다. - $, _이외의 문자는 변수의 이름에 사용할 수 없다. - 키워드(for, if, int)는 사용할 수 없다. 기본 자료형은 4가지로 정수형, 실수형, 논리형, 문자형이 존재하며 각 바이트는 아래 표와 같다. 정수형(byte, short, int, long) byte(1) < short(2) < int(4) < long(8) 바이트 순이며 기본 자료형은 int(4)이다. 바이트 크기에 대한 값의 표현 범위는 아래 표와 같다. 실수형(float, double) 실수는 정수보다 정밀하기 때문에 부동 소수점 방식을 사용한다. 부동 소수점 : 소..
2023.07.18
no image
01_ SPR - 단일 책임 원칙
01_ SPR (Single Responsibility Principle) 단일 책임 원칙 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다. - 하나의 클래스에 역할과 책임이 많기 때문에 객체 지향 특성을 가지지 못함 - 하나의 클래스가 역할과 책임에 따라 4개의 클래스로 분리 - 단일 책임 원칙은 속성, 메서드, 패키지, 모듈, 컴포넌트, 프레임워크 등에도 적용할 수 있다.
2023.02.20

 1차 과제와 비슷하게 Kakao API를 활용해서 HTTP 요청을 보내고, 응답을 받는 주제로 과제를 진행했다. 

동작 - 데이터 - 객체 - 클래스 순서로 객체를 모델링 해야하는데 아직 참 어렵다. 그래도 더 나아질 부분만 남았다는 뜻이니깐 객체지향 공부를 더 해야겠다.

 

문제 1

[saveAllEntity.class]

 JDBC를 사용하기 위해 Driver에 연결된 Connection을 인자로 받고, List<BookDto> list를 DB 저장소로 저장하는 메서드 이다. PreparedStatement 객체를 생성해서 사용을 하는데 Price와 Sale_price를 넣는 과정에서 SQL 문 ? 자리에 매칭이 되지 않는 문제가 있었다. intValue를 붙여줘서 잘 동작하긴 하지만 IDE에서 필요 없는 변환이라고 도움말이 뜨긴 한다. 이 부분에 대해서는 PreparedStatement 에 대해 더 알아봐야 할 것 같다.

 

느낀 점

 

 1차 과제는 빈 프로젝트에서 아무런 설계 없이, 클래스를 하나 하나 만들어 가면서 과제를 진행했다. 점점 진행 할 수록 과제가 산으로 가고 있다는 느낌을 받았다. 지난 1차 과제와는 다르게 공책에 연필로 직접 관계도를 그려가면서 클래스를 설계했다. DB와 관계를 가지는 JdbcRepository.class를 구상하고, Kaka API와 통신하는 HttpClient.class를 중심으로 과제를 진행했다. 멘토님께서 말씀해주신 방식은 동작 - 데이터 - 객체 - 클래스 순서로 객체를 모델링 이 순서이다. 이 문장을 봤을 때, 아직 어떻게 시작을 해야할 지 막막하다는 생각이 들었다. 멘토님께서 추천해주신 책을 주문을 하고 그 책을 읽어보면서 객체지향에 관한 개념을 다시 한 번 정리해야할 것 같은 필요성을 느꼈다. 

 

[클래스 설계도]

 

실행 화면, 결과 화면

 

[실행 화면]

 

[패키지 목록]

 

[카카오 디벨로퍼 API 응답 https://developers.kakao.com/docs/latest/ko/local/dev-guide#search-by-category]

문제 1

 과제를 처음 진행할 때 출력 반복문의 인덱스를 정하기 위해서 객체의 수를 알아내기 위해 공식 API를 참고했다. 응답내용에 meta -> total_count가 응답받은 결과의 갯수인 줄 알고 그 값을 기준으로 출력할 수 있도록 반복문을 작성했다. 결과는 아래의 표와 같다.

 

반경(km) total_count 실제 응답 받은 객체 수
0.3 2 2
0.5 20 15

 

 공식 문서에는 검색 된 문서의 총 수를 응답받지만 결과가 달라서 내 코드를 신뢰할 수 없었다. HTTP 요청 테스트 방법이 익숙치 않아서 시간을 아끼고자 다른 방법을 사용했다. (추후에 HTTP 요청 테스트 하는법 공부하기)  원래는 오브젝트 정보를 받아오자마자 날 것으로 프린트하려고 했지만 List에 담아서 size()를 활용했다.

 

 아래의 그림은 API로 검색할 땐 결과가 나오지 않지만, 카카오 맵에서는 결과가 표시된다는 질문에 대한 답변이다.

 total_count의 "검색 된 문서의 수" 가 API 내에서의 검색 수인지, 카카오 맵에서의 검색 수인지 잘 모르겠지만 값이 다른 이유라고 의심해볼까...?

 

[카카오 API Q&A 답변 https://devtalk.kakao.com/t/topic/130581]

 

문제 2

 과제의 실행 결과 화면에서는 "00시 ㅁㅁ아파트" 와 같이 아파트 이름의 주소를 입력해 값을 응답받았는데 같은 주소를 내 코드에 실행시켜보니 실패했다. 이유를 찾다보니 정확하지 않지만 카카오 API 공지사항에서 아래와 같은 글을 찾았다.

 

[카카오 API 공지사항 https://devtalk.kakao.com/t/api-upgrade-notice-search-address-api-for-better-search-quality/112161]

 

과제의 예시처럼 ㅁㅁ 아파트로는 검색이 안되었지만, 해당 아파트의 도로명 주소? 00도 00시 00동 으로 검색하니 잘 동작하였다. 위의 문제인지는 잘 모르겟지만 일단 마무리 지었다.

 

++ 그룹 스터디 조원분들이 알려주셨다. 나는 "주소 검색하기"로 x, y 좌표를 구했는데 "키워드 검색하기" 로 검색을 했어야 했다. 다음부턴 문제를 잘 읽자 ㅎㅎ

 

느낀점

 

 

 Codecomplexity 를 쓰니 코드의 복잡성에 대해 다시 생각하게 된다. 위의 코드는 list를 출력하는 역할을 하는 메서드이다. 두 개의 메서드 모두 같은 기능을 하지만 어떻게 구현하느냐에 따라 코드의 CodeComplexity를 점수로 나타내주는 플러그인을 통해 메서드를 분리한다던지, 의존성을 줄인다던지 등 완벽하진 않지만 더 나은 코드를 작성할 수 있는지에 대한 고민을 할 수 있는 기회를 자연스럽게 갖게 되었다.

 

Spring boot를 처음 공부를 할때는 어노테이션을 기반으로 한 생성자 주입, 예외처리, 벨리데이션을 배웠는데

순수 자바 코드로 구현을 하려니깐 막막했다. 예외를 잡기위해 try catch를 남발하고 의존성 주입을 lombok 어노테이션으로만 구현을 했었는데 필드주입으로 구현한 점 등, 

 

멘토님께서 DTO와 Interface를 언급해주셨다. 주먹구구식으로 개발한 내 과제에서 코드를 수정하긴 했지만 DTO가 어떤 역할을 하는지, 왜 필요한지 자세하게 설명할 수 없었고 깡통 인터페이스를 implements했지만 의미가 있는지 등 의미 없이 코드를 가져다 붙인 것 같다. 다음 과제부터는 주먹구구식으로 시작하지 말고 객체 설계, 연관 관계를 잘 고려해 개발을 똑똑하게 시작해야겠다.

 

 

[과제 실행화면 1]
[과제 실행화면 2]

 

Spring Boot의 예외 처리는 @RestControllerAdvice 를 사용한다.

 

@RestControllerAdvice = ControllerAdvice + ResponseBody 

 

따라서, ResponseBody와 같이 리턴하는 응답 값이 body로 설정되어 클라이언트에게 전달된다.

아래와 같이 IndexOutOfBoundsException을 발생하도록 설정하고 HTTP Get요청을 보내면 아래 그림과 같이

Http Status Code 500번과 Internal Server Error이 반환된다. 

 

@Slf4j
@RestController
@RequestMapping("/api")
public class RestApiBController {

    @GetMapping(path = "")
    public void hello() {
        var list = List.of("hello");

        var element = list.get(1);

        log.info("element : {}", element);
    }
}

 

 

예외가 발생해도 자연스럽게 응답을 내려주기 위해서는 서버에서 컨트롤러에 대한 예외를 처리해야 한다.

try catch로 직접 처리할 수 있지만 코드 길이가 길어질 수 있으므로 @RestControllerAdvice 를 사용한 Handler 클래스를 만들어서 사용한다.

 

@RestControllerAdvice 가 붙은 클래스는 Rest API Controller에서 예외가 일어나는 것을 감지

@ExceptionHandler로 어떠한 예외를 캐치할 것인지 선언 가능, 아래의 코드에선 (IndexOutOfBoundsException)을 value 값으로 설정했으므로 해당 예외를 처리한다.

 

@Slf4j
@RestControllerAdvice
//-> 아래 클래스는 rest api를 사용하는 곳에 에러를 감지함
public class RestApiExceptionHandler {

    @ExceptionHandler(value = { IndexOutOfBoundsException.class })
    public ResponseEntity outOfBound(
            IndexOutOfBoundsException e
    ){
        log.error("IndexOutOfBoundsException",e);
        return ResponseEntity.status(200).build();
    }
}

 

ResponseEntity를 반환하기에 HttpStatus 코드를 200으로 변경하여 반환하면 이전과 다르게 예외가 핸들링된 것을 볼 수 있다. @ExceptionHandler(value = { IndexOutOfBoundsException.class }) 의 value 값을 Exception.class로 바꾸게 되면 전체적인 Exception 하위의 예외들을 한 번에 처리할 수 있다.

 

 

다른 방법으로 따로 ExceptionHandler을 관리하지 않고, 컨트롤러 단에서 직접 @ExceptionHandler을 사용하여 해결할 수 있다. 아래 코드는 위와 같은 예제에서 Controller 내부에서 @ExceptionHandler 를 적용한 코드이다. 코드 길이가 길어질 수 있으므로  이 방법은 특별한 컨트롤러에서만 사용을 한다.

 

@Slf4j
@RestController
@RequestMapping("/api/b")
public class RestApiCController {

    @GetMapping("")
    public void hello() {
        throw new NumberFormatException("number format exception");
    }

    @ExceptionHandler(value = NumberFormatException.class) //->글로벌로 가지 않고 여기서 해결
    public ResponseEntity numberFormatException(
            NumberFormatException e
    ){
        log.error("RestApiCController", e);
        return ResponseEntity.ok().build();
    }
}

 

 value 값에 클래스를 명시하는 것 이외에도 basePackages를 명시할 수 있다. @RestControllerAdvice 의 value값에 패키지 경로를 명시하게 되면 해당 패키지에 속한 컨트롤러에서 일어나는 모든 예외를 하나의 핸들러로 관리할 수 있다.

 

@Slf4j
@RestControllerAdvice(basePackages = "com.example.exception.controller") // 패키지 명시
@Order(1)
public class RestApiExceptionHandler {

    @ExceptionHandler(value = { IndexOutOfBoundsException.class })
    public ResponseEntity outOfBound(
            IndexOutOfBoundsException e
    ){
        log.error("IndexOutOfBoundsException",e);
        return ResponseEntity.status(200).build();
    }

    @ExceptionHandler(value = NoSuchElementException.class)
    public ResponseEntity<Api> noSuchElement(
            NoSuchElementException e
    ){
        log.error("",e);

        var reponse = Api.builder()
                .resultCode(String.valueOf(HttpStatus.NOT_FOUND))
                .resultMessage(HttpStatus.NOT_FOUND.getReasonPhrase())
                .build();

        return ResponseEntity.status(HttpStatus.NOT_FOUND)
                .body(reponse);
    }
}

 

 

ExceptionHandler가 2개 이상인 경우 @Order을 통해 먼저 처리될 수 있는, 우선순위를 부여할 수 있다.

 

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

 

@Slf4j
@RestControllerAdvice(basePackages = "com.example.exception.controller") // 패키지 명시
@Order(1)
public class RestApiExceptionHandler {
@Order <<<< spec >>>>
int value() default Ordered.LOWEST_PRECEDENCE;
int LOWEST_PRECEDENCE = Integer.MAX_VALUE;

@Order의 우선순위를 설정할 때 기본 값은  LOWEST_PRECEDENCE = MAX_VALUE 로 설정되어 있다.

@Order가 있을 경우,  value가 낮은 친구 먼저 처리된다.

 

Order     vs  Order(1) : default가 MaxInt이므로 그보다 낮은 1이 실행

Order(2) vs Order(3) : 2가 실행

Order      vs Order : Class 이름 순으로 실행 

먼저 처리되고 싶으면 value에 낮은 값을, 나중에 처리되고 싶으면 높은 값을 주면 된다.

 

위의 GlobalExceptionHandlerRestApiExceptionHandler에서 (처리하지 못한, 예상치 못한) 나머지 예외를 받아내기 위한 최후의 역할을 하므로RestApiExceptionHandler 의 Order(value)값 보다 높게 값을 설정하여 RestApiExceptionHandler가 먼저 처리되게 한다.

 

 

(위의 예시 상황은 Oder가 없는 경우 vs 있는 경우임... 만약 Order가 둘 다 있을 경우엔 값이 낮은 친구부터)

 

 

Optional이 등장한 계기 :

 

 메소드가 반환할 결과 값이 '없음'을 명백하게 표현할 필요가 있고, null 을 반환하면 에러가 발생할 가능성이 높은 상황에서 메소드의 반환 타입으로 Optional 을 사용하자는 것이 Optional 을 만든 주된 목적이다.
Optional 타입의 변수의 값은 절대 null 이어서는 안 되며, 항상 Optional 인스턴스를 가리켜야 한다.

 

 

Optional<T> 생성, 선언

   @Override
   public Optional<Member> findById(Long id) {
        return Optional.ofNullable(store.get(id)); //Null값 까지 받을 수 있음-> Null이면 Empty 객체 생성
        
        //Optional.of(T) -> 명시한 T값을 가지고 있는 객체 생성, Null일 경우 Error
        //Optional.empty() ->비어있는 객체 생성
    }

 

 

isPresent(True or False), ifPresent(Consumer<? super T> action)

  값이 존재하면 True or False, 값이 존재하면 action을 취하라

    private void validateDuplicateMember(Member member) {
        memberRepository.findByName(member.getName())
                        .ifPresent(m ->{
            throw new IllegalStateException("이미 존재하는 회원입니다.");
        });
    }

 

옵셔널을 활용한 NPE 지옥 탈출하기

 

https://www.daleseo.com/java8-optional-before/

 

자바8 Optional 1부: 빠져나올 수 없는 null 처리의 늪

Engineering Blog by Dale Seo

www.daleseo.com

 

옵셔녈 관련 Optional<> 

 

 

옵션 커맨드 화살표 (화면 이동? 전환?)

옵션 커맨드 v (반환값을 받을 변수 자동생성?)

illegalstateException (테스트 예외처리)

컨트롤 r (이전 실행 실행)

 

 

 

https://dev-coco.tistory.com/178

 

[Java] Optional 올바르게 사용하기

개요 Java 언어 설계자인 Brian Goetz는 Optional 을 만든 의도를 다음과 같이 공식 API 문서에 작성해 두었다. API Note: Optional is primarily intended for use as a method return type where there is a clear need to represent "no re

dev-coco.tistory.com

 

protected의 핵심을 요약하자면 아래와 같다.

 

접근제어자가 protected로 설정되었다면, 동일 패키지의 클래스 또는 해당 클래스를 상속받은 다른 패키지의 클래스에서만 접근이 가능하다.

 

 

public vs protected 

 

public은 외부에서 접근할 수 있지만 protected는 외부에서 접근할 수 없다.

 

어떻게보면 public와 protected는 비슷하다고 볼 수 있다.

 

protected는 원하는 클래스의 메소드를 직접 instance를 만들어 사용할 순 없지만, 상속 관계가 되는 경우

자유롭게 이용이 가능하기 때문이다.

 

그럼 오직 외부에서의 접근을 막기 위해 protected를 써야 하는지에 대한 궁금증이 생겼기에

구글링을 통해 OOP에서의 protected의 역할을 찾아봤다.

 

protected는 잠재적으로 자식 클래스가 오버라이드(Override)해서 바꾸어야 할 경우를 고려한 접근제어자이다.

아래의 새(Bird) 코드와 타조(Ostrich)클래스 예시를 보자

 

public class Bird {

    void fly() {
        System.out.println("I am flying");
    }

    protected void moveFast() {
        fly();
    }
}

 

public class Ostrich extends Bird{
    public static void main(String[] args) {
        Ostrich ostrich = new Ostrich();
        ostrich.moveFast();
    }

    void run(){
        System.out.println("I am running");
    }
    protected void moveFast(){
        run();
    }
}

 

타조는 Bird 클래스를 통해 moveFast() 메서드를 상속받았지만 다른 새들과 달리 fly()를 사용할 수 없기에

불가피하게 moveFast()를 오버라이드를 통해 변경해야 한다. 따라서 변경이 짐작되는 메서드는 protected를 통해 변경의 요지를 표시하는 용도로 사용될 수 있다.

 

Object, Clonabel인터페이스, clone()메서드

 

위 사진은 Object에서 사용할 수 있는 메서드 종류이다. clone, finalize 메서드는 protected 접근제어자를 가진다.

 

finalize메서드는 Deprecated 

 

Clonabel 인터페이스(믹스인 용도) : 일반적인 인터페이스랑 다르다. 아무 내용이 없다, clone()메서드의 동작방식을 결정한다. (믹스인 : 객체지향에서 다른 클래스에서 사용할 목적으로 만들어진 클래스) Clonable 인터페이스를 구현하지 않은 상태에서 clone()를 호출하면 CloneNotSupportedException을 던진다.

 

기본적인 사용법은 clone()를 사용하려는 클래스에서 Clonable 인터페이스를 구현하고, clone()를 오버라이딩 해서 사용한다.

 

왜 clone()를 오버라이딩 해야하냐

아래의 블로그를 참조하자 아직 헷갈린다.

 

https://cinnamonc.tistory.com/273

 

[Java 공부하기] clone 메소드를 오버라이딩 해서 사용해야하는 이유에 대해서 찾아보기

clone 메소드를 공부하다가 멘붕이 와서 한번 정리하기로 했다. 일단 clone 메소드는 Object의 메소드이며, 접근수준 지시자는 protected이다. 이 clone 메소드를 다른 클래스에서 사용하려면 Cloneable 인

cinnamonc.tistory.com

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=2feelus&logNo=220576845725 

 

Java에서 protected 의 의미와 용도

1. Java의 접근자(modifier)들 Java 의 필드와 메소드들에 대한 접근 권한 제어를 modifier라고 한다.&nb...

blog.naver.com

 

for each 특징

 

1. 배열의 값을 가져다만 사용할 수 있고 수정할 수 없다. Only read

2. 내부적인 Iterator을 생성해서 사용

3. for문과 구현 방식에 대한 성능 차이는 없다.(List 제외)

4. 인덱스를 사용할 수 없다.

 

 

평범한 for문 구조

String[] numbers = {"one", "two", "three"};
for(int i=0; i<numbers.length; i++) { //평범한 for문 출처 "점프 투 자바"
    System.out.println(numbers[i]);
}

 

for each문 구조 

String[] numbers = {"one", "two", "three"};
for(String number: numbers) { //for each 문 
    System.out.println(number);
}

 

for (type var: iterate) {
    body-of-loop
}

 

 

ArrayList vs LinkedList 시간복잡도 차이

import java.util.ArrayList;
import java.util.LinkedList;

public class ListTest {

    public static void main(String[] args) {

        long beforeTime, afterTime;
        ArrayList<Integer> Alist = new ArrayList<Integer>();
        LinkedList<Integer> Llist = new LinkedList<Integer>();

        for(int i = 0; i < 100000; i++){
            Alist.add(i);
            Llist.add(i);
        }


        beforeTime = System.currentTimeMillis();
        for(int i = 0; i < 100000; i++){
            Alist.get(i);
        }
        afterTime = System.currentTimeMillis();
        System.out.println("ArrayList 수행시간 : " + (afterTime - beforeTime));


        beforeTime = System.currentTimeMillis();
        for(int i = 0; i < 100000; i++){
            Llist.get(i);
        }
        afterTime = System.currentTimeMillis();
        System.out.println("LinkedList 수행시간 : " + (afterTime - beforeTime));
    }
}

 

ArrayList 수행시간 : 1
LinkedList 수행시간 : 3769

 

 

 

 

LinkedList에서 for문을 사용하면 안되는 이유

-  배열은 index크기만큼 더해서 값에 접근함 (0번의 주솟값 + 배열 한 칸의 byte 크기 = 찾으려는 공간)

- 연결리스트는 고정된 변화값으로 주소값이 연속되지 않음 주소가 불연속적 : 따라서 시간 복잡도 O(n^2)

 

 

LinkedList에서 for each 사용 

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;

public class ListTest {


    public static void main(String[] args) {

        long beforeTime, afterTime;
        ArrayList<Integer> Alist = new ArrayList<Integer>();
        LinkedList<Integer> Llist = new LinkedList<Integer>();

        for(int i = 0; i < 100000; i++){
            Alist.add(i);
            Llist.add(i);
        }


        beforeTime = System.currentTimeMillis();
        for(int i = 0; i < 100000; i++){
            Alist.get(i);
        }
        afterTime = System.currentTimeMillis();
        System.out.println("ArrayList for 수행시간 : " + (afterTime - beforeTime));


        beforeTime = System.currentTimeMillis();
        for(int i = 0; i < 100000; i++){
            Llist.get(i);
        }
        afterTime = System.currentTimeMillis();
        System.out.println("LinkedList for 수행시간 : " + (afterTime - beforeTime));


        beforeTime = System.currentTimeMillis();
        for(int i : Llist){
            //int sum += i; TODO
        }
        afterTime = System.currentTimeMillis();
        System.out.println("LinkedList for-each 수행시간 : " + (afterTime - beforeTime));


    }

}

 

ArrayList for 수행시간 : 1
LinkedList for 수행시간 : 3564
LinkedList for-each 수행시간 : 4

 

 

Iterator ?

자바 컬렉션에 저장되어 있는 요소들을 순화하는 인터페이스

요소에 대해 내부적으로 객체를 생성한 후 순차적으로 조회한다.

사용법이 쉽지만 객체를 생성하는 부분에서 시간이 걸린다.

 

Collection ?

자바에서 제공하는 자료구조들의 인터페이스, List, ArrayList, Stack, Queue, LinkedList 등이 있다.

따라서 이러한 컬렉션 인터페이스를 상속받는 클래스들에 대해 Iterator 인터페이스 사용이 가능하다.

 

 

Collection 구조 / 위키백과

 

List Iterator ?

 Iterator 인터페이스에서 List에 맞게 기능이 추가된 인터페이스이다. 추가, 요소 대체, 역방향 접근, 앞/뒤 인덱스 확인 등

 

 사용 상황 : List요소의 수정이 필요한 경우에 사용한다.

 

 

 

for, for each, Iterator, forEach(),,,  더 알아보기

 

 

 

list . foreach? (Stream API)

for each vs 이터레이터

 

참조 : https://www.geeksforgeeks.org/how-to-iterate-linkedlist-in-java/

 

How to Iterate LinkedList in Java? - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org

https://you88.tistory.com/39

 

[Java] 자바 List 탐색/순회 (for문, 향상된for문, ListIterator)

자바는 List 인터페이스를 구현한 ArrayList, LinkedList, Vector, Stack 클래스 등을 제공한다. 따라서 List의 탐색, 순회 방법을 이용하여 이러한 클래스들의 탐색, 순회가 가능하다. 자바의 버전이 올라가

you88.tistory.com

 

 

연산자 : 연산을 수행하는 기호

피연산자 : 연산자의 작업 대상

 

 연산자의 종류

 

- 산술 연산자

- 비교 연산자

- 논리 연산자

- 대입 연산자 

- 형 변환, 삼항, instanceof 연산자

 

종류 연산자 설명
산술 연산자 + - * / % << >> 사칙, 비트, 나머지 연산자
비교 연산자 > < <= >= == != 크기 비교 연산자
논리 연산자 & | ! ~ ^ AND, OR, XOR 등 연산
대입 연산자 = 변수에 값을 대입
기타 (type) ?: instanceof 형변환, 삼항, instanceof 연산자

 

연산자 우선순위 예제

예시 설명
x << 2 + 1  쉬프트 연산자는 덧셈 연산자보다 우선순위가 낮다.
data & 0xFF == 0 비트 연산자(&)는 비교 연산자보다 우선순위가 낮아 비교연산 이후 비트연산이 수행된다.
x < -1 || x > 3 && x < 5 논리 연산자는 AND > OR 이므로 ||기호의 오른쪽 항부터 수행된다.

https://johngrib.github.io/wiki/ternary-operator-and-null-pointer-exception/#%EB%B6%80%EB%A1%9D-a-java-13-%EC%8A%A4%ED%8E%99%EC%9D%98-1525-%EC%A0%88

 

 

 

Java의 삼항 연산자와 Null Pointer Exception

언박싱하다 NPE가 터지는 것이 원인

johngrib.github.io

 

 

프로그래밍에서 변수(Variable)란 하나의 값을 저장할 수 있는 저장공간을 의미한다.

 

변수의 이름을 지을 때 주의할 점

 - 숫자로 변수의 이름을 시작할 수 없다.
 - $, _이외의 문자는 변수의 이름에 사용할 수 없다.

 - 키워드(for, if, int)는 사용할 수 없다.

 

 

기본 자료형은 4가지로 정수형, 실수형, 논리형, 문자형이 존재하며 각 바이트는 아래 표와 같다.

 

[기본 자료형의 종류]

 

정수형(byte, short, int, long)

 

byte(1) < short(2) < int(4) < long(8) 바이트 순이며 기본 자료형은 int(4)이다. 바이트 크기에 대한 값의 표현 범위는 아래 표와 같다.

 

[정수형 표현 범위]

 

실수형(float, double)

 

실수는 정수보다 정밀하기 때문에 부동 소수점 방식을 사용한다.

 

부동 소수점 : 소수점의 위치를 고정하지 않고 그 위치를 나타내는 수를 따로 적는 것, 가수와 지수로 표현한다.

 

[float 실수 표현법]

 

 

[실수형 표현 범위]

 

부동 소수점 방식의 오류

 

지수와 가수로 나타내는 부동 소수점 방식에서는 지수부가 0을 표현할 수 없기 때문에 약간의 오차가 발생한다.

 

 

[부동 소수점 방식 오류]
[실행 결과]

 

 

 

 

 

 

 

 

출처 :

 

https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EA%B8%B0%EB%B3%B8-%EC%9E%90%EB%A3%8C%ED%98%95-%EC%A2%85%EB%A5%98-%EC%B4%9D%EC%A0%95%EB%A6%AC-int-double-char-String

 

https://sujinhope.github.io/2020/09/21/CS-%EA%B3%A0%EC%A0%95-%EC%86%8C%EC%88%98%EC%A0%90,-%EB%B6%80%EB%8F%99-%EC%86%8C%EC%88%98%EC%A0%90.html

01_ SPR - 단일 책임 원칙

균민이
|2023. 2. 20. 16:31

01_ SPR (Single Responsibility Principle) 단일 책임 원칙


클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다.

 

[그림 1] 남자 클래스와 의존 관계에 있는 다른 클래스

 

- 하나의 클래스에 역할과 책임이 많기 때문에 객체 지향 특성을 가지지 못함

 

[그림 2] 단일 책임 원칙을 적용한 남자 클래스

 

- 하나의 클래스가 역할과 책임에 따라 4개의 클래스로 분리

- 단일 책임 원칙은 속성, 메서드, 패키지, 모듈, 컴포넌트, 프레임워크 등에도 적용할 수 있다.