

프로그램 동작 도중 모종의 이유로 수행 중인 동작에 예상하지 못한 영향을 받는 것
Exception은 class이며,Throwable 라는 class를 상속했다.public class Main {
public static void main(String []args) {
throw new IllegalArgumentException("예외도 객체처리 합니다.");
}
}
new로만 exception을 만들면 프로그램이 그저 메모리에 올릴 뿐 예외를 인식 못할 수 있다. throw로 예외 상황을 띄워줘야 한다.
NullPointerException : 컴파일은 되지만 실행 도중 예외 상황이 발생한다.IOException : 해결방법을 마련하지 않으면 아예 컴파일이 되지 않는다. 자바에서 컴파일 시점에 검사가 이루어지며, 프로그램이 예외 발생 가능성을 명시적으로 처리하도록 강제한다. 반드시 예외 처리가 필요하며, 이를 무시하면 컴파일 오류가 발생한다.
Exception을 바로 상속받은 예외들은 체크드 예외이다.try-catch 를 이용하여 예외 처리를 해주거나, throws 키워드를 사용하여 예외처리를 호출하는 시점으로 미루는 방법이 있다. 프로그램 실행 중에 발생하는 예외 중 컴파일러가 체크하지 않는 예외이다. 명시적으로 예외 처리를 하지 않아도 프로그램이 컴파일된다. 즉, 프로그램 실행 중에 예외가 발생할 수 있으며, 이를 사전에 처리하지 않으면 프로그램이 예기치 않게 종료될 수 있다.
RuntimeException 클래스를 상속받은 하위클래스들이 언체크드 예외이다.NullPointerException도 이에 해당한다.
- 메서드에서 예외가 발생할 수 있음을 알리는 데 사용하는 키워드
- 메서드 시그니처에서 사용한다.
- 메서드가 호출될 때 특정 예외가 발생할 가능성이 있다는 것을 메서드를 사용하는 시점에 알린다.
Checked Exception일 때
throws가 있으면, 해당 메서드를 호출하지 않는다면 컴파일 에러가 발생하지 않는다. (예외처리를 호출 시점에 미루는 것)throws가 없으면 컴파일 중 오류가 발생한다.
- 언체크드 예외일 때는, 메서드를 실행한다.
프로그램 실행 중 발생할 수 있는 예외를 적절하게 관리하여 프로그램이 중단되지 않고 안정적으로 실행될 수 있도록 하는 방법
try {
// 예외 발생 가능성이 있는 명령문
} catch (예외타입 변수명) {
// 예외 발생 시 처리할 명령문
} finally {
// **예외 처리와 상관없이 반드시 실행**되는 명령문
// finally는 생략 가능
}
try-catch 에서 예외가 1개 이상의 catch문에 걸릴 수 있을 때, 가장 먼저 걸리는 catch문에 들어가게 된다.
- 원하는 시점에 예외를 강제로 발생시키는 것
- 예외 역시 객체이기 때문에 throw를 사용하여 예외를 발생시킬 수 있다.
try { throw new Exception("예외"); } catch(Exception e) {
시스템 수준에서 발생하는 심각한 문제를 나타내며, 일반적으로 프로그램에서 처리할 수 없는 상황을 의미
Error도 Throwable을 상속했기 때문에 try-catch를 구현할 수 있지만, 이를 통해 처리하는 걸 절대 추천하지 않는다. => 예외적으로 시스템에 의해 자동으로 처리되거나, 발생 즉시 프로그램을 중단시킬 수 있다.클래스나 메서드를 정의할 때, 데이터 타입을 일반화(Generalization)하여 사용할 수 있게 하는 기능
클래스 정의 시 타입 매개변수를 사용하여 다양한 데이터 타입을 처리할 수 있는 클래스
public class 클래스명<문자> { // 제네릭 클래스에 쓰인 <문자>는 메서드에 쓰인 제네릭과 별개다.
public 문자 field1;
public 문자 method1() {
...
}
}
MyGeneric<String, int, boolean> generic = new MyGeneric<>(); 와 같이 primitive type은 타입으로 왜 못 넣을까?NULL을 포함할 수 있어야 한다.클래스, 인터페이스, 메서드를 정의할 때 사용하는 형식화된 변수이다. 이 변수는 구체적인 데이터 타입(자료형)이 아닌 타입 그 자체를 나타낸다. (이 말은 N이라고 해서 무조건 Number만 가능한 게 아니라는 뜻) 해당 타입은 제너릭 클래스나 메서드를 사용하는 시점에 지정된다.
| 타입(Type) | 구분 |
|---|---|
<T> | Type |
<E> | Element |
<K> | Key |
<V> | Value |
<N> | Number |
public class Clazz<T> {
public static T field1;
}
제네릭 타입의 객체를 생성할 때 타입을 명시하지 않고 간결하게 코드를 작성할 수 있도록 도와주는 연산자
Box**<String>** myBox = new Box<String>();
Box<> myBox = new Box<String>(); : 문제 발생
Box<String> myBox = new Box<>();
Map<String, List<Integer>> map = new HashMap<String, List<Integer>>();
Map<String, List<Integer>> map = new HashMap<>();
접근제어자 static <제네릭 타입> 함수반환타입 메서드이름(<제네릭 타입> 매개변수, ...) {
}
// <T> 는 반환타입이 아니라 매개변수 타입 !!
public <T> void printAry(T[] arr) {
for (T el : arr) {
System.out.println(el);
}
}
public class MyClass1<T> {
public static void method1(T t) {
.. // 컴파일 에러 발생
}
}
public class MyClass2 {
pbulic static void <T> method2(T t) {
...
}
}
Generic의 타입은 instance가 생성될 때 정해진다.MyClass1의 제네릭 타입 T는 인스턴스가 생성될 때 결정이 되는데, static 메소드는 인스턴스 생성과 별도로 메모리에 올라와 있다. 그렇다면 MyClass1이 생성되는 시점에 결정되는 제네릭 타입을 메서드가 매개변수로 받아낼 방법이 없다.MyClass2의 메소드는, 호출되는 시점에 타입이 결정되기 때문에 컴파일 에러가 발생하지 않는다.public class MyStaticGeneric<T> {
private static T name; // 불가능하다 -> private T name; 은 가능
static 제네릭 함수의 타입은 호출 시점에 확정된다. 즉, 제네릭 메서드의 타입 파라미터는 메서드가 호출될 때 구체화된다.public class MyStaticGeneric<T> {
public static <T> String test1(T data) { // String은 반환형, T는 매개변수 타입
System.out.println("data = " + data);
return "ok";
}
}
static 메소드이기 때문에 직접 호출이 가능하다. MyStaticGeneric.test1("Hello"); 와 같이 static인 함수를 인스턴스 생성없이 할 수 있다.
- 타입 매개변수에 대해 특정 타입이나 타입 계층을 설정하여 제네릭 클래스나 메서드가 처리할 수 있는 타입을 제한하는 기능
extends키워드를 사용하여 제네릭 타입 매개변수의 범위를 제한할 수 있다.
public class Box<T extends Number> {
public T field1;
public T method1() {
}
}
interface A {
}
class B implements A{ // 가능
}
class C extends B{ // 가능
}
class D {
}
class GenericTest<T extends B & A> { // B의 하위 클래스 + A의 구현체가 올 수 있다.
}
// new GenericTest<D>(); 불가능
GenericTest<C> cGenericTest = new GenericTest<>();
GenericTest<B> bGenericTest = new GenericTest<>();
GenericTest의 타입 T는 B 혹은 A의 하위타입이어야만 한다.제네릭 타입 매개변수의 구체적인 타입을 알 수 없거나, 여러 가지 타입 중 하나를 허용할 필요가 있을 때 사용된다. => 어떠한 타입도 다 된다.
interface A {
}
class B implements A{
}
class C extends B{
}
class D extends C {
}
class E extends D {
}
//1.
public void method1(Clazz<? extends C> a) {
// A,B : 불허, C,D,E : 허용
}
//2.
public void method1(Clazz<? super C> a) {
// A,B,C : 허용, D,E : 불허
}
C보다 상위 클래스는 올 수 없다. (C는 가능)C보다 상위 타입만 올 수 있다. C를 상속받은 건 올 수 없다. (C 가능)Java에서
NullPointerException을 방지해주는, 즉,null인 값을 참조해도NullPointerException이 발생하지 않도록 값을 래퍼로 감싸주는 타입
.empty()
정보
기능 : 비어있는 Optional 객체를 생성
리턴값 : Optional<T>
예제 코드
public static <T> Optional<T> empty() {
return new Optional<>(null);
}
Optional<Object> empty = Optional.empty();
.of(T value)
정보
기능 : 전달된 값으로 새로운 Optional 객체를 생성 (Null일 수 없는, Null이라면 예외처리를 한)
리턴값 : Optional<T>
예제 코드
public static <T> Optional<T> of(T value) {
// if(value == null) {
// throw new NullPointerException();
// } -> requireNonNull 함수랑 동일
return new Optional<>(Objects.requireNonNull(value));
}
try{
Optional.of(null);
} catch (NullPointerException e) {
System.out.println("Null은 보관할 수 없습니다!");
System.out.println(e.getMessage());
}
.ofNullable(T value)
정보
기능 : 비어있을 수도 있고, 아닐 수도 있는 Optional 객체를 생성
리턴값 : Optional<T>
예제 코드
public static <T> Optional<T> ofNullable(T value) {
return value == null
? new Optional<>(null)
: new Optional<>(value);
}
String imNull = null;
Optional<Object> opt1 = Optional.ofNullable(imNull);
Optional<Object> opt2 = Optional.ofNullable("Hello");
.get()
정보
기본 : Optional 객체의 값을 가져온다.
리턴값 : T
예제 코드
public T get() { // 반환형 T
if (data == null) {
throw new NoSuchElementException("No value present");
}
return data;
}
Optional<Object> empty = Optional.empty();
try{
empty.get();
} catch (NoSuchElementException e) {
System.out.println(e.getMessage());
}
.isEmpty()
정보
기능 : Optional 객체가 비어있는지 확인
리턴값 : boolean
예제 코드
public boolean isEmpty() {
return data == null;
}
boolean isEmpty = empty.isEmpty();
}
.isPresent()
정보
기능 : Optional 객체가 있는지 확인
리턴값 : boolean
예제 코드
public boolean isPresent() {
return data != null;
}
boolean isPresent = empty.isPresent();
}
Q. throws는 그럼 다른 개발자들에게 예외가 발생할 수 있다는 걸 알려주는 것이 주 목적인 건가요
A. 정확히는 해당 메서드를 사용하는 “주체”에게 해당 메서드는 예외가 발생할수 있다는 것을 알려주기 위해 사용합니다.
우리가 만드는 메서드는 좁게 바라보면 개발자가 사용하지만 시선을 넓게 바라보면 다른 시스템이 호출할 수도 있습니다. 따라서, 다른 개발자들에게 라기보다는 이 메서드를 호출하는 주체에게 예외가 발생할 수 있다는것을 알리는 용도로 사용한다로 보는게 더 좋을 것 같습니다 🙂
throws의 의미가 강의들을 때는 모호했는데 강사님이 대답해주신 답과 복습하면서 다시 보니 개념이 더 확실히 이해가 되었다.
아니 매번 실습 코드를 바로 타이핑하고 커밋하고 있었는데,,, 오늘 그냥 어쩌다 깃헙 profile overview에 들어갔는데.. 잔디밭에 커밋 기록이 없다..? 이게 뭔.. 하.. 찾아보니까 로컬에서 커밋할 때 email을 설정 안 해준 것이었다. 예전에 이미 다 해놨었는데 언제 풀린 건지.. 토큰 바꿀 때 이상하게 만졌나? 암튼 그래서 이전 커밋 기록이 다 없다..
우선 중요한 email 설정은 해주었다. 그래서 오늘 실습 커밋들은 다 정상적으로 올라가는 것을 확인하였다. 하지만, 이전 커밋 기록들은 여전히 기록되지 않았다. 해결 방법이 적힌 사이트를 참고해서 해보겠지만.. 너무 복잡해보인다. 그래서 걱정은 되지만 일단 해보겠다 ! :) 꼬이면 깃헙 언제나처럼 미워할 것이야 그러니까 (깃헙 너) 잘하도록.
https://wellbell.tistory.com/43
오늘도 2시간 팀원들과 열공했다. (물론, 따로하지만 혼자하는 것보다 좋은 듯..(?)) 오늘 RBF 어떻게 할지 다시 살짝 의논하고, 슬랙 채널도 활성화...하자고 하루에 적어도 메세지 하나는 남기기로 했다 ! 그리고 오늘 팀원 분 중 한 분이 ZEP이라는 플랫폼으로 혼자 공부할 때 플랫폼에서 같이 해보자! 라고 제안해주셔서 너무 좋았다 !!
지금까지 정말 많은 걸 배운 것 같다. 이제 갈수록 스프링에서 실제 잘 쓰는 기능(?)들이 함께 소개가 되는 것 같다. 스프링을 아직 잘 몰라서 겁이 난다 호호 그치만 뭐 잘 해내겠지 ~ 암튼 그래서 더 이해를 잘 하고 넘어가는 것이 중요할 것 같다 ! 오늘도 수고하였다 ! 벌써 수요일 금요일 언제 오나~..