Arrays

  • 배열을 다루기 편리한 메서드(static) 제공
  • 배열의 출력 toString()
  • 배열의 복사 copyOf(), copyOfRange()
  • 배열 채우기 -fill(), setAll()
  • 배열의 정력과 검색 - sort(), binarySearch()
    • binarySearch하기 전에는 반드시 배열 정렬 .sort() 먼저
  • 다차원 배열의 출력 deepToString()
  • 다차원 배열의 비교 - deepEquals()
  • 배열을 List로 변환 asList(Object ... a)
  • 람다와 스프림 관련 - parallel(), spliterator(), stream()

arrays

 

Comparator 와 Comparable

  • 객체 정렬에 필요한 메서드(정렬기준 제공)를 정의한 인터페이스
  • Comparable - 기본 정렬기준을 구현
  • Comparator - 기본 정렬기준 외에 다른 기준으로 정렬하고자할 때 사용
public interface Comparator {
	int compare(Object o1, Object o2); //o1, o2 두 객체 비교
    boolean equals(Object obj); //equals를 오버라이딩하라는 뜻
  }
  
public interface Comparable {
	int compareTo (Object o); // 주어진 객체 o 를 자신과 비교
 }

 

public final class Integer extends Number implements Comparable {
	...
    public in t compareTo(Integer anotherInteger) {
    	int v1 = this.value;
        int v2 = anotherInteger.value;
        //같으면 0, 오른쪽값이 크면 -1, 작으면 1을 반환
        return (v1 < v2 ? -1: (v1==v2? 0 :1));
    }
    ...
}

 

예제 Ex11_7

import java.util.*;

class Ex11_7 {
    public static void main(String[] args) {
        String[] strArr = {"cat", "Dog", "lion", "tiger"};

        Arrays.sort(strArr); // String의 Comparable 구현에 의한 정렬
        System.out.println("strArr=" + Arrays.toString(strArr));

        Arrays.sort(strArr, String.CASE_INSENSITIVE_ORDER); // 대소문자 상관 없이 정렬
        System.out.println("strArr=" + Arrays.toString(strArr));

        Arrays.sort(strArr, new Descending()); //역순으로 정렬
        System.out.println("strArr=" + Arrays.toString(strArr));
    }
}

class Descending implements Comparator {
    public int compare(Object o1, Object o2){
        if( o1 instanceof Comparable && o2 instanceof Comparable) {
            Comparable c1 = (Comparable)o1;
            Comparable c2 = (Comparable)o2;
            return c1.compareTo(c2) * -1 ; //-1을 곱해서 기본 정렬방식의 역으로 변경
            // 또는 c2.compareTo(c1)와 같이 순서를 바꿔도 됨
        }
        return -1;
    }
}

 

Integer와 Comparable

  • 삼항연산자가 기본사칙연산보다 상대적으로 빠르다 (2~3% 정도)

 

버블정렬 bubble sort 코드

  • 서로 인접한 두 원소의 대소를 비교하고, 조건에 맞지 않다면 자리를 교환하며 정렬하는 알고리즘
static void sort(int[] intArr) {
	for(int i=0; i<intArr.length-1;i++) {
    	for(int j=0; j<intArr.length-1-i; j++) {
        int tmp =0;
        
        if(intArr[j] > intArr[j+1]) {
        	tmp = intArr[j];
            intArr[j] = intArr[j+1];
            intArr[j+1] =tmp;
            }
     }
}
  • 버블 정렬은 첫 번째 자료와 두 번째 자료를, 두 번째 자료와 세 번째 자료를, 세 번째와 네 번째를, … 이런 식으로 (마지막-1)번째 자료와 마지막 자료를 비교하여 교환하면서 자료를 정렬함
  • 1회전을 수행하고 나면 가장 큰 자료가 맨 뒤로 이동하므로 2회전에서는 맨 끝에 있는 자료는 정렬에서 제외되고, 2회전을 수행하고 나면 끝에서 두 번째 자료까지는 정렬에서 제외된다. 이렇게 정렬을 1회전 수행할 때마다 정렬에서 제외되는 데이터가 하나씩 늘어난다.

https://gyoogle.dev/blog/algorithm/Bubble%20Sort.html

 

거품 정렬(Bubble Sort) | 👨🏻‍💻 Tech Interview

거품 정렬(Bubble Sort) Goal Bubble Sort에 대해 설명할 수 있다. Bubble Sort 과정에 대해 설명할 수 있다. Bubble Sort을 구현할 수 있다. Bubble Sort의 시간복잡도와 공간복잡도를 계산할 수 있다. Abstract Bubble S

gyoogle.dev

 

 

 

 

 

 

 

 

 

 

Iterator

Iterator, ListIterator, Enumeration

  • 컬렉션에 저장된 데이터를 접근하는데 사용되는 인터페이스
  • iterator만 쓰면됨 (Enumeration은 Iterator의 옛날 버전)
  • ListIterator는 Iterator의 접근성을 향상 시킨것

  • 컬렉션에 저장된 요소들을 읽어오는 방법을 표준화한 것
  • 컬렉션에 iterator()를 호출해서 Iterator를 구현한 객체를 얻어서 사용
List list = new ArrayLsit(); //다른 컬렉션으로 변경할 때는 이 부분만 고치면 된다.
Iterator it = list.interator();

while(it.hasNext()) { //boolean has Next()
	System.out.println(it.next()); 
  }
  • iterator는 1회용이라 다쓰고나면 다시 얻어와야 한다

 

Map과 Iterator

  • Map에는 iterator()가 없음
  • Keyset(), entrySet(), values()를 호출해야함
Map map = new HashMap();
.
.
.
Iterator it = map.entrySet().iterator();

 

 

 

  • stack: LIFO 구조, 마지막에 저장된 것을 제일 먼저 꺼냄
  • Queue: FIFO 구조, 제일 먼저 저장한 것을 제일 먼저 꺼냄

stack and queue

 

Stack 메서드

stack 메서드

 

Queue 메서드

 

  • Queue는 인터페이스
  • stack은 클래스

 

인터페이스를 구현한 클래스 찾기

  • Queue를 구현한 클래스를 사용

Java API문서

  • 스택 활용 예 - 수식계산, undo/redo, 웹브라우저 뒤로/앞으로
  • 큐 활용 예 - 최근사용문서(recent files), 인쇄작업 대기목록, buffer
  • 배열의 장점: 구조가 간단하고 데이터를 읽는데 걸리는 시간(access time)이 짧다
  • 배열의 단점:
    • 크기를 변경할 수 없다 -> 새로운 배열을 생성 후 데이터를 복사해야함
    • 크기 변경을 피하기 위해 충분히 큰 배열을 생성하면 메모리 낭비
    • 비순차적인 데이터의 추가, 삭제에 시간이 많이 걸림
    • 데이터를 추가하거나 삭제하기 위해, 다른 데이터를 옮겨야 함
    • 순차적인 데이터 추가(끝에 추가)와 삭제(끝부터 삭제)는 빠름

LinkedList

LinkedList는 배열의 단점(1. 크기변경 x 2. 추가삭제시간 많이걸림) 을 보완

  • LinkedList는 불연속적으로 존재하는 데이터를 연결(link)
  • 불연속적
class Node{
	Node next; 
        Object obj;
        }
  • 단 한번의 참조변경으로 데이터 삭제 가능
  • 한번의 Node 객체생성과 두번의 참조 변경만으로 데이터 추가 가능

 

LinkedList - 이중 연결 리스트

  • LinkedList - 데이터 접근성이 나쁨
  • doubly linked list - 이중 연결 리스트, 접근성 향상
class Node{
	Node next; 
    Node previous;
        Object obj;
        }

 

  • doubly circular linked list - 이중 원형 연결리스트
  • 자바에서는 이중연결리스트로 구현되어 있음

 

ArrayList vs. LinkedList 

  • ArrayList가 추가할 때 더 빠름
  • 순차적으로 삭제할 때 ArrayList가 빠름
  • 비순차적으로 데이터 추가/삭제 - LinkedList가 빠름 (20배는 차이남)
  • 접근시간(access time)- ArrayList가 빠름 (400배 이상)
  • 읽기는 ArrayList가 빠르고 추가/삭제는 LinkedList가 빠름
  • LinkedList는 데이터가 많을수록 접근성이 떨어짐

 

 

 

 

 

 

 

ArrayList

  • ArrayList는 기존의 Vector를 개선한 것으로 구현원리와 기능적으로 동일
  • List인터페이스를 구현하므로, 저장순서가 유지되고 중복 허용
  • 데이터의 저장공간으로 배열을 사용
  • List 인터페이스 구현
  • 모든 종류의 객체 저장 가능

 

ArrayList 메서드

  • ArrayList()
  • ArrayList(Collection c)
  • ArrayList(int initialCapacity)
  • boolean add(Object o)
  • void add(int index Object element)
  • boolean addAll(Collection c)
  • boolean addAll(int index, Collection c)
  • boolean remove(Object o)
  • Object remove(int index)
  • boolean removeAll(Collection c)
  • void clear()
  • int indexOf(Object o)
  • int lastIndexOf(Object o)
  • boolean contains(Object o)
  • Object get(int index)
  • Object set(int index, Object element)
  • List subList(int fromindex, int toindex)
  • Object[] toArray() 
  • Object[] toArray(Object[] a)
  • boolean isEmpty ()
  • void trim ToSize()
  • int size() (저장된 객체 갯수 반환)

 

list1:[0,1,2,3,4,5]
list2:[0,2,4]

list1.containsAll(list2):true

containsAll: 포함하고 있는지 true/false 반환 하는 메서드

 

list1.remove(1) // 인덱스가 1인 객체를 삭제
list1.remove(new Integer(1)); // 1을 삭제

 

 

 

 

ArrayList 저장된 객체의 삭제 과정

- 마지막 객체부터 삭제하면 됨

 

 

 

 

 

  • collection: 여러 객체(데이터)를 모아 놓은 것
  • framework: 표준화, 정형화된 체계적인 프로그래밍 방식
  • collections framework:
    • 컬렉션을 다루기 위한 표준화된 프로그래밍 방식
    • 컬렉션을 쉽고 편리하게 다룰 수 있는 클래스를 제공
    • java.util 패키지에 포함. JDK1.2부터 제공
  • collection class: 다수의 데이터를 저장할 수 있음

 

컬렉션 프레임웍의 핵심 인터페이스

  • List:
    • 순서가 있는 데이터의 집합
    • 데이터의 중복을 허용
  • Set(집합):
    • 순서를 유지하지 않는 데이터의 집합
    • 데이터의 중복을 허용하지 않음
  • Map:
    • Key와 Value의 쌍(pair)로 이루어진 데이터의 집합
    • 순서는 유지되지 않으며, 키는 중복을 허용하지 않고 값은 중복 허용
    • ex) 우편번호, 지역번호

 

