문자열 객체. 불변(immutable)이라 한 번 만들어지면 수정이 불가능하다. 변경할 때마다 새로운 객체가 만들어진다.
“hello” 와 같이 쌍따옴표로 작성된 문자열이다. 자바의 String Pool에 저장된다. 같은 문자열이 여러번 사용되면 하나의 인스턴스만 사용해서 메모리를 절약할 수 있다.
새로운 String 객체를 Heap메모리에 만들어서 사용한다. 같은 내용의 문자열이라도 각 각 다른 객체로 만들어진다.
가변적(mutal)이면서 빠른 속도로 문자열을 변경 할 수 있다.
동기화 지원은 하지 않는다. ( 동기화 : 여러 스레드가 동시에 접근할때의 안정성 )
StringBuilder와 비슷하지만 동기화를 지원한다. 그러므로 여러 스레드가 동시에 접근해도 안전하다. 하지만 속도는 StringBuilder보단 느리다.
프로그램에서 발생할 수 있는 문제이다. 개발자가 처리할 수 있다.
프로그램 외부 또는 심각한 문제… 개발자가 쉽게 처리할 수 없는 것이다.
어플리케이션 코드에서는 일반적으로 Error를 잡아서 처리하지 않고, 처리하는 것을 권장하지도 않는다.
throw new IllegalArgumentException("잘못된 값임!!!!");
public void myMethod() throws IOException {
// 메서드에서 IOException이 발생할 수 있음
}
그럼 왜 상위 계층에서 예외 처리를 하는 것이 더 나을까?
서비스나 어플리케이션의 구조에 따라서 특정 메서드는 단순히 예외를 던지고, 더 높은 계층의 메서드에서 예외를 처리하는 것이 더 의미 있는 경우가 있다. ... -> 언제일까?
모든 예외(Exception)와 에러(Error)의 최상위 클래스이다. (=부모 클래스)
Java에서 예오 처리가 가능한 모든 객체의 부모로 프로그램의 정상적인 흐름을 방해할 수 있는 상황을 나타낸다.
Throwable의 자식 클래스 중 하나. 개발자가 처리할 수 있는 문제만 포함한다.
프로그램 내에서 발생할 수 있는 일반적인 예외 상황을 나타내고 try-catch block을 사용해서 처리할 수 있다.
finally 블록은 예외가 발생하든 안하는 항상 실행된다. 주로 자원을 정리하거나 닫을 때 사용된다.
try {
// 예외가 발생할 수 있는 코드
} catch (Exception e) {
// 예외 처리
} finally {
System.out.println("여기는 항상 실행되는 공간!");
}
제네릭은 클래스나 메서드에 사용할 타입을 미리 지정하지 않고, 객체를 생성하거나 메서드를 호출 할 때 타입을 지정해서 사용하는 기능이다.
장점 : 타입 안정성을 보장해주고 코드의 중복을 줄일 수 있다.
public class Box<T> {
private T content;
public void setContent(T content) {
this.content = content;
}
public T getContent() {
return content;
}
}
제네릭 클래스를 정의할때는 위와 같이 타입을 미리 지정하지 않고 타입 매개변수 T를 사용한다.
Box<String> stringBox = new Box<>();
stringBox.setContent("Hello");
Box<Integer> intBox = new Box<>();
intBox.setContent(123);
Box 클래스는 어떤 타입이든 사용할 수 있도록 설계되어서, 위에 보이는 코드처럼 String이든 Integer든 객체를 생성할 때 타입을 지정해서 넣어준다.
ArrayList<String> list = new ArrayList<>();
list.add("Hello");
// list.add(123); // 컴파일 오류, String 타입만 허용
제네릭을 통해 ArrayList가 String타입의 객체만 저장할 수 있도록 지정해두었다.
ArrayList list = new ArrayList(); // 제네릭을 사용하지 않았을 때
list.add("Hello");
list.add(123); // 다른 타입도 추가 가능!
String str = (String) list.get(0); // 타입 변환
int num = (int) list.get(1); // 타입 변환 위의 코드처럼 list에 모든 타입의 객체를 추가할 수 있어서 캐스팅이 필요하다.💡
ArrayList
HashMap<K, V>
HashSet
자바에서 코드를 더 간결하고 읽기 쉽도록 만든 함수 표현식이다.
(x, y) -> x + y; // 두 수를 더하는 람다식
데이터의 흐름을 다루는 도구.
주로 필터링, 변환, 집계등의 작업을 할 때 사용된다.
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream().filter(name -> name.startsWith("A")).forEach(System.out::println);
코드의 간결성과 가독성을 높이고 병렬 처리를 쉽게 하기 위해 도입되었다.
코드에 메타데이터를 추가해 특별한 의미나 동작을 부여한다.
목적 : 코드의 명확성을 높이고 컴파일러나 런타임 환경에서 특정 기능을 트리거할 수 있다.
실행중에 클래스의 구조(필드, 메서드)를 탐색하고 수정할 수 있는 기능이다.
어노테이션을 통해 메타데이터를 읽어 특정 동작을 실행할 수 있다.
위 클래스는 I/O작업이기 때문에 데이터를 출력할 때 마다 리소스를 사용하기에 속도가 느리다. 많은 데이터를 출력할 때 더욱이 성능 저하가 발생할 수 있다.
입출력 작업은 속도가 많이 소요되기 때문에 대량의 데이터를 다룰때에는 로그를 비동기식으로 처리하거나 적절한 로그 라이브러리를 사용하는 것이 좋다.
sout호출보다 속도가 훨씬 빠르다.