문제 CAR_RENTAL_COMPANY_RENTAL_HISTORY 테이블에서 2022년 10월 16일에 대여 중인 자동차인 경우 '대여중' 이라고 표시하고, 대여 중이지 않은 자동차인 경우 '대여 가능'을 표시하는 컬럼(컬럼명: AVAILABILITY)을 추가하여 자동차 ID와 AVAILABILITY 리스트를 출력하는 SQL문을 작성해주세요. 이때 반납 날짜가 2022년 10월 16일인 경우에도 '대여중'으로 표시해주시고 결과는 자동차 ID를 기준으로 내림차순 정렬해주세요.
문제 설명 어떤 문장의 각 알파벳을 일정한 거리만큼 밀어서 다른 알파벳으로 바꾸는 암호화 방식을 시저 암호라고 합니다. 예를 들어 "AB"는 1만큼 밀면 "BC"가 되고, 3만큼 밀면 "DE"가 됩니다. "z"는 1만큼 밀면 "a"가 됩니다. 문자열 s와 거리 n을 입력받아 s를 n만큼 민 암호문을 만드는 함수, solution을 완성해 보세요.
제한 조건 공백은 아무리 밀어도 공백입니다. s는 알파벳 소문자, 대문자, 공백으로만 이루어져 있습니다. s의 길이는 8000이하입니다. n은 1 이상, 25이하인 자연수입니다. 입출력 예 s n result "AB" 1 "BC" "z" 1 "a" "a B z" 4 "e F d"
자바에서 사용자의 입력실수, 스택오버플로우, 메모리부족등의 문제가 생길때 그 문제를 해결하기위해서는 자바에서는 예외 처리가 있다.
오류 시스템 레벨에서 환경적인 이유로 일반적으로 회복이 불가능한 오류이다. 어떠한 에러인지 확인하고 대응을 한다
예외 코드 레벨에서 처리할수 있는 문제사항이다.
컴파일 에러 컴파일이란 코드를 컴퓨터가 이해 할 수 있는 언어로 변환되는 과정인데 프로그래밍 언어의 규칙을 지키지 않았을때 발생하며 존재하지않은 클래스 호출, 접근이 불가능한 프로퍼티나 메소드에 접근하려고 할때 뜬다. 해결법 : 문법에 맞게 다시 작성하는것이다
런타임 에러 runtime : 프로그램이 수행되고 있는 때 컴파일은 됐지만, 프로그램이 실행중 예외를 만나게되어 중지되는 오류이다.
확인된 예외 컴파일 시점에서 발생하는 예외로, 반드시 예외처리를 해야만 컴파일이 성공적으로 진행된다.
미확인된 예외 런타임 시점에서 발생하는 예외로, 예외처리가 반드시 필요하지는 않지만, 프로그램이 정지가 되거나, 넘어가는 에러이다.
예외발생과 예외처리방법
클래스 생성
예외 발생시 예외를 처리하기 위한 클래스를 생성할 수 있다.
throws, throw
classOurClass{
privatefinal Boolean just = true;
// 신규 문법 throws!publicvoidthisMethodIsDangerous()throws OurBadException {
if (just) {
// 신규 문법 throw!thrownew OurBadException();
}
}
}
throws와 throw를 사용하는 방법이고, just가 true라서 ourbadexception이 실행됨을 알수있다.
throws는 메서드의 선언부 뒤에 위치하게 되며, 예외가 발생할때 어떤 예외처리 메서드를 던질지 명시한다. throw는 실제 예외를 던질때 사용되며, 특정 조건이 만족된다면 직접 예외객체를 생성한후 던지게된다.
try - catch 예외가 발생할것 같은 코드에 실행후 오류가 발생한다면 예외처리를 해준다.
publicclassStudyException{
publicstaticvoidmain(String[] args) {
OurClass ourClass = new OurClass();
try {
// 1. 위험한 메소드의 실행을 "시도" 해 봅니다.// "시도" 해보는 코드가 들어가는 블럭입니다.
ourClass.thisMethodIsDangerous();
} catch (OurBadException e) {
// 2. 예외가 발생하면, "잡아서" handling 합니다.// 예외가 발생하는경우 "handling" 하는 코드가 들어가는 블럭입니다.// 즉 try 블럭 내의 구문을 실행하다가 예외가 발생하면// 예외가 발생한 줄에서 바로 코드 실행을 멈추고// 여기 있는 catch 블럭 내의 코드가 실행됩니다.
System.out.println(e.getMessage());
} finally {
// 3. 예외의 발생 여부와 상관없이, 실행시켜야 하는 코드가 들어갑니다.// 무조건 실행되는 코드가 들어가는 블럭입니다.
System.out.println("우리는 방금 예외를 handling 했습니다!");
}
}
}
try문에는 원래 실행할 코드가 들어가고 catch는 예외가 발생하였을때 처리할 방법을 적는다 finally는 예외의 발생여부상관없이 무조건 실행된다, 즉 예외가있든 없든 실행된다고 보면된다. 요약하여 예외가 발생하였을때는 try에서 즉시 (다음 코드가 남아있어도 그자리에서 중지하고) catch로 간후 finally를 출력하고 try에서 예외가 발생하지 않았다면 finally로 가서 수행한다.
e.getMessage()는 오류 메세지를 출력해준다
publicclassMultipleCatchExample {
publicstaticvoidmain(String[] args) {
try {
int[] numbers = {1, 2, 3};
System.out.println(numbers[5]); // ArrayIndexOutOfBoundsExceptionint result = 10 / 0; // ArithmeticException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("배열의 인덱스가 잘못되었습니다: " + e.getMessage());
} catch (ArithmeticException e) {
System.out.println("산술 연산 오류: " + e.getMessage());
} catch (Exception e) {
// 모든 다른 예외를 잡기 위한 catch 블록
System.out.println("예기치 않은 오류가 발생했습니다: " + e.getMessage());
} finally {
System.out.println("예외 처리 완료.");
}
}
}
catch문은 여러개를 둘 수 있는데 첫번째 캐치문이 그 예외를 처리하지못한다면 다음으로,, 또 다음으로 넘긴다. 모든 예외는 익셉션클래스에서 파생되므로, 마지막 매개변수는 그외 모든 에러를 처리한다.
만약 try 두번째줄의 오류가 두번째 catch문에서 예외를 처리했다면(위 코드와 다름) try 첫번째줄 > try 두번째줄 > catch 첫번째문 > catch 두번째문(예외처리) > finally 이렇게 동작하게 된다.
예외클래스
Throwable 클래스 모든 클래스는 Object 클래스로 부터 파생되었다 흔히 볼 수 있는 배열 범위 초과, 널 포인트 에러들은 따로 예외 처리를 하지 않더라도 컴파일 시점에서는 문제 없이 통과되지만, 실행 시 예외가 발생하면 프로그램이 중단된다. 이 말의 뜻은 이러한 예외들은 코드 레벨에서 복구가 가능하지만, 예외 처리를 하지 않으면 실행 중에 프로그램이 비정상적으로 종료된다는 것이다.
이미 만들어진 예외를 처리할수 있는 방법이 많다. 없으면 예외 클래스를 구현하여 직접 만들수 있다.
예외 처리하는법
chained Exception 예외가 서로 연결되어있을때 a가 예외 b를 발생하였다면 a는 b의 원인이다
예를들어 파일을 읽으려고했는데 파일이 없어서 A가 발생했다 이예외때문에 다른 작업이 실패해서 예외 B가 발생했다. 이때 예외 B를 던지면서, 예외 A를 기록하여 나중에 끝 예외에갔을때 이 예외가 어디로부터 시작되었는지 알기 쉽게한다.
publicclassMain{
publicstaticvoid main(String[] args) {
try {
// 예외 생성
NumberFormatException ex = new NumberFormatException("가짜 예외이유");
// 원인 예외 설정(지정한 예외를 원인 예외로 등록)
ex.initCause(new NullPointerException("진짜 예외이유"));
// 예외를 직접 던집니다.throw ex;
} catch (NumberFormatException ex) {
// 예외 로그 출력
ex.printStackTrace();
// 예외 원인 조회 후 출력
ex.getCause().printStackTrace();
}
// checked exception을 감싸서 unchecked exception 안에 넣습니다.thrownewRuntimeException(newException("이것이 진짜 예외 이유입니다."));
}
}
initCause() : 예외를 연결하는 메서드 getCause() : 예외를 반환하는 메서드
ex라는 예외를 생성한다, 그 예외는 initCause 메서드를 사용하여 원인 예외를 설정한다
예외를 직접 던져, number~~~~~~예외가 발생하고 그 원인은 nullpointer~~인것이다.
try 블록에서 발생한 예외를 catch 블록에서 잡으며 printStackTrace 메서드를 사용하여 예외의 스택 트레이스(예외 처리과정의 로그)를 출력한다 getCause 메서드를 사용하여 원인 예외(NullPointerException)의 스택 트레이스도 출력한다..
위 코드에서 원래 checkexception을 사용하려면 try catch문으로 감싸야겠지만, runtimeException 안에 exception을 넣음으로써 unchecked exception처럼 만든다initCause의 내용은 getCause에서 뜨게된다.이에대한 장점은 예외가 발생한 근본적인 원인을 찾기에 편하다
numberformatException보다는 nullpointerException이 더 에러를 직관적으로 알 수 있다.
예외연결의 장점 여러 예외상황에서 발생한 문제를 특정 예외로 추상화 하여 처리할수 있기 때문이다 (가독성에 좋음)
클래스나, 메서드에 사용할수 있으며, 이름 뒤에 <>이 입력되며 <>안에 들어가야할 타입 변수를 지정한다. T는 다른 개발자들이 암암리에 정해놓은 규약이기때문에 바꿔도된다.
선언해둔 T는 특정한 타입이 들어갈 자리에 대신 들어갈 수 있다. 메서드의 리턴타입또한 가능하다.
아래 main문에서는 String을 입력했으며, 제네릭 클래스의 T부분에는 모두 String이 들어간다.
제네릭 문법
publicclassGeneric<T> { ... }Generic<String> stringGeneric = new Generic<>();
제네릭을 사용한 클래스를 제네릭 클래스라고 하며, 변수명 T는 타입변수라고 한다.
static 멤버에 사용할 수 없다
다수의 타입변수를 사용 할 수 있다
publicclassGeneric<T, U, E> {
public E multiTypeMethod(T t, U u) { ... }
}
Generic<Long, Integer, String> instance = new Generic();
instance.multiTypeMethod(longVal, intVal);
<? extends T> : T와 그 자손들만 사용 가능 <? super T> : T와 그 조상들만 가능 <?> : 제한 없음
제네릭과 인터페이스를 사용한 List
List 리스트는 추상적 자료구조이다 (리스트 인터페이스는 추상적으로 구현해서 어레이리스트와 링크드리스트가 상속을해서 구체화한것이다) 순서가있고 중복을 허용해준다 list는 인터페이스로 이고 제네릭으로 만들어졌다. Collection을 상속받은것을 볼 수 있다. 제네릭을 사용함으로써 코드의 재사용성을 높이고, 다양한 데이터 타입을 안전하게 처리할 수 있다. 예를들어 List<Integer> 이나 List<String>처럼 구체적인 타입을 하나의 인터페이스만으로 구현을 할 수 있다.
Collection또한 제네릭으로 만든 인터페이스이며 인터페이스끼리 상속을 할시에는 extends를 사용할 수 있다.
list는
//list.java
int size();
boolean isEmpty();
boolean contains(Object o);
Object[] toArray();
boolean add(E e);
boolean remove(Object o);
//ArrayList.javapublicclassArrayList<E> extendsAbstractList<E>
implementsList<E>, RandomAccess, Cloneable, java.io.Serializablepublicintsize() {
checkForComodification();
return size;
}
publicbooleanisEmpty() {
return size == 0;
}
publicbooleancontains(Object o) {
return indexOf(o) >= 0;
}
publicObject[] toArray() {
return Arrays.copyOf(elementData, size);
}
privatevoidadd(E e, Object[] elementData, int s) {
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}
public E remove(int index) {
Objects.checkIndex(index, size);
final Object[] es = elementData;
@SuppressWarnings("unchecked") E oldValue = (E) es[index];
fastRemove(es, index);
return oldValue;
}
보는것과 같이 인터페이스로 구현되어 ArrayList는 부모 요소의 내용을 뽑아서 구체화 시킨것을 볼 수 있다.
래퍼타입
prmitive(원시) 타입 기본적으로 변경이 불가능한 타입이다. int, double, byte short등이 있다. int a = 10; a=20;이라고 했을때 값이 바뀌는것이 아니냐.라고 생각할 수 있지만, 내부적으로는 10을 20으로 바꾸는 과정이아닌, 10대신 20을 가리키는 것으로 재할당 되는것이다.
래퍼타입은 원시타입이 제공하지 않는 메소드와 기능을 객체에서 사용가능하다. parseint나, compare등과같은 유용한 메서드를 제공하여 작업을 편리하게 한다.
원시값을 객체화 하는것은 박싱이라고하며, 객체를 다시 원시값으로 만들어주는것을 언박싱이라고 하는데 자동형변환처럼 자동으로 원시타입을 객체로 객체타입을 원시타입으로 변환해주기도 한다
Integer num = newInteger(17); // Boxingint n = num.intValue(); // UnBoxing
Character ch = 'X'; // AutoBoxing
char c = ch; // AutoUnBoxing
오늘의 회고
원시타입을 공부하면서 제대로 이해하지못한 부분이 많다 그리고 제네릭 강의에서 제네릭 클래스는 원시타입이라는데 이 부분도 되게 이해가 안된다
해야할 일
우선순위 1. 자바 강의 5주차 듣기 2. 개인과제 레벨 1 3. sql with, union 공부하기 4. 객체지향 SOLID 5. 원시타입과 래퍼타입의 차이점과 원시타입을 쓰는 이유