List 인터페이스 - 순서 o, 중복 x

 

List 인터페이스 메서드

 

Set 인터페이스 - 순서 x, 중복 x

 

 

 

Map 인터페이스 - 순서 , 중복 (키 x, 값 o)

 

JPA를 활용하여 연관관계를 맺어줘서 게시글 하나만 삭제해도 관련된 댓글이 다 삭제가 되고, 게시글 하나만 불러도 연관된 댓글이 몽땅 다 삭제되는 것을 구현하는 것에 성공했습니다. JPA는 테이블을 객체처럼 사용한다에서 흰트를 얻어서 객체처럼 넣어주고 값을 불러주고 하는 방법으로 구현했습니다. 복잡한 코드를 작성하지 않더라도 전체 게시글 조회할 때 각 게시글에 연관된 댓글들이 함께 조회가 됩니다. 어제는 중첩 for문을 돌려서 전체 게시글(+댓글) 조회를 했는데 JPA로 for문 필요 없이 간단하게 불러오게 했습니다.

am....I ..... genius? no... jjajipgi dal-in

 

JPA 연관관계 사용 게시판, 댓글 구현하기

 

Post

package com.example.post.entity;

import com.example.post.dto.PostRequestDto;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

@Getter
@Entity
@NoArgsConstructor
public class Post extends Timestamped{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String title;

    @Column(nullable = false)
    private String content;

    @Column(nullable = false)
    private String username;
//
    @ManyToOne(fetch = FetchType.LAZY)
    private User user;


// mappedBy로 연관관계 주인 설정, ManytoOne 다대일 관계설, "comment"가 외래키를 관리
    @OneToMany(mappedBy = "post", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
    private List<Comment> commentLists = new ArrayList<>();

    public Post(PostRequestDto requestDto, User user){
        this.content = requestDto.getContent();
        this.title = requestDto.getTitle();
        this.username = user.getUsername();
        this.user = user;

    }

    public void update(PostRequestDto requestDto) {
        this.content = requestDto.getContent();
        this.title = requestDto.getTitle();
    }
}
  • @ManyToOne으로 User 와의 관계를 설정해주었습니다. post를 작성한 user의 정보를 받아 올 수 있습니다. user 생성자를 작성했습니다.
  • @OneToMany로 Comment와의 관계를 설정해주었습니다. post에 작성한 댓글 목록을 불러올 수 있습니다.
  • 게시글을 삭제하면 연관된 댓글이 모두 삭제가 되게 cascade = CascadeType.REMOVE 를 붙여주었습니다.

 

Comment

package com.example.post.entity;

import com.example.post.dto.CommentRequestDto;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@Entity
public class Comment extends Timestamped{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String username;

    @Column(nullable = false)
    private String comment;

    //여러 댓글을 한 게시글에 작성
    @ManyToOne(fetch =FetchType.LAZY)
    @JoinColumn(name = "post_id")
    private Post post;

    //여러 댓글을 한명의 user가 작성
    @ManyToOne(fetch =FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;

    public Comment(String comment, User user, Post post){
        this.username = user.getUsername();
        this.user = user;
        this.comment = comment;
        this.post = post;


    }

    public void update(CommentRequestDto commentRequestDto){
        this.comment = commentRequestDto.getComment();
    }
}
  • @ManytoOne 어노테이션을 넣어서 Post와의 관계를 설정해주었습니다. 한 post에 여러 댓글을 작성할 수 있습니다.
  • @ManytoOne 어노테이션을 넣어서 User와의 관계를 설정해주었습니다. 한명의 user가 여러 댓글을 작성할 수 있습니다.
  • Comment 생성자에 User와 Post를 넣어서 객체로 불러 올 수 있게 작성하였습니다.

 

User

package com.example.post.entity;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

@Getter
@NoArgsConstructor
@Entity(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true)
    private String username;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false)
    @Enumerated(value = EnumType.STRING)
    private UserRoleEnum role;

