본문 바로가기

SpringBoot/백엔드

[이것이 백엔드 개발이다] ch 3. 실무에 가장 많이 쓰이는 자바 문법

1. 다형성 : 상속과 인터페이스 

 

 - 하나의 객체가 내부적으로 여러 타입을 가질 수 있고, 어떤 타입이 들어 있느냐에 따라 각기 다른 동작을 하는 성질 

public interface Car{}

public class Sonata implements Car {}

public class K5 implements Car {}

public class Main {
 public static void main(String[] args) {
   Car car1 = new Sonata();
   Car car2 = new K5();
 }
}

- 자동차 (Car)라는 인터페이스를 정의 

- 자동차 인터페이스를 구현하는 Sonata라는 클래스, K5 클래스 정의 

- 인터페이스인 Car 타입의 참조 변수에 자동차 인터페이스의 구현체인 Sonata와 K5의 인스턴스를 모두 대입 가능 

 

2. 컬렉션 : List

 

 - 컬렉션(Collection)이란 데이터의 집합을 의미

 - 주요 컬렉션으로는 List, Set, Map이 있는데, 이것은 모두 구현체가 아닌 인터페이스

 

 java List 컬렉션 

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

public class Main {
    public static void main(String[] args) {
        List list = new ArrayList<Integer>();

        list.add(1);
        list.add(2);
        list.add(3);

        System.out.println(list.get(1));
        }
}

//2

 

java ArrayList 출력

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

public class Main {
    public static void main(String[] args) {
        List list = new ArrayList<String>();

       list.add("public");
       list.add("static");
       list.add("void");

       //for문으로 List 순회 가능
        for(int i=0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

        list.remove(1); //1번째 요소인 "static" 제거
        int voidIndex = list.indexOf("void"); //void의 인덱스인 1 반환
        System.out.println("void의 index = "+voidIndex);

        System.out.println(list.get(1));
        }
}

/*
public
static
void
void의 index = 1
void
*/

 

3. 람다 표현식

 

- 자바 기본 문법에서는 함수만 따로 선언할 수 없고 클래스가 있어야 함.

- 클래스를 먼저 선언한 다음 그 안에 함수를 선언해야 그 전체를 메서드라고 부를 수 있음. 

- 클래스와 메서드에 모두 이름을 붙여 줘야 하나의 함수로 사용 가능 

- 이런 불편함을 피하기 위해 익명 클래스를 사용하기도 하지만, 불필요한 코드가 많이 추가되어 코드의 가독성이 떨어짐 

 

java 람다 표현식

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


public class Main {
    public static void main(String[] args) {
        List list = new ArrayList<String>();

        list.add("public");
        list.add("static");
        list.add("void");

        //익명 클래스 코드
        list.sort(new Comparator<String>() {
            @Override
            public int compare(String str1, String str2){
                return str1.compareTo(str2);
            }
        });

        //람다 표현식
        list.sort((Comparator<String>)(str1,str2)-> str1.compareTo(str2));

    }
}

 

4. 스트림 API

 

- 컬렉션에 추가된 메서드의 집합 

- 컬렉션에 담긴 데이터를 처리하는 존재 

 

1) forEach

 - 컬렉션의 요소들을 하나씩 꺼내서 반복하므로 반복문을 대체 

 

.java  forEach() 메서드 활용 

import java.util.Arrays;
import java.util.List;


public class Main {
    public static void main(String[] args) {
        Integer[] integerArray = new Integer[]{1,2,3,4,5};
        List<Integer> list = Arrays.asList(integerArray);
        list.stream().forEach(value-> System.out.println(value));
    }
}

/*
1
2
3
4
5
*/

 

2) filter

-  컬렉션의 요소들 중 조건문에 맞는 요소만 뽑아 새로운 스트림을 만듬 

- collect() 메서드와 함께 사용하면 전체 리스트 요소 중 조건문을 만족하는 요소를 뽑아 새로운 리스트를 만들 수 있음 

 

.java filter() 메서드 활용 

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


public class Main {
    public static void main(String[] args) {
        Integer[] integerArray = new Integer[]{1,2,3,4,5,6,7,8,9,10};
        List<Integer> list = Arrays.asList(integerArray);
        List evenList = list.stream()
                .filter(value -> value%2==0).collect(Collectors.toList());
        evenList.stream().forEach(value-> System.out.println(value));
    }
}

/*
2
4
6
8
10
*/

 

3) distinct

- 컬렉션의 요소에서 중복을 제거 

- 중복을 제거한다는 행위가 이미 정해져 있기 때문에 람다 표현식을 함수의 인자로 넘겨줄 필요가 없고, 이때 중복인지 아닌지를 판단하는 것은 요소들의 equals() 메서드이다.

 

.java distinct() 메서드 활용

import java.util.Arrays;
import java.util.List;


public class Main {
    public static void main(String[] args) {
        Integer[] integerArray = new Integer[]{1,1,1,2,2,2,3,3,4,4,4};
        List<Integer> list = Arrays.asList(integerArray);
        List<Integer> distinctList = list.stream().distinct().toList();
        distinctList.stream().forEach(value-> System.out.println(value));
    }
}

/*
1
2
3
4
*/

 

4) Map

- 컬렉션의 요소들에 특정 연산을 적용한 새로운 스트림을 만듬

- 입력으로 들어간 컬렉션의 수와 출력으로 나오는 컬렉션의 수는 동일 

 

.java map() 메서드 활용 

- 문자열 컬렉션의 모든 소문자 요소들을 대문자로 바꾸는 새로운 컬렉션 

import java.util.Arrays;
import java.util.List;


public class Main {
    public static void main(String[] args) {
      String[] lowercaseArray = new String[]{"public","static","void"};
      List<String> lowercaseList = Arrays.asList(lowercaseArray);
      List<String> uppercaseList = lowercaseList.stream()
              .map(value->value.toUpperCase()).toList();
      uppercaseList.stream().forEach(value-> System.out.println(value));
    }
}

/*
PUBLIC
STATIC
VOID */

 

5. Optional 

- 널(null)이 들어 있는 레퍼런스 변수의 멤버(필드나 메서드)에 접근하려고 할 때 발생하는 예외인 NullPointerException을 해결하기 위해 등장 

 

.java NullPointerException 발생 

public class Main {
    private static String getSomeString(){
        return null; // 이 메서드는 항상 null을 반환
    }
    public static void main(String[] args) {
      String isThisNull = getSomeString();

        System.out.println(isThisNull.toUpperCase());
    }
}

 

 

.java 비어 있는 Optional 반환 

import java.util.Optional;

public class Main {
    private static Optional<String> getSomeString(){
        return Optional.empty(); //null을 반환하는 것이 아니라 비어 있는 Optional을 반환
    }
    public static void main(String[] args) {
      Optional<String> isThisNull = getSomeString();

        isThisNull.ifPresent(str-> System.out.println(str.toUpperCase()));
    }
}

 

- Optional로 선언된 메서드에서 반환된 문자열이 비어 있지 않은 경우(empty가 아닌 경우)에는 ifPresent의 인자로 들어간 람다 표현식을 실행하고, 비어 있는 경우에는 실행되지 않음