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의 인자로 들어간 람다 표현식을 실행하고, 비어 있는 경우에는 실행되지 않음
'SpringBoot > 백엔드' 카테고리의 다른 글
| [이것이 백엔드 개발이다] ch 6. 백엔드 개발에 필요한 최소한의 HTML (0) | 2026.05.24 |
|---|---|
| [이것이 백엔드 개발이다] ch 5. API 호출 클라이언트 페이지 만들기 (0) | 2026.05.23 |
| [이것이 백엔드 개발이다] ch 4. 서버와 클라이언트 (0) | 2026.05.10 |