    @OneToMany(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
    private List<Post> posts = new ArrayList<>();

    @OneToMany(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
    private List<Comment> comments = new ArrayList<>();


    public User(String username, String password, UserRoleEnum role) {
        this.username = username;
        this.password = password;
        this.role = role;
    }
}
  • @OneToMany로 Comment 및 Post의 관계를 설정해주었습니다. 
  • user를 삭제하면 연관된 댓글 및 게시글이 모두 삭제가 되게 cascade = CascadeType.REMOVE 를 붙여주었습니다.

 

PostResponseDto

package com.example.post.dto;

import com.example.post.entity.Post;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class PostResponseDto {

    private Long id;
    private String title;
    private String content;
    private String username;
    private LocalDateTime createdAt;
    private LocalDateTime modifiedAt;

    private List<CommentResponseDto> commentResponseDtoList = new ArrayList<>();

    //stackoverflow를 방지하기 위해서 객체 직렬화를 해야한다. stream을 써야하나보다?
    public PostResponseDto(Post post){
        this.id = post.getId();
        this.title = post.getTitle();
        this.content = post.getContent();
        this.username = post.getUser().getUsername();
        this.createdAt = post.getCreatedAt();
        this.modifiedAt = post.getModifiedAt();
        this.commentResponseDtoList = post.getCommentLists().stream().map(CommentResponseDto::new).collect(Collectors.toList());

    }
}

 

  • 생성자에 getUser().getUsername()을 사용해서 username을 불러왔습니다.
  • 댓글리스트는 Dto에 담아서 불러옵니다. 바로 가져오면 stackoverflow, 순환 참조 오류가 발생합니다.
  • 이를 해결하기 위해 구글링해보니 dto에 담아오면 되고 목록을 담으려면 stream을 쓰면 된다고 해서 썼는데 여기는 정말 그냥 가져온거라서 나중에 stream에 대해서 학습하고 더 나은 방법이 있나 알아보도록 하겠습니다.

 

CommentResponseDto

package com.example.post.dto;

import com.example.post.entity.Comment;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@Getter
@NoArgsConstructor
public class CommentResponseDto {

    private Long id;
    private String username;
    private String comment;
    private LocalDateTime createdAt;
    private LocalDateTime modifiedAt;

    private Long postId;

    private Long userId;

    public CommentResponseDto(Comment comment) {
        this.id = comment.getId();
        this.username = comment.getUsername();
        this.comment = comment.getComment();
        this.createdAt = comment.getCreatedAt();
        this.modifiedAt = comment.getModifiedAt();
        this.postId = comment.getPost().getId();
        this.userId = comment.getUser().getId();
    }
}
  • postId는 comment.getPost().getId()를 사용해서 불러왔습니다. 
  • userId는 comment.getUser().getId()를 사용해서 불러왔습니다.
  • JPA 연관관계를 설정했기 때문에 메소드로 호출할 수 있습니다.

 

PostService

  //게시글 전체 조회 USER/ADMIN 상관 없음
    public List<PostResponseDto> getPostList() {
        List<Post> postList = postRepository.findAllByOrderByModifiedAtDesc();

        if(postList.isEmpty()){
            throw new NullPointerException("게시글이 존재하지 않습니다.");
        }

        List<PostResponseDto> postResponseDtoList = new ArrayList<>();
        //각 게시물마다 조회해서 넣어줌
        for (Post post : postList) {
            postResponseDtoList.add(new PostResponseDto(post));
        }
        return postResponseDtoList;
    }

    @Transactional(readOnly = true)
    //게시글 상세 조회 USER/ADMIN 상관 없음
    public PostResponseDto getPost(Long id) {
        Post post = postRepository.findById(id).orElseThrow(
                () -> new NullPointerException("해당 게시글은 존재하지 않습니다.")
        );

//        List<CommentResponseDto> commentResponseDtoList = new ArrayList<>();

//        for (int i =0; i<post.getCommentLists().size(); i++){
//            Comment comment = post.getCommentLists().get(i);
//            commentResponseDtoList.add(new CommentResponseDto(comment));
//        }
        return new PostResponseDto(post);

    }
  • 게시글을 불러오면 댓글은 자동으로 따라오기 때문에 댓글 관련해서 작성했던 코드를 지워주었습니다. 
  • JPA 연관관계 설정을 잘 해놓으니 매우 편리하네요!!

 

 

결론

JPA 연관관계를 도대체 어떻게, 왜 쓰는지를 해결했습니다. 스프링 첫주차부터 JPA 연관관계 강의를 들었는데 이제사 좀 이해가 되는 것 같습니다. 연관관계를 설정해 놓으면 알아서 데이터가 연관되어서 불러오고 삭제하는 것이 간단해집니다. 연관관계 설정도 조금만 더 연습해보면 잘 할 수 있을 것 같습니다. 시간이 괜찮으면 좋아요와 대댓글 기능도 구현을 해보려 합니다.

 

내일부터는 프론트와 함께 하는 첫 협업 프로젝트날입니다😎

Spring과 Java는 사랑입니다😍😍

예외 처리 Exception Handling

  • 프로그램에서 예외가 발생했을 경우, 프로그램의 갑작스러운 종료를 막고, 정상 실행을 유지하기 위해 예외 처리를 해야 함
  • 자바 컴파일러는 일반 예외가 발생할 가능성이 있는 코드를 발견하면 컴파일 에러를 발생시켜 예최처리 코드를 개발자가 강제적으로 작성하도록 요구함
  • 실행 예외의 경우에는 개발자의 경험을 바탕으로 예외 처리 코드를 작성해야 함

자바 예외처리

 

예외 처리 코드

  • try-catch-finally 블록은 생성자 내부와 메소드 내부에서 작성되어 일반 예외와 실행 예외가 발생할 경우 예외 처리를 할 수 있도록 해줌

1. try 블록에는 예외 발생 가능 코드가 위치

2. try 블록의 코드가 예외 발생 없이 정상 실행되면 catch 블록의 코드는 실행되지 않고 finally 블록의 코드를 실행;

    try 블록의 코드에서 예외가 발생하면 즉시 실행을 멈추고 catch 블록으로 이동하여 예외 처리 코드 실행 -> finally 블록 코드 실행

3. finally 블록은 생략 가능; 예외 발생 여부와 상관 없이 항상 실행할 내용이 있을 경우에만 finally 블록을 작성함;

    try 블록과 catch 블록에서 return문을 사용하더라도 finally 블록은 항상 실행됨

 

예외 종류에 따른 처리 코드

 

다중 catch

  • 다중 catch 블록을 작성해서 블록5 내부 다양한 예외 처리
  • catch 블록의 예외 클래스 타입은 try 블록에서 발생된 예외의 종류를 말함
  • try 블록에서 해당 타입의 예외가 발생하면 catch 블록을 실행함
  • catch 블록이 여러 개일지라도 단 하나의 catch 블록만 실행 -> 하나의 예외가 발생하면 즉시 실행을 멈추고 해당 catch 블록으로 이동

 

catch 순서

  • 다중 catch 블록을 작성할 때 주의할 점: 상위 예외 클래스가 하위 예외 클래스보다 아래쪽에 위치해야함
  • 하위 예외는 상위 예외를 상속했기 때문에 상위 예외 타입도 되기 때문임

 

예외 떠넘기기

  • 경우에 따라서 메소드를 호출한 곳으로 예외를 떠넘길 수 있음 -> throw 키워드 사용
  • throw 키워드: 메소드 선언부 끝에 작성되어 메소드에서 처리하지 않은 예외를 호출한 곳으로 떠넘기는 역할
  • throw 키워드 뒤에 떠넘길 예외 클래스를 쉼표로 구분해서 나열해주면 됨

 

리턴타입 메소드이름(매개변수, ...) throws 예외클래스1, 예외클래스2, ... {
}

 

 

또는

 

리턴타입 메소드이름(매개변수, ....) throws Exception {
}

 

 

  • throw 키워드가 붙어있는 메소드는 반드시 try 블록 내에서 호출되어야 함
  • catch 블록에서 떠넘겨 받은 예외를 처리해야함

 

public void method1() {

try {

  method2();

} catch(ClassNotFoundException e){

  //예외 처리 코드

  System.out.println("클래스가 존재하지 않습니다.");

  }

}



public void method2() throws ClassNotFoundException {

 Class claszz = class.forName("java.lang.String2");

}



==> 호출한 곳에서 예외 처리 예시

 

 

확인문제

  • try{} 블록에는 예외가 발생할 수 있는 코드를 작성한다
  • catch {} 블록은 try {} 블록에서 발생한 예외를 처리하는 블록이다.
  • try{} 블록에서 return 문을 사용하면 finally {} 블록은 실행되지 않는다. (x)
  • catch{} 블록은 예외의 종류별로 여러 개를 작성할 수 있다.
  •  
  • 생성자나 메소드의 선언 끝부분에 사용되어 내부에서 발생된 예외를 떠넘긴다.
  • throws 뒤에는 떠넘겨야 할 예외를 쉼표(,)로 구분해서 기술한다.
  • 모든 예외를 떠넘기기 위해 간단하게 throws Exception으로 작성할 수 있다.
  • 새로운 예외를 발생시키기 위해 사용된다. (x)

 

자바도 모르는데 스프링하는 개발자지망생

분기문 aka 조건문

어떠한 조건에 따라 다른 명령을 실행하게 하는 문법으로, 가장 대표적인 분기문에는 if문이 있습니다.

분기문은 조건문과 같은 의미로 사용됩니다.

 

분기문 (조건문) 종류

java 자바 언어에서 분기문은 if, else if, switch 가 있습니다.

if문은 분기를 처리할 때 가장 많이 쓰이는 문법입니다.

 

조건을 분기하여 처리할 때 사용합니다.

 

분기처리

분기문을 이용해 선택적으로 조건에 따라 코드를 실행하게 만드는 것을 의미합니다.

 

 

 

 

  • 예외(exception): 사용자의 잘못된 조작 또는 개발자의 잘못된 코딩으로 인해 발생하는 프로그램 오류
  • 예외 처리(exception handling): 프로그램을 종료하지 않고 정상 실행 상태가 유지되도록 할 수 있음
  • 자바는 예외 처리 유무를 확인하고 예외 처리 코드가 없다면 컴파일이 안됨

 

예외와 예외 클래스

  • 일반 예외: exception
  • 실행 예외:runtime exception
  • RuntimeException 클래스 기준으로 구분

 

실행 예외

  • 자바 컴파일러가 체크하지 않기 때문에 개발자가 예외 처리 코드를 작성해야 함

 

NullPointerException

  • 객체 참조가 없는 상태, 즉 null 값을 갖는 참조 변수로 객체 접근 연산자인 도트(.)를 사용했을 때 발생
  • 객체가 없는 상태에서 객체를 사용하려고 할때 생기는 예외

 

ArrayIndexOutOfBoundsException

  • 배열에서 인텍스 범위를 초과할 경우 생기는 실행 예외

 

NumberFormantException

  • 문자열을 숫자로 변환 할 때 숫자로 변환될 수 없는 문자가 포함되어 있을 때 발생

 

ClassCastException

  • 타입변환은 상위클래스와 하위 클래스 간에 발생하고 구현 클래스와 인터페이스 간에 발생하는데 이런 관계가 아닐 때 발생하는 예외
  • instanceof 연산자 사용해서 타입 변환 전에 변환 가능한지 확인하기

 

확인문제

  • 예외는 사용자의 잘못된 조작 개발자의 잘못된 코딩으로 인한 프로그램 오류를 말한다.
  • RuntimeException의 하위 클래스는 컴파일러가 예외처리 코드를 체크하지 않는다.
  • 예외는 클래스로 관리된다.
  • Exception의 하위 클래스는 모두 일반 예외에 해당한다. (x)

중첩 클래스와 중첩 인터페이스

중첩 클래스 (nested class)

  • 클래스 내부에 선언한 클래스
  • 중첩 클래스를 사용하면 두 클래스의 멤버들을 쉽게 접근할 수 있고 외부에는 불필요한 관계 클래스를 감춤으로서 코드의 복잡성을 줄일 수 있음

 

중첩 인터페이스 nested interface

  • 인터페이스를 클래스 내부에서 선언하는 경우
  • 해당 클래스와 긴밀한 관계를 맺는 구현 클래스를 만들기 위해서 사용

 

중첩 클래스

  • 멤버 클래스: 클래스의 멤버로서 선언되는 중첩 클래스
  • 로컬 클래스: 생성자 또는 메소드 내부에서 선언되는 중첩 클래스
  • 멤버 클래스는 클래스나 객체가 사용 중이라면 언제든지 재사용이 가능하지만 로컬 클래스는 메소드 실행할 때만 사용되고 메소드가 종료되면 없어짐

 

중첩 클래스 바이트 코드 파일 => A $ B . class
  • A는 바깥 클래스, B는 멤버 클래스

 

로컬 클래스 바이트 코드 파일 => A $1 B .class
  • A는 바깥 클래스, B는 로컬 클래스

 

인스턴스 멤버 클래스

  • static 키워드 없이 중첩 선언된 클래스
  • 인스턴스 멤버 클래스는 인스턴스 필드와 메소드만 선언이 가능하고 정적 필드와 메소드는 선언할 수 없음

 

class A {
	/**인스턴스 멤버 클래스**/
    class B {
    	B() {} //생성자
        int field1; //인스턴스 필드
        //static int field2; // 정적필드 (x)
        void method1() {} //인스턴스 메소드
        //static void method2() {} // 정적 메소드 (x)
        }
 }

 

정적 멤버 클래스

  • static 키워드로 선언된 클래스
  • 모든 종류의 필드와 메소드를 선언 할 수 있음
class A {
	/**정적 멤버 클래스**/
    static class C {
    	C() {} //생성자
        int field1; //인스턴스 필드
        static int field2; // 정적필
        void method1() {} //인스턴스 메소드
        static void method2() {} // 정적 메소드
        }
 }

 

 

로컬 클래스

메소드 내에서 중첩 클래스 선언

  • 로컬 클래스는 접근 제한자 및 static을 붙일 수 없음
  • 로컬 클래스는 메소드 내부에서만 사용되므로 접근을 제한할 필요가 없음
  • 로컬 클래스 내부에는 인스턴스 필드와 메소드만 선언할 수 있음
  • 정적 필드와 메소드는 선언할 수 없음
  • 로컬 클래스는 메소드가 실행될 때 메소드 내에서 객체를 생성하고 사용해야 함

 

중첩 클래스의 접근 제한

  • 멤버 클래스 내부에서 바깥 클래스의 필드와 메소드에 접근할 때는 제한이 있음
  • 메소드의 매개변수나 로컬 변수를 로컬 클래스에서 사용할 때도 제한이 있음

 

바깥 필드와 메소드에서 사용 제한

  • 바깥 클래스에서 인스턴스 멤버 클래스를 사용할 때 제한
  • 인스턴스 멤버 클래스는 바깥 클래스의 인스턴스 필드의 초기값이나 인스턴스 메소드에서 객체를 생성할 수 있음
  • 정적 필드의 초기값이나 정적 메소드에서는 객체를 생성할 수 없음
  • 정적 멤버 클래스는 모든 필드의 초기값이나 모든 메소드에서 객체를 생성할 수 있음

 

멤버 클래스에서 사용제한

  • 멤버 클래스가 인스턴스 또는 정적으로 선언됨에 따라 멤버 클래스 내부에서 바깥 클래스의 필드와 메소드에 접근할 때에도 제한이 있음
  • 인스턴스 멤버 클래스 안에서는 바깥 클래스의 모든 필드와 모든 메소드에 접근 가능
  • 정적 멤버 클래스 안에서는 바깥 클래스의 정적필드와 메소드에만 접근할 수 있고 인스턴스 필드와 메소드에는 접근할 수 없음

 

로컬클래스에서 사용 제한

  • 메소드의 매개 변수나 로컬 변수를 로컬 클래스에서 사용할 때 제한
  • 로컬 클래스의 객체는 메소드 실행이 종료되면 없어지는 것이 일반적이지만 로컬 스레드 객체를 사용하면 계속 실행상태로 존재
  • 매개 변수나 로컬 변수가 수정되어 값이 변경되면 로컬 클래스에 복사해둔 값과 달라지므로 문제를 해결하기 위해 매개변수나 로컬 변수를 final로 선언할것을 요구 -> 자바 8부터는 final 선언을 하지 않아도 값이 수정될 수 없도록 final 특성을 부여함

 

중첩 클래스에서 바깥 클래스 참조 얻기

  • 중첩 클래스에서 this 키워드를 사용하면 바깥 클래스의 객체 참조가 아니라, 중첩 클래스의 객체 참조가 됨
  • 중첩 클래스 내부에서 this.필드, this.메소드()로 호출하면 중첩 클래스의 필드와 메소드가 사용됨
  • 중첩 클래스 내부에서 바깥크 ㄹ래스의 객체 참조를 얻으려면 바깥 클래스의 이름을 this 앞에 붙여주면 됨
바깥클래스.this.필드;
바깥클래스.this.메소드();

 

중첩 인터페이스

  • 클래스 멤버로 선언된 인터페이스
  • 인터페이스를 클래스 내부에서 선언하는 이유는 해당 클래스와 긴밀한 관계를 맺는 구현 클래스를 만들기 위해서임
  • 중첩 인터페이스는 인스턴스 멤버 인터페이스와 정적멤버 인터페이스 모두 가능
  • 인스턴스 멤버 인터페이스는 바깥 클래스의 객체가 있어야 사용 가능
  • 정적 멤버 인터페이스는 바깥 클래스의 객체 없이 바깥 클래스만으로 바로 접근 가능
  • UI 프로그래밍에서 이벤트를 처리할 목적으로 많이 활용
class A {
	[static] interface I {
    void method();
    }
}

 

확인문제

  • 인스턴스 멤버 클래스는 바깥 클래스의 객체가 있어야 사용될 수 있다. (o)
  • 정적 멤버 클래스는 바깥 클래스의 객체가 없어도 사용될 수 있다 (o)
  • 인스턴스 멤버 클래스는 내부에는 바깥 클래스의 필드와 메소드를 사용할 수 있다. (o)
  • 정적 멤버 클래스 내부에는 바깥 클래스의 인스턴스 필드를 사용할 수 있다. (x)
  • 로컬 클래스는 생성자 또는 메소드 내부에 선언된 클래스를 말한다. (o)
  • 로컬클래스도 필드와 생성자를 가질 수 있다. (o)
  • 로컬 클래스는 static 키워드를 이용해서 정적 클래스로 만들 수 있다. (x)
  • final 특성을 가진 매개 변수나 로컬 변수만 로컬 클래스 내부에서 사용할 수 있다. (o)

타입변환과 다형성

인터페이스의 다형성

  • 프로그램 소스 코드는 변함 없지만 구현 객체를 교체함으로써 프로그램의 실행결과가 다양해짐

 

자동 타입 변환 promotion

  • 자동타입변환 : 구현 객체가 인터페이스 타입으로 변환 되는 것
  • 인터페이스 구현 클래스를 상속해서 자식 클래스를 만들었다면 자식 객체 역시 인터페이스 타입으로 자동 타입 변환 가능
  • 필드의 다형성과 매개 변수의 다형성을 구현할 수 있음

 

필드의 다형성

  • 매개 변수의 다형성: 매개 변수 타입이 인터페이스일 경우 어떠한 구현 객체도 매개값으로 사용할 수 있고, 어떤 구현 객체가 제공되느냐에 따라 메소드의 실행결과가 다양해짐

 

강제타입변환 (casting)

  • 구현 객체가 인터페이스 타입으로 자동 타입 변환하면, 인터페이스에 선언된 메소드만 사용가능 -> 제약
  • but, 경우에 따라서 구현 클래스에 선언된 필드와 메소드를 사용해야 하는 경우 발생 -> 강제타입변환(casting) 사용 -> 다시 구현 클래스 타입으로 변환 -> 구현 클래스의 필드와 메소드 사용

 

객체 타입 확인

  • 강제 타입 변환은 구현 객체가 인터페이스 타입으로 변환되어 있는 상태에서 가능
  • 어떤 구현 객체가 변환되어 있는지 모르는 상태에서 강제타입변환 할 경우 ClassCastException 에러가 발생할 수 있음
    • -> instanceof 연산자를 사용해서 인터페이스 타입으로 변환된 객체 확인

 

확인문제

  • 구현 객체는 인터페이스 타입으로 자동 변환된다 (o)
  • 부모 클래스가 인터페이스를 구현하면 자식 클래스로부터 생성된 객체는 인터페이스 타입으로 자동 변환할 수 있다. (x)
  • 인터페이스 변수에 대입된 객체를 원래 구현 클래스 타입으로 변환하는 것을 강제 타입 변환이라고 한다 (o)
  • 메소드의 매개변수 타입이 인터페이스이면 매개값으로 모든 구현 객체를 대입하면 자동 타입 변환이 된다 (o)
  • 다형성을 구현하기 위한 조건은 메소드의 재정의와 타입 변환이다 (o)
  • 클래스 상속과 인터페이스는 모두 메소드 재정의와 티압 변환 기능이 제공되므로, 어떤 방법을 사용하든 다형성 구현이 가능하다. (o)
  • 매개 변수 타입이 클래스라면 해당 클래스로 생성된 객체만 대입이 가능하다 (x)
  • 매개 변수의 타입이 인터페이스라면 모든 구현 객체가 대입이 가능하다 (o)

인터페이스 혼자공부하는자바

 

인터페이스

  • 개발 코드와 객체가 서로 통신하는 접점 역할
  • 개발 코드가 인터페이스의 메소드를 호출하면 인터페이스는 객체의 메소드를 호출
  • 개발 코드를 수정하지 않고 사용하는 객체를 변경할 수 있음
  • 코드 변경 없이 실행 내용과 리턴값을 다양화 할 수 있음

 

인터페이스 선언

[public] interface 인터페이스이름 {...}
  • 인터페이스 선언은 class 키워드 대신에 interface 키워드 사용
  • 인터페이스는 상수 필드와 추상 메소드만을 구성 멤버로 가짐
  • 객체를 생성할 수 없기 때문에 생성자를 가질 수 없음

 

interface 인터페이스이름 {
	//상수
    타입 상수이름 = 값;
    //추상 메소드
    타입 메소드이름(매개변수, ...);
}

 

상수 필드(constant field) 선언

  • 인터페이스에 고정된 값으로 실행시에 데이터 변경 불가능
[public static final] 타입 상수이름 = 값;

 

 

추상메소드 선언

  • 인터페이스의 메소드는 실행 블록이 필요 없는 추상 메소드로 선언
  • 추상 메소드는 리턴 타입 메소드 이름, 매개 변수만 기술되고 중괄호 {} 를 붙이지 않는 메소드

 

인터페이스 구현

  • 인터페이스 메소드를 호출하면 인터페이스는 객체의 메소드를 호출함
  • 객체는 인터페이스에서 정의된 추상 메소드와 동일한 메소드 이름, 매개 타입, 리턴 타입을 가진 실체 메소드를 가져야함 -> 구현 객체(implement object), 구현 객체를 생성하는 클래스는 구현 클래스

 

구현 클래스

  • 클래스 선언 부에 Implements 키워드를 추가하고 인터페이스 이름을 명시
  • 인터페이스에 선언된 추상 메소드의 실체 메소드를 선언해야 함

 

public class 구현클래스이름 Implements 인터페이스이름 {

  //인터페이스에 선언된 추상 메소드의 실체 메소드 선언

}

 

  • 구현 클래스가 작성되면 new 연산자로 객체를 생성할 수 있음
  • 인터페이스로 구현 객체를 사용하려면 인터페이스 변수 선언 후 구현 객체를 대입
  • 인터페이스 변수는 참조 변수로 구현 객체가 대입될 경우 구현 객체의 번지를 저장

 

다중 인터페이스 구현 클래스

  • 다중 인터페이스를 구현하는 경우, 구현 클래스는 모든 인터페이스의 추상메소드에 대해 실체 메소드를 작성해야 함

 

인터페이스 사용

  • 클래스를 선언할 때 인터페이스는 필드, 생성자, 또는 메소드의 매개변수, 생성자 또는 메소드의 로컬 변수로 선언 될 수 있음

1. 인터페이스가 필드타입으로 사용 -> 필드에 구현 객체를 대입 가능

2. 인터페이스가 생성자의 매개 변수 타입으로 사용 -> new 연산자로 객체를 생성할 때 구현 객체를 생성자의 매개값으로 대입 가능

3. 인터페이스가 로컬 변수 타입으로 사용 -> 변수에 구현 객체를 대입할 수 있음

4. 인터페이스가 로컬 매개 변수 타입으로 사용될 경우 ->메소드 호출 시 구현 객체를 매개값으로 대입 가능

 

  • 구현 객체가 인터페이스 타입에 대입되면 인터페이스에 선언된 추상 메소드를 개발 코드에서 사용 가능

 

확인문제

  • 인터페이스는 객체 사용 방법을 정의해놓은 타입이다 (o)
  • new 연산자를 이용해서 인터페이스 객체를 만들 수 있다 (x)
  • 인터페이스는 상수 필드와 추상 메소드를 갖는다 (o)
  • 구현 클래스는 Implements 키워드로 인터페이스를 기술해야 한다 (o)
  • 클래스를 선언할 때 인터페이스 타입의 필드를 선언할 수 있다 (o)
  • 생성자의 매개 타입이 인터페이스일 경우 매개값으로 구현 객체를 대입한다 (o)
  • 인터페이스 타입의 로컬 변수는 선언할 수 없다 (x)
  • 메소드의 매개 타입이 인터페이스일 경우 매개값으로 구현 객체를 대입한다 (o)

 

 

추상 클래스

추상 클래스

  • 객체를 직접 생성할 수 있는 클레스들의 공통적인 특성을 추철해서 선언한 클래스
  • 추상클래스가 부모, 실체 클래스가 자식으로 구현되어 실체 클래스는 추상 클래스의 모든 특성을 물려받고 추가적인 특성(필드, 메소드)을 가질 수 있음

 

추상 클래스의 용도

  • 공통된 필드와 메소드의 이름을 통일할 목적
  • 실체 클래스를 작성할 때 시간 절약
  • 작성해야할 클래스가 다수이고 이 클래스들이 동일한 필드와 메소드를 가져야 할 경우, 설계자는 공통된 부분을 춯상 클래스로 설계하는 것이 좋음
  • 추상 클래스를 상속해서 구체적인 클래스를 만듦

 

추상 클래스 선언

public abstract class 클래스 {
	//필드
    //생성자
    //메소드
}
  • abstract를 붙이면 new 연산자를 이용해서 객체 못만들고 상속을 통해 자식 클래스만 만들 수 있음
  • new 연산자로 직접 호출할 수는 없지만 자식 객체가 생성될 때 super(...)를 호출해서 추상 클래스 객체를 생성
  • 추상 클래스도 생성자가 반드시 있어야 함

 

public abstract class Phone {
	//필드
    public String owner;
    
    //생성자
    public Phone(String owner) v{
    	this.owner =owner;
    }
    
    //메소드
    public void turnOn() {
      System.out.println("폰 전원을 켭니다.");
    }
    public void turnOff() {
      System.out.println("폰 전원을 끕니다.");
    } 
  }

 

  • 부모 클래스의 super(owner) 코드로 생성자를 호출함

 

public abstract class SmartPhone extends Phone {
    
    //생성자
    public SmartPhone(String owner) v{
    	super(owner);
    }
    
    //메소드
    public void internetSearch() {
      System.out.println("인터넷 검색을 합니다.");
    }
    
    } 
  }

 

추상 메소드와 재정의

