에러 (Error)
: 시스템 레벨에서 발생하는 심각한 문제
에러의 종류
- VirtualMachineError
: OutOfMermoryError
: StackOverflowError
- ThreadDeath
컴파일 에러와 런타임 에러의 이해
- 컴파일 에러 : 코드의 문법적 오류
1) 문법 오류 : 괄호, 세미콜론 누락 등
2) 타입 불일치 : 변수나 메소드의 반환 타입이 일치하지 않는 경우
3) 미선언 변수 : 선언도지 않은 변수를 참조하는 경우 (오타)
- 런타임 에러 : 프로그램 실행 중에 발생하는 오류
예외(Exception )
: 프로그램 실행 중에 발생할 수 있는 예상치 못한 상황
: 에러와의 차이는 에러가 발생하면 프로그램이 실행조차 되지 않지만, 예외는 실행은 됨
: 에러는 개발자가 직접 처리하기 힘든 경우가 대부분이고 예외는 개발자가 직접 처리할 수 있음
- 체크 예외(Checked Exception)
: 컴파일 시점에서 검사
: 컴파일러가 강제로 예외 처리 요구 (반드시 예외 처리)
- 언체크 예외(Unchecked Exception)
: 런타임 시점에서 발생
: 컴파일러가 예외 처리를 강제하지 않음
예외 처리 방법
try-catch 구문을 통해서 처리 가능
try : { 예외가 발생할 가능성이 있는 구문 }
catch ( 예외클래스 예외인스턴스 ) {특정 예외가 발생할 때 실행할 구문 }
public class A_Exception {
// throw를 통해서 호출부에 예외러치에 대한 강제성 부여
private void throwException() throws Exception {
// throw를 통해서 강제로 예외를 발생
throw new NullPointerException("널포인터 제외");
// Exception in thread "main" java.lang.NullPointerException: 널포인터 제외
}
- 발생할 수 있는 예외
: 사용자가 정수를 입력하지 않았을 때
: 사용자가 0을 입력했을 때
방법 1
try {
int number = scanner.nextInt();
// 정수 X 인 경우 Exception in thread "main" java.util.InputMismatchException at ch03.A_Exception.main(A_Exception.java:18)
System.out.println(18 / number);
// 0인 경우 Exception in thread "main" java.lang.ArithmeticException:/ by zero at ch03.A_Exception.main(A_Exception.java:19)
}catch (ArithmeticException exception) {
System.out.println("수학적 예외가 발생했습니다."); // 0인 경우 예외처리
}catch (InputMismatchException exception) {
System.out.println("옳지 못한 입력을 하였습니다."); // 정수X인 경우 예외처리
}
scanner.close();
System.out.println("Scanner 자원을 반환했습니다.");
}
방법 2
try {
int number = scanner.nextInt(); // 정수 X 인 경우
System.out.println(18 / number); // 0인 경우
// Exception 으로 다양한 예외를 통합하여 사용
catch (Exception exception) {
System.out.println("예외가 발생했습니다.");
}
scanner.close();
System.out.println("Scanner 자원을 반환했습니다.");
}
finally 블록
try {
int number = scanner.nextInt(); // 정수 X 인 경우
System.out.println(18 / number); // 0인 경우
}catch (ArithmeticException exception) {
System.out.println("수학적 예외가 발생했습니다.");
}catch (InputMismatchException exception) {
System.out.println("옳지 못한 입력을 하였습니다.");
}finally {
// finally로 예외가 발생하든 안하든 실행할 코드를 작성
// 자원의 반환처리를 대부분 finally 에서 작업
scanner.close();
System.out.println("Scanner 자원을 반환했습니다.");
}
예외 던지기
- throw : 예외를 명시적으로 던질 수 있음
- throws : 메소드가 발생시킬 수 있는 예외를 선언
A_Exception instance = new A_Exception();
try {
instance.throwException();
} catch (Exception exception) {
exception.printStackTrace();
}
System.out.println("프로그램이 정상적으로 종료되었습니다.");
// 프로그램이 정상적으로 종료되었습니다.
* instance.throwException(); - 강제로 부여 해서 아래 코드 완성시킴
사용자 정의 예외
사용자 정의 예외 클래스 생성 방법
: 부모 클래스의 생성자로 전달되어 예외가 발생했을 때 출력
public class CustomException extends Exception { // 상속
public CustomException(String message) {
super(message);
}
}
자바의 내장 예외 클래스
- NullPointerException
: 객체 참조가 null인 상황에서 해당 참조를 사용시 발생
NullPointerException 사용 시나리오와 처리 방법 (자주 사용함)
Object obj = null;
if (obj != null) {
obj.toString();
}
- ArrayIndexOutOfBoundsException
: 배열의 범위를 벗어나는 인덱스를 사용시 발생
- NumberFormatException
: 숫자 형식이 아닌 문자열을 숫자로 변환시 발생
- IllegalArgumentException
: 메소드에 부적절한 인수가 전달되었을 때 발생
예외 처리의 위치
- 예외가 발생하는 곳보다는, 이를 처리할 수 있는 곳에서 하는 것이 좋음
- 위치는 예외 발생에 대한 적절한 복구 전략이나 사용자 피드백을 제공할 수 있는 곳
- 예외를 호출하는 상위 메소드에서 처리하는 것이 일반적
예외처리의 성능 문제
- 예외 처리를 잘 못 사용하는 경우
: 예외를 제어 흐름으로 사용하는 경우
: 예외 생성 비용
- 예외 처리의 성능 문제 해결 방법
: 제어 흐름에서의 예외 사용을 피하고, 예외적인 상황에만 예외를 사용
: 예외 처리를 최소화
: 일반적인 작업을 위해 비용이 큰 예외 생성을 피함
자바 패키지
Wrapper 클래스
: 기본형 데이터 타입을 참조형 데이터 타입으로 다룰 수 있도록 하는 클래스
: 일반적으로 기본형 데이터타입의 풀네임에 첫글자를 대문자로 지정하면 Wrapper 클래스가 됨
: 기본 유형, 참조 유형
Wrapper 클래스의 종류
- byte: Byte
- short: Short
- int: Integer
- long: Long
- float: Float
- double: Double
- boolean: Boolean
- char: Character
Integer wrapperInt = 10;
Double wrapperDouble = 10.0;
Boolean wrapperBoolean = false;
String wrapperString = "String";
Wrapper 클래스의 유용한 메서드들
parse 메서드 : 문자열을 특정 타입으로 변환
int number = Integer.parseInt("123"); // 문자열 "123"을 int 타입 123으로 변환
toString 메서드 : 특정 타입의 값을 문자열로 변환
String string = Integer.toString(123); // int타입 123을 문자열 "123"으로 변환
java.util 패키지
Collection Framework
: Java에서 데이터구조에 대한 표준화된 기법을 제공
List 인터페이스
: 데이터를 저장할 때 중복 허용하고 순서가 존재(→ index가 있다)
: List<참조형 타입> arraylist 기본형
List<Integer> arrayList; // Int[] arrayList; 와 같은 느낌
* Integer를 넣으면 정수타입의 데이터를 만들 수 있음
* <>를 제너릭이라고 하는데 이 제너릭에는 참조형 타입만 올 수 있음
주요 구현체
★ ArrayList : List 중에서 내부 배열을 사용하여 인덱스를 사용한 검색이 빠름, 가장 많이 사용함
arrayList = new ArrayList<>();
System.out.println(arrayList); // []
LinkedList : 이중 연결 기법을 사용하여 추가, 삭제가 빠름
arrayList = new LinkedList<>();
ArrayList와 LinkedList의 차이점
주요 메서드
add() : List에 요소를 추가
주의사항 : 추가할 요소의 데이터 타입은 반드시 제너릭으로 지정한 타입으로만 지정 가능
arrayList.add(10);
System.out.println(arrayList); // [10]
List<Integer> arrayList; // 정수타입
arrayList.add("aaaa"); // 문자열 타입이여서 컴파일러 에러가 남
* List<> arrayList || List<Object> arrayList 으로 변경 시 에러X
get()
: List의 특정 인덱스 요소에 접근
: List 인덱스 범위를 초과하는 인덱스를 지정할 수 없음
: 기본형 데이터타입의 변수로 반환값을 받을 경우 null 값을 받을 수 있음을 주의
int arrayElement = arrayList.get(0);
System.out.println(arrayElement); // 10
set()
: List의 특정 인덱스 요소를 변경
: List 인덱스 범위를 초과하는 인덱스를 지정할 수 없음
arrayList.set(1, -99);
System.out.println(arrayList);
remove()
: List의 특정 요소를 삭제
arrayList.remove(2); // 2라는 숫자는 인덱스 번호
System.out.println(arrayList);
size() : List의 길이를 반환
System.out.println(arrayList.size()); // 2
Set
: 데이터를 저장할 때 중복을 허용하지 않고 순서가 존재하지 않음(집합)
Set<String> set;
주요 구현체
HashSet : 해싱 기법을 사용해서 검색 속도가 빠름
set = new HashSet<>();
TreeSet : 요소를 정렬해서 추가
set = new TreeSet<>();
주요 메서드
add() : Set에 요소를 추가, 단, 동일한 요소가 이미 추가되어있다면 추가하지 않음
set = new HashSet<>(); 경우
set.add("Apple");
System.out.println(set); // [Apple]
set.add("Banana");
System.out.println(set); // [Apple, Banana]
set.add("Banana1");
System.out.println(set); // [Banana1, Apple, Banana] // 순서가 막 나옴
// set.add("Banana"); // 중복된 값이어서 추가가 되지 않음
set = new TreeSet<>(); 경우
set.add("Apple");
System.out.println(set); // [Apple, Banana, Banana1]
set.add("Banana");
System.out.println(set); // [Apple, Banana, Banana1]
set.add("Banana1");
System.out.println(set); // [Apple, Banana, Banana1]
remove()
: Set에서 특정 요소를 제거
: 제거하고자 하는 요소가 없더라도 예외가 발생하지 않음
set.remove("Apple"); // 요소 값 Apple 제거, (인덱스로 제거X)
set.remove("Apple1"); // Apple, Banana, Banana1 , 없는 요소는 단순히 처리하지 않음
System.out.println(set); // [Banana, Banana1]
contains()
: Set에서 특정 요소가 존재하는지 확인
System.out.println(set.contains("Apple")); // false
System.out.println(set.contains("Banana")); // true
Map : 키와 값이 한쌍으로 이루어진 요소들의 집합, 키는 중복 불가능, 값은 중복 가능, 순서 없음
Map<String, String> map;
HashMap : 해싱기법으로 키의 검색 속도가 빠름
map = new HashMap<>();
TreeMap : 키를 정렬하여 저장
map = new TreeMap<>();
put()
: Map에 키와 값을 추가
: 만약 동일한 키가 존재한다면 해당 키의 값을 변경
map = new HashMap<>() 경우
map.put("Apple", "사과"); // {Apple=사과}
System.out.println(map);
map.put("Banana", "바나나"); // {Apple=사과, Banana=바나나}
System.out.println(map);
map.put("Apple", "링고"); // {Apple=링고, Banana=바나나}
System.out.println(map);
map.put("Banana1", "바나나"); // {Banana1=바나나, Apple=링고, Banana=바나나} // 정렬없이 출력
System.out.println(map);
map = new TreeMap<>() 경우
: 순서가 없음
map.put("Apple", "사과"); // {Apple=사과, Banana=바나나, Banana1=바나나}
System.out.println(map);
map.put("Banana", "바나나"); // {Apple=사과, Banana=바나나, Banana1=바나나}
System.out.println(map);
map.put("Apple", "링고"); // {Apple=사과, Banana=바나나, Banana1=바나나}
System.out.println(map);
map.put("Banana1", "바나나"); // {Apple=사과, Banana=바나나, Banana1=바나나}
System.out.println(map);
get()
: Map에서 특정 키를 가지는 요소를 반환
: 존재하지 않는 키로 검색할 경우 null로 반환
System.out.println(map.get("Apple1")); // null
remove()
: Map에서 특정 키를 가지는 요소를 제거
: remove 작업에 성공하면 해당 키의 값을 반환
map.remove("Apple"); // {Banana=바나나, Banana1=바나나}
map.remove("Apple1"); // {Banana=바나나, Banana1=바나나}
// 없는 값을 입력하면 처리하지 않음, 단, 값은 출력함
class Human {
String name;
String address;
int age;
}
Human human1 = new Human();
human1.name = "홍길동";
human1.address = "부산광역시 진구";
human1.age = 10;
Map<String, Object> human2 = new HashMap<>();
// Object는 제약이 없음
human2.put("name", "홍길동");
human2.put("address", "부산광역시 진구");
human2.put("age", "열살");
// 1 문제점 : 사용 혹은 추가할때 오타(실수)에 대한 가능성
human2.get("name");
// 2. 문제점 : 타입의 안정성의 문제
Integer age = (Integer) human2.get("age");
제너릭 : 클래스나 메서드에서 사용할 데이터 타입을 외부에서 받아오는 기법
class Test1 {
String subject;
int score;
}
class Test2 {
String subject;
String score;
}
* Test1, Test2 형태로 클래스를 사용하게되면 코드의 중복이 발생함
class Test3 {
String subject;
Object score;
}
* Test3 형태로 클래스를 사용하게되면 타입의 안정성 떨어짐
Test3 myTest = new Test3();
myTest.subject = "국어";
myTest.score = 95;
Test3 yourTest = new Test3();
yourTest.subject = "경영학원론";
yourTest.score = "A+";
제너릭 클래스
: 클래스 내부에 있는 데이터 타입을 외부에서 받아오려 할 때 사용
: class 클래스명<매개타입> { 매개타입 변수명 }
class Test4<T> { // 클래스 전체에 대해서 제한
String subject;
T score;
}
Test4<Integer> hisTest = new Test4<>();
hisTest.score = 95;
// hisTest.score = "A+"; // 정수여서 컴파일러 에러가 남
Test4<String> herTest = new Test4<>();
herTest.score = "A+";
// herTest.score++; // 문자열 형태여서 컴파일러 에러가 남
List<String> arrayList1 = new ArrayList<>();
arrayList1.add("A");
arrayList1.add("B");
arrayList1.add("C");
List<Boolean> arrayList2 = new ArrayList<>();
arrayList2.add(true);
arrayList2.add(false);
arrayList2.add(true);
제너릭 메서드
: 해당 메서드의 매개변수의 타입이나 반환 타입에서 사용할 타입을 외부에서 받아오려 할 때 사용
: <매개타입> 반환타입 메서드명 (<매개타입>매개변수) {...}
class Test5 {
static <T> void method(List<T> arg) {
System.out.println(arg);
}
Test5.method(arrayList1);
Test5.method(arrayList2);
? : 와일드 카드로 제너릭에 대해서 모든 타입을 받을 수 있도록 함
static void wildCardMethod (List<?> arg) {
System.out.println(arg);
}
Test5.wildCardMethod(arrayList1);
Test5.wildCardMethod(arrayList2);
? extends 클래스명 : 특정 클래스 혹은 특정 클래스를 확장한 클래스를 확장한 클래스만 제너릭으로 받을 수 있도록 제한함
: (본인클래스 또는 자손클래스)
static void extendMethod (List<? extends MyClass> arg) {
System.out.println(arg);
}
SuperClass superClass = new SuperClass();
MyClass myClass = new MyClass();
SubClass subClass = new SubClass();
List<SuperClass> superList = new ArrayList<>();
superList.add(superClass);
List<MyClass> myList = new ArrayList<>();
superList.add(myClass);
List<SubClass> subList = new ArrayList<>();
superList.add(subClass);
? super 클래스명 : 특정 클래스 혹은 특정 클래스가 확장한 클래스만 제너릭으로 받을 수 있도록 제한함
: (본인클래스 또는 조상클래스)
static void superMethod (List<? super MyClass> arg) {
System.out.println(arg);
}
}
Test5.wildCardMethod(superList);
Test5.wildCardMethod(myList);
Test5.wildCardMethod(subList);
// Test5.extendMethod(superList); // superList는 들어오지 않음 - myClass이거나 확장한 메소드만 받을 수 있다.
Test5.extendMethod(myList);
Test5.extendMethod(subList);
Test5.superMethod(superList);
Test5.superMethod(myList);
// Test5.superMethod(subList); // subList는 들어오지 않음 - 부모 클래스에서 받지 못해서 이다.
'AWS(산대특)' 카테고리의 다른 글
DAY 11 - GitHub (0) | 2024.02.01 |
---|---|
DAY 9 - JAVA (0) | 2024.01.30 |
DAY 7 - JAVA (0) | 2024.01.28 |
DAY 6 -JAVA (0) | 2024.01.25 |
객체지향 프로그래밍 보충 (0) | 2024.01.25 |