Java는 Java 8, 11, 17, 21 등의 LTS(Long-Term Support) 버전이 주로 사용되며, 그 외의 버전은 단기 지원입니다.
✅ 주요 특징:
() -> {}) 예제 - Lambda 표현식
// 기존 방식 (익명 클래스)
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("Hello, Java!");
}
};
// 람다 표현식 사용
Runnable r2 = () -> System.out.println("Hello, Java!");
r1.run();
r2.run();
✅ 주요 특징:
module-info.java) try-with-resources 개선 (AutoCloseable 자동 적용) private 인터페이스 메서드 지원 예제 - List.of() 사용
List<String> names = List.of("Alice", "Bob", "Charlie");
✅ 주요 특징:
var 키워드 도입 (지역 변수 타입 추론) Optional.orElseThrow() 추가 예제 - var 사용
var message = "Hello, Java 10";
System.out.println(message);
✅ 주요 특징:
var 키워드를 람다 매개변수에서도 사용 가능 String 메서드 추가 (isBlank(), lines(), repeat()) Files.writeString(), Files.readString() 추가 예제 - String의 repeat() 메서드
String text = "Hello! ";
System.out.println(text.repeat(3)); // Hello! Hello! Hello!
✅ 주요 특징:
switch 문 개선 (break 없이 사용 가능) """ """ - 여러 줄 문자열) record 타입 도입 sealed class 도입 (클래스 확장 제한) Pattern Matching for instanceof (instanceof 개선) 예제 - Java 14 record 사용
public record Person(String name, int age) {}
Person p = new Person("Alice", 30);
System.out.println(p.name()); // Alice
✅ 주요 특징:
sealed class 정식 도입 (상속 제한 가능) Pattern Matching for switch (switch 문에서 instanceof 대체 가능) Foreign Function & Memory API (JNI 대체 실험 기능) 예제 - sealed class 사용
sealed class Animal permits Dog, Cat {}
final class Dog extends Animal {}
final class Cat extends Animal {}
✅ 주요 특징:
예제 - Virtual Threads (가벼운 스레드)
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> System.out.println("Hello from virtual thread!"));
}
실무에서는 Java 8, Java 11, Java 17, Java 21이 주로 사용됩니다.
"Java 8 이전 버전도 사용해봤는지?"
Java 8 이전 버전에서 작성된 레거시 시스템이나 구형 애플리케이션을 다뤄본 경험이 있는지 확인하는 것. 많은 기업들이 여전히 Java 7이나 Java 6 같은 이전 버전에서 돌아가는 시스템을 운영하고 있기 때문에, 이전 버전의 Java를 다뤄본 경험이 있는지 확인하고 싶어할 가능성이 크다.
Java 8 이전 버전에서는 람다 표현식이나 Stream API와 같은 기능이 없었으므로, 기존의 Java 문법과 구조에 대한 이해도 중요한 요소이다. Java 8 이전의 익명 클래스나 기존의 for문, Runnable 사용법 등을 잘 알고 있는지 확인하고 싶은 것일 수 있다.
Java 8 이전 버전에서의 경험을 물어보는 이유는 다양한 환경에서 개발을 해본 경험을 갖추었는지 확인하려는 목적일 가능성이 크다. 최신 버전의 기능을 사용할 수 있지만, 구버전 코드와 호환되는 방식으로 작업할 수 있는 능력도 중요하기 때문이다.
대부분의 기업들이 구형 버전의 Java에서 새로운 기능을 추가하거나 유지보수하는 작업을 진행하고 있기 때문에, 구버전 Java를 사용한 경험이 있으면 그 부분에 대해 보다 효율적이고 신속한 대응이 가능할 것이라고 예상할 수 있다.
Java 8에서 Stream API를 통해 컬렉션을 함수형 스타일로 처리할 수 있습니다.
<대표적인 메서드>
filter(Predicate<T>): 조건에 맞는 요소 필터링 map(Function<T, R>): 요소 변환 collect(Collectors.toList()): 결과를 리스트로 변환 forEach(Consumer<T>): 요소 반복 처리 reduce(BinaryOperator<T>): 요소를 하나로 축약 메소드 활용 예제:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> filteredNames = names.stream()
.filter(name -> name.startsWith("A"))
.collect(Collectors.toList());
//ArrayList의 요소를 변환할 때 - map();
//`map(Integer::parseInt)`를 사용하여 `String`을 `Integer`로 변환
List<String> numbers = Arrays.asList("1", "2", "3");
List<Integer> intNumbers = numbers.stream()
.map(Integer::parseInt)
.collect(Collectors.toList());
기본 DTO (Getter/Setter 포함)
public class UserDTO {
private String name;
private int age;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
불변 객체 (Setter 없음)
public class ImmutableUserDTO {
private final String name;
private final int age;
public ImmutableUserDTO(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
Java 14+ record 사용
record는 자동으로 불변 객체를 만들어 줌.public record UserDTO(String name, int age) {}
final 사용
final로 선언하여 불변성 보장.public final class ImmutablePerson {
private final String name;
private final int age;
public ImmutablePerson(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
Setter 사용 (Mutable 객체)
public class User {
private String name;
public void setName(String name) {
this.name = name;
}
}
생성자 사용 (Immutable 객체)
final을 사용하여 불변 객체를 구현.public class User {
private final String name;
public User(String name) {
this.name = name;
}
public String getName() { return name; }
}
final 활용final을 사용하여 불변 객체 및 상수 값을 안전하게 관리할 수 있음.static final을 사용하여 상수 값 정의.final 활용불변 객체에서 final은 객체의 상태가 한 번 설정되면 변경되지 않도록 보장합니다.
final을 사용하여 객체의 필드를 초기화 후 변경하지 않도록 하는 방식입니다.
final을 사용하면 생성자에서만 초기화가 가능하고, 이후에는 변경할 수 없습니다.public final class ImmutablePerson {
private final String name;
private final int age;
public ImmutablePerson(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
final 활용일반 객체에서 final을 사용하면 값을 한 번만 할당할 수 있게 만들 수 있습니다.
이는 불변성을 유지하려는 목적에서 사용될 수 있지만, 객체 자체를 불변 객체로 만드는 것은 아님.
public class FinalExample {
private final String name;
public FinalExample(String name) {
this.name = name; // final 필드는 한 번만 할당
}
public String getName() { return name; }
}
이 경우, 객체는 여전히 변경 가능하지만, name 필드는 변경할 수 없도록 final을 사용하여 설정합니다.
final을 사용한 상수 정의 ]final을 사용하여 상수 값을 정의할 때도 사용됩니다. 이 경우 값은 한 번만 할당되고, 이후 변경할 수 없습니다.
public class Constants {
public static final String APP_NAME = "MyApplication"; // 상수 정의
}
final을 사용하여 객체의 상태를 변경 불가능하게 보장합니다.final을 사용하여 객체의 특정 속성이 변경되지 않도록 할 수 있으며, 이는 불변성을 보장하는 방식의 일환일 수 있습니다.final은 값을 한 번만 할당할 수 있게 하므로, 값이 변경되지 않도록 보장하는 데 유용합니다.final 필드, Setter 없음, 생성자를 통해 초기화 후 변경 불가.record: 간결한 불변 객체 표현.final: 불변 객체 보장, 상수 값 정의, 안전한 초기화.