  • 추상클레스는 실체 클래스의 멤버(필드, 메소드)를 통일하는 게 목적
  • 모든 실체들이 가지고 있는 메소드의 실행 내용일 동일하면 추상 클래스에 메소드를 작성
  • 메소드 선언만 통일하고 실행 내용은 실체 클래스마다 달라야 하는 경우 -> 추상 클래스는 추상 메소드 선언 가능

 

[public | protected] abstract 리턴타입 메소드이름(매개변수, ...);
  • 추상 클래스 설계 시 하위 클래스가 실행 내용을 반드시 채우도록 강제하고 싶은 메소드가 있을 경우 추상 메소드 선언
  • 자식 클래스는 반드시 추상 메소드를 재정의해서 실행 내용 작성해야함 -> 아니면 컴파일 에러 발생

 

확인문제

  • 추상 클래스는 직접 new 연산자로 객체를 생성할 수 없다 (o)
  • 추상 클래스는 부모 클래스로만 사용 (o)
  • 추상 클래스는 실체 클래스들의 공통된 특성(필드, 메소드)로 구성된 클래스이다. (o)
  • 추상 클래스에는 최소한 하나의 추상 메소드가 있어야 한다 (x)
  • 추상 메소드는 선언부만 있고 실행 블록을 가지지 않는다 (o)
  • 추상 메소드는 자식 클래스에서 재정의 해서 실행 내용을 결정해야 한다 (o)
  • 추상 메소드를 재정의 하지 않으면 자식 클래스도 추상 클래스가 되어야 한다 (o)
  • 추상 메소드가 있더라도 해당 클래스가 꼭 추상 클래스가 될 필요는 없다 (x)

어제 팀원들이랑 대화하다가 새벽 3시쯤 잠들어서 파워냅 30분했는데 코딩하는 꿈을 꿨습니다...😱  하루종일 코딩만 생각하니 이런 꿈도 꿉니다. 오늘은 주특기 2주차 시작일로 Spring 숙련주차입니다. 강의가 새로 지급되었고 개인과제와 팀과제가 새로 나왔습니다. 다들 월드컵 보러 갈 때 치킨으로 만족하고 강의 듣습니다.🍗🍗🍗

 

zep

JPA 심화

