본문 바로가기
AWS(산대특)

DAY 8 - JAVA

by dkdlxl 2024. 1. 29.

에러 (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