  • JPA는 자동으로 Id값을 찾아주지만 (@GeneratedValue 사용) Query는 Select를 사용해 최대값을 넣어서 찾아서 마지막 id값+1해서 넣어줘야 한다
  • JPA를 사용하면 query보다 간단함 
  • Spring Data JPA 사용

 

영속성 컨텍스트 Persistence context

  • 엔티티를 영구 저장 하는 환경
  • 어플리케이션이 데이터베이스에서 꺼내온 데이터 객체를 보관하는 역할
  • 영속성 컨텍스트는 엔티티 매니저를 통해 엔티티를 조회하거나 저장할때 엔티티를 보관하고 관리함

 

1. find(”memberB”)와 같은 로직이 있을 때 먼저 1차 캐시를 조회

2. 있으면 해당 데이터를 반환

3. 없으면 그 때 실제 DB로 “SELECT * FROM….” 의 쿼리를 보냄

4. 반환하기 전에 1차캐시에 저장하고 반환

 

 

=> MemberA, MemberB를 생성할 때 마다 DB를 다녀오는건 비효율적

 

해결책 =>“쓰기 지연 SQL 저장소” Transactional write-behind

 

1. memberA, memberB를 영속화

2. entityManager.commit() 메서드를 호출

3. 내부적으로 쓰기 지연 SQL 저장소에서 Flush가 발생 -> 임의로 시점 지정 가능

4. “INSERT A”, “INSERT B”와 같은 쓰기 전용 쿼리들이 DB로 전달

 

 

@Enumerated

  • 속성으로는 Ordinal, String이 있음
  • String인경우 해당 문자열 그대로 저장해서 비용은 많이 들지만, 나중에 Enum이 변경되어도 위험할일이 없기 때문에 일반적으로는 String을 사용합니다.
  • Enum은 데이터 순서대로 값을 매기기 때문에 변경되거나 삭제시 오류가 발생할 수 있음
    • 값이 변경되어도 위험할 일이 없기 때문에 대부분 String을 사용

 

 

 

벌써 12월이 되었습니다. 한달이 훌쩍 지나갔네요. 정식으로 부트캠프는 99일이라고 홍보가 되어있지만 사전 스터디 기간까지 합친다면 거진 2달의 기간이 지나갔습니다. 11월에는 자바가 무엇인지 객체지향 프로그램이 무엇인지 처음 배우는 시간이었습니다. 그동한 배우고 구현 해본 것들을 나열하자만 아래와 같습니다.

 

  • JWT를 이용해서 Flask python 회원가입, 로그인 기능 구현
  • 자바의 정석 유튜브 동영상 강의 ch 1 ~ 7
  • 프로그래머스 문제 풀이 30개
  • 혼자공부하는 자바 ch 1 ~ 7
  • 깃과 깃허브 사용해서 협업
  • 1주차 미니프로젝트 완성
  • 2주차 알고리즘 test
  • 3주차 Spring 주특기 1주차 강의
  • 객체지향 프로그래밍 과제
  • 게시판 구현 (CRUD 기능 구현: 등록, 조회, 수정, 삭제)
  • Postman 사용
  • JPA 기초
  • HTTP method (PUT, POST, DELETE 등)
  • API 명세서 작성
  • API 만들기

생각보다 한 게 많지만 없습니다.

개발자가 되기 위한 단계로 보면 이제 튜토리얼의 튜토리얼을 뗀 수준입니다. 

프로그래머의 삶

자바도 그렇고 이제 갓 배우기 시작해서 뭐든 다 새롭고 매일 엄청난 양의 새로운 정보를 습득하다 보니 혼란할 때도 많습니다. 어제 튜터님께 자바 공부를 하고 있다고 말씀드리니까 자바 백엔드 개발자 공부 로드맵을 이야기 해주셨습니다. 

 

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

 

자바 백엔드 공부 로드맵

자바 공부 로드맵

1. 자바의 정석

- 남궁성 자바의 정석 유튜브 보면서 다 따라치면서 연습하기

- 객체지향 부분은 스스로 예제 만들면서 익히기

 

2. 모던 자바인 액션

- 자바 8, 9, 10 버전을 예시와 함께 설명하는 책

 

3. 컴파일러 만들기

- 컴파일러 만들어보기

책입니다 --> 책정보 링크 클릭

 

4. 클린 코드, 이펙티브 자바

클린코드 책 구매 링크

이펙티브 자바 책 구매 링크

 

고급 개발자가 되기 위해서 읽자.

 

Gof의 디자인 패턴

(클린 코드 다음에 읽을 책)

 

schema 설계

DB 설계 중요

 

컴퓨터 공학 Network

1. MIT 유튜브 강의

2. 네트워크 공부하기

 

Spring 공부

1. 토비의 스프링 3.1 

- 좀 두꺼운 편이니까 아래 책을 먼저 읽는 것도 추천

 

2. 자바 웹프로그래밍 Next step

- 토비의 스프링보다 얇은 편

 

3. 김영한 강의도 추천

 

알고리즘 코딩 테스트 공부

하루에 1문제 풀기.

lv 순으로 풀기 보다는 bfs, dfs (최단시간) 문제 등 유형별로 풀어보기

 


12월의 목표는....

  • 자바에 대해 어느정도 익숙해지는 것
    • 자바의 정석 남궁성 유튜브 강의 완강
    • 혼자공부하는자바 완독
  • 아무것도 안보고 CRUD 혼자 구현해 보는 것
    • 이건 이번 주말에 할 겁니다
  • Spring 김영한 입문 강의 완강
    • 28개 강의
  • 알고리즘 공부
    • 2일에 한 문제씩 풀기

입니다.

 

2월 17일이 항해99 부트캠프가 끝나니까요. 그때는 얼마나 성장해 있을지 기대가 됩니다.

 

나는 2023년 1분기 이내 취직한다.

 

 

 

 

디폴트 메서드와 static 메서드

디폴트 메서드와 static 메서드

  • 인터페이스에 디폴트 메서드, static 메서드 추가 가능 (JDK1.8부터)
  • 인터페이스에 새로운 메서드(추상 메서드)를 추가하기 어려움
    • 해결책 => 디폴트 메서드(default method) (인터페이스 원칙 위반: 예외)

 

디폴트 메서드가 기존의 메서드와 충돌할 때 해결책

  • 여러 인터페이스와 디폴트 메서드 간의 충돌
    • 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩 해야함
  • 디폴트 메서드와 조상 클래스의 메서드 간의 충돌
    • 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시됨

인터페이스 interface

  • 추상 메서드의 집합
  • 구현된 것이 전혀 없는 설계도. 껍데기 (모든 멤버가 public)
  • 기본 설계도
  • 다른 클래스를 작성하는데 도움이 될 목적으로 작성
  • 추상클래스와 인터페이스의 차이
    • 추상클래스는 일부가 구현된 미완성 설계도
    • 인터페이스는 아무것도 구현된 것도 없고 밑그림만 그려져있는 기본 설계도
interface 인터페이스이름 {
	public static final 타입 상수이름 = 값; //상수
    public abstract 메서드이름(매개변수목록); //추상메서드
}

//인터페이스의 모든 메소드는 public이고 final이고 abstract 여서 생략 가능

 

인터페이스의 상속

  • 인터페이스의 조상은 인터페이스만 가능(Object가 최고 조상이 아님)
  • 다중 상속이 가능 (추상메서드는 충돌해도 문제 없음)
interface Fightable extends Movable, Attackable {}
interface Movable {
	/** 지정된 위치(x,y)로 이동하는 기능의 메서드 */
    void move(int x, int y);
 }
 
 interface Attackable {
 	/** 지정된 대상(u)을 공격하는 기능의 메서드 */
    void attack(Unit u);
}

 

인터페이스의 구현

  • 인터페이스에 정의된 추상 메서드를 완성하는 것
class 클래스이름 implements 인터페이스이름 {
        // 인터페이스에 정의된 추상메서드를 모두 구현해야 한다
}
  • 구현한다는 의미의 키워드 'implements'를 사용함
class Fighter implements Fightable {
	public void move(int x, int y) { /*내용 생략 */}
    public void attack(Unit u)     { /*내용 생략 */} // 몸통 완성
}

//Fighter 클래스는 Fightable 인터페이스를 구현했다.
  • 추상클래스 완성과 동일; 키워드만 다름
  • 일부만 구현하는 경우, 클래스 앞에 abstract를 붙어야 함

 

  • 인터페이스란?
    • 추상 메서드의 집합
  • 인터페이스의 구현이란?
    • 인터페이스의 추상메서드 몸통{} 만들기(미완성 설계도 완성하기)
  • 추상 클래스와 인터페이스의 공통점은?
    • 추상 메서드를 가지고 있다 (미완성 설계도)
  • 추상 클래스와 인터페이스의 차이점은?
    • 인터페이스는 iv를 가질 수 없다

 

 

인터페이스를 이용한 다형성

  • 인터페이스도 구현클래스의 부모
  • 인터페이스 타입 매개변수는 인터페이스 구현한 클래스의 객체만 가능
  • 인터페이스를 메서드를 리턴타입으로 지정할 수 있다
abstract class Unit2 {
    int x, y;
    abstract void move(int x, int y);
    void stop() {
        System.out.println("멈춥니다.");
    }
}

interface Fightable { //인터페이스의 모든 메서드는 public abstract. 예외 없이
    void move (int x, int y); // public abstract가 생략됨
    void attack(Fightable f); // public abstract가 생략됨
}

class Fighter extends Unit2 implements Fightable{
    //오버라이딩 규칙: 조상(public) 보다 접근제어자가 좁으면 안된다.
    public void move (int x, int y) {
        System.out.println("["+x+","+y+"]로 이동");
    }
    public void attack(Fightable f){
        System.out.println(f+"를 공격");
    }

}

public class FighterTest {
    public static void main(String[] args) {
//      Fighter f = new Fighter();
        Unit2 u = new Fighter(); //Unit2에는 attack()이 없어서 호출불가
        Fightable f = new Fighter();
        u.move(100, 200);
//        u.attack(new Fighter());  //Unit2에는 attack()이 없어서 호출불가
        u.stop();

        f.move(100, 200);
        f.attack(new Fighter());
//        f.stop();                 //Fightable에는 stop()이 없어서 호출불가

    }
}

 

인터페이스의 장점

  • 두 대상(객체) 간의 '연결, 대화, 소통'을 돕는 '중간 역할'을 한다
  • GUI - Graphic User Interface
  • 선언(설계, 껍데기)와 구현(알맹이)을 분리시킬수 있게 함
    • 변경에 유리하고 유연한 코드가 됨
    • 인터페이스 덕분에 B가 변경되어도 A는 안바꿀 수 있게 됨 -> 느슨한 결합
    • 의존도가 낮아짐
  • 개발 시간 단축 가능
  • 변경에 유리한 유연한 설계 가능
  • 표준화가 가능
  • 서로 관계없는 클래스들을 관계를 맺어줄 수 있음
  • 다중상속 가능
class A{
    public void method(I i) { //인터페이스 I를 구현한 넘들만 들어와라
        i.method();
    }
}


// B클래스의 선언과 구현을 분
interface I {
    public  void method();
}

class B implements I{
    public void method(){
        System.out.println("B클래스의 메서드");
    }
}

class C implements I{
    public void method(){
        System.out.println("C클래스의 메서드");
    }
}

public class InterfaceTest {
    public static void main(String[] args) {
        A a = new A();
        a.method(new C()); // A가 B를 사용(의존)

    }
}

자바의정석 남궁성

 

추상클래스 (abstract class)

- 미완성 설계도, 미완성 메서드를 갖고 있는 클래스

- 추상메서드는 몸통{}이 없는 미완성 메서드

- 다른 클래스 작성에 도움을 주기 위한 것 -> 인스턴스 생성 불가

abstract class Player{
        abstract void play(int pos);  //추상메서드 (몸통{} 이 없는 미완성 메서드)
        abstract void stop();     // 추상메서드
}

- 상속을 통해 추상 메서드를 완성해야 인스턴스 생성가능

class AudioPlayer extends Player{
         void play(int pose) { /*내용 생략*/}  //추상메서드를 구현
         void stop() { /* 내용 생략*/ }             //추상메서드를 구현

 

추상 메서드(abstract method)

-미완성 메서드, 구현부 {}가 없는 메서드

abstract 리턴타입 메서드이름();

- 꼭 필요하지만 자손마다 다르게 구현될 것으로 예상되는 경우 사용

 

 

abstract class Player {  //추상 클래스
    abstract void play(int pos);  //추상 메서드
    abstract void stop();  //추상 메서드 (선언부만 있고 구현부{}가 없는 메서드)

}

//추상 클래스는 상속을 통해 완성해야 객체 생성가능
class AudioPlayer extends  Player {
    @Override
    void play(int pos) {
        System.out.println(pos+"위치부터 play 합니다");
    }

    @Override
    void stop() {
        System.out.println("재생을 멈춥니다.");
    }
}


public class PlayerTest {

    public static void main(String[] args) {
//        Player p = new Player(); // 추상 클래스의 객체를 생성
//        AudioPlayer ap = new AudioPlayer();
        Player ap = new AudioPlayer(); //다형성
        ap.play(100);
        ap.stop();
    }
}

 

추상클래스의 작성

- 여러 클래스에 공통적으로 사용될 수 있는 추상클래스를 바로 작성하거나 기존 클래스의 공통 부분을 뽑아서 추상클래스를 만든다


public class Ex7_10 {
    public static void main(String[] args) {
//        Unit[] group = new Unit[]{new Marine(), new Tank(), new Dropship()};
        Unit[] group = new Unit[3];
        group[0] = new Marine();
        group[1] = new Tank();
        group[2] = new Dropship();
        for(int i = 0; i < group.length; ++i)
            group[i].move(100, 200);
    }

}

abstract class Unit {
    int x, y;
    abstract void move(int x, int y);
    void stop() {/*현재 위치에 정지*/}
}

class Marine extends Unit { //보병
    void move(int x, int y) {
        System.out.println("Marine[x="+x+",y="+y+"]");
    }
    void stimPack() {/*스팀팩을 사용한다. */}
}

class Tank extends Unit { //탱크
    @Override
    void move(int x, int y) {
        System.out.println("Tank[x="+x+",y="+y+"]");
    }
    void changeMod() { /*공격모드를 변환한다.*/}
}

class Dropship extends Unit { //탱크
    @Override
    void move(int x, int y) {
        System.out.println("Dropship[x="+x+",y="+y+"]");
    }
    void change() { /*공격모드를 변환한다.*/}
}

- 추상화된 코드는 구체화된 코드보다 유연; 변경에 유리함

 

 

자바의 정석 기초편

instanceof 연산자

  • 참조변수의 형변환 가능여부 확인에 사용 -> 가능하면 true return
  • 형변환 전에 반드시 instanceof로 확인해야함
  • 참조변수 형변환은 왜?
    • -> 참조변수를 변경함으로써 사용할 수 있는 멤버의 갯수를 조절하기 위해서
    • 타입 일치시키려고

 

매개변수의 다형성

  • 다형적 매개변수
  • 하나의 배열로 여러종류 객채다루기
  • 참조형 매개변수는 메서드 호출시, 자신과 같튼 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있다.

 

여러 종류의 객체를 배열로 다루기

  • 조상타입의 배열에 자손들의 객체를 담을 수 있다

 

Vector class에는 모든 종류의 객체 저장 가능

object[]

 

동영상 예시를 보면 도움이 된다.

 

 

+ Recent posts