2023-12-18 (8일차) - 생성자, ArrayList, 제네릭, 접근 제한자, 예외 처리

민짱·2024년 1월 7일
post-thumbnail

📅2023. 12. 18 8일차


🎨 Java

생성자(constructor)

  • 객체의 생성과 동시에 인스턴스 변수를 원하는 값으로 초기화할 수 있는 생성자(constructor)라는 메소드를 제공한다.
  • 특징
  1. 생성자는 반환값이 없지만, 반환 타입을 void형으로 선언하지 않습니다.

  2. 생성자는 초기화를 위한 데이터를 인수로 전달받을 수 있습니다.

  3. 객체를 초기화하는 방법이 여러 개 존재할 경우에는 하나의 클래스가 여러 개의 생성자를 가질 수 있습니다.

    즉, 생성자도 하나의 메소드이므로, 메소드 오버로딩이 가능하다는 의미입니다.

  • 생성자 실행 순위

    • 부모 생성자 먼저 그 후 자식 생성자 실행.

ArrayList란?

  • Collection 프레임워크의 일부이며, java.util 패키지에 소속되어 있다.

표준 배열보다는 느리지만 배열에서 많은 조작이 필요한 경우 유용하게 쓰임.

List 인터페이스에서 상속받아 사용된다.

ArrayList는 객체가 추가되어 용량을 초과하면 자동으로 부족한 크기만큼 용량이 늘어난다.


ArrayList 내부 작동원리

  • T는 제네릭으로 Type을 뜻한다.
public class Main {
	public static void main(String[] args) {
		ArrayList<Integer> numbers = new ArrayList<Integer>();
		numbers.add(10);
		numbers.add(20);
		numbers.add(30);
		numbers.add(40, 1);
		numbers.remove(0);
		for (int i = 0; i < numbers.size(); i++) {
			int num = numbers.get(i);
			System.out.printf("%d : %d\n", i, numbers.get(i));
		}
	}
}
class ArrayList<T> {
	Object[] array;
	int size;
	ArrayList() {
		size = 0;
		array = new Object[3];
	}
	boolean isFull() {
		return array.length == size;
	}
	void sizeUp() {
		Object[] newArray = new Object[array.length * 2];
		for (int i = 0; i < array.length; i++) {
			newArray[i] = array[i];
		}
		array = newArray;
	}
	void add(int data) {
		if (isFull()) {
			sizeUp();
		}
		array[size] = data;
		size++;
	}
	int getLastIndex() {
		return size - 1;
	}
	void add(Object data, int index) {
		if (isFull()) {
			sizeUp();
		}
		int lastIndex = getLastIndex();
		for (int i = lastIndex; i >= index; i--) {
			array[i + 1] = array[i];
		}
		array[index] = data;
		size++;
	}
	void remove(int index) {
		for (int i = index + 1; i < size; i++) {
			array[i - 1] = array[i];
		}
		size--;
	}
	T get(int index) {
		return (T) array[index];
	}
	int size() {
		return size;
	}
}

자바 접근 제한자 (public, private, protected, default)

  • 접근 제한자란?
    멤버들은 객체 자신들만의 속성이자 특징이므로 대외적으로 공개되는 것이 결코 좋은 것은 아니다.그런 이유로 프로그래머가 객체의 멤버들에게 접근 제한을 걸 수가 있는데 자바에서는 이를 접근 제한자라 한다.
i) public : 모든 접근을 허용
ii) protected : 같은 패키지(폴더)에 있는 객체와 상속관계의 객체들만 허용
iii) default : 같은 패키지(폴더)에 있는 객체들만 허용
iv) private : 현재 객체 내에서만 허용
  • private일 때 변수 1개당 public 필요, setter 필요, getter 필요

예외(Exception)

  • 컴파일 오류와 런타임 오류 두 종류 중 런타임 오류는 에러(Error)와 예외(Exception)이 있다.
  • 에러는 프로그램이 코드로 복구될 수 없는 오류를 의미하고 예외는 프로그래머가 직접 예측하여 막을 수 있는 처리가능한 오류이다.
  • 메모리가 부족한 경우 프로그래머가 직접 제어할 수 없으므로 이런 경우는 메모리 부족(OutOfMemoryError) 에러가 발생하고 함수 호출이 많아 스택이 쌓일 경우에는 StackOverFlowError가 발생할 수 있다.
  • 예측가능한 상황에서 오류를 제어할 수 있는것이 예외이다.
  • Compile시에 발견하지 못하는 에러를 Runtime에러라고 하는데, 이때는 프로그래머가 예측하여 처리해줘야 한다.
    그리고 그런 예외가 발생했을때 어떤 동작을 처리해야하는지를 예외 처리라고 합니다.
  • 자바에서 모든 예외는 Exception이라는 클래스를 상속받는다.

try{
	//예외가 발생될만한 코드
}catch(FileNotFoundException e){	//FileNotFoundException이 발생했다면

}catch(IOException e){ //IOException이 발생했다면

}catch(Exception e){	//Exception이 발생했다면

}finally{
	///어떤 예외가 발생하던 말던 무조건 실행
}
  • try 블록 : 이 블록에서 예외가 발생할만한 코드가 쓰인다.

  • cath(예외 종류) 블록 : 이 부분에서 예외가 발생되었을 때 처리하는 동작을 명시한다.

    • cath블록은 여러 개가 있을 수 있다.
    • 맨 처음 cath블록에서 잡히지 않는 예외라면 다음 cath의 예외를 검사한다.
    • 이 때 상속관계에 있는 예외 중 부모가 위의 cath, 그리고 자식 예외 클래스가 아래의 cath에 놓일 수 없다.
  • finally 블록 : 여기서는 예외가 발생하건 발생하지 않건 공통으로 수행되어야할 코드가 쓰여진다. 임시 파일의 삭제 등 뒷정리 코드가 쓰인다.


  • throws
    • 예외를 여기서 처리하지 않을테니 불러다가 쓰는 녀석에게 에러 처리를 전가하겠다는 의미(조심해해라~)
    • throw 예외객체
      ex) throw new Exception("예외 발생!")

자바 (Garbage collection)

  • 프로그램을 개발 하다 보면 유효하지 않은 메모리인 가바지(Garbage)가 발생하게 된다. C언어를 이용하면 free()라는 함수를 통해 직접 메모리를 해제해주어야 한다.
  • 하지만 Java나 Kotlin을 이용해 개발을 하다 보면 개발자가 메모리를 직접 해제해주는 일이 없다. 그 이유는 JVM의 가비지 컬렉터가 불필요한 메모리를 알아서 정리해주기 때문이다. 대신 Java에서 명시적으로 불필요한 데이터를 표현하기 위해서 일반적으로 null을 선언해준다. 

Person person = new Person();
person.setName("Mang");
person = null;

// 가비지 발생
person = new Person();
person.setName("MangKyu");
  • 기존의 Mang으로 생성된 person 객체는 더이상 참조를 하지 않고 사용이 되지 않아서 Garbage(가비지)가 되었다.
  • Java나 Kotlin에서는 이러한 메모리 누수를 방지하기 위해 가비지 컬렉터(Garbage Collector, GC)가 주기적으로 검사하여 메모리를 청소해준다.
  • (물론 Java에서도 System.gc()를 이용해 호출할 수 있지만, 해당 메소드를 호출하는 것은 시스템의 성능에 매우 큰 영향을 미치므로 절대 호출해서는 안된다.)

Java Generic

  • 제네릭(Generic)은 직역하자면 '일반적인'이라는 뜻이다. '데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있도록 하는 방법'이다.
  • 제네릭(Generic)은 클래스 내부에서 지정하는 것이 아닌 외부에서 사용자에 의해 지정되는 것을 의미한다.
ArrayList <Array List>articles = new ArrayList<Array List>();

// <Array List> Array List만 들어갈 수 있음

ArrayList <Integer>articles = new ArrayList<Integer>();

// <Integer> 정수만 들어갈 수 있다는 뜻

// < > 요소의 타입을 지정해주는 공간이라고 생각하면 된다
List<Article> articles = new ArrayList<>(); // 생략버전

Generic의 장점

  1. 제네릭을 사용하면 잘못된 타입이 들어올 수 있는 것을 컴파일 단계에서 방지할 수 있다.

  2. 클래스 외부에서 타입을 지정해주기 때문에 따로 타입을 체크하고 변환해줄 필요가 없다. 즉, 관리하기가 편하다.

  3. 비슷한 기능을 지원하는 경우 코드의 재사용성이 높아진다.

Generic 사용 방법

타입설명
TType
EElement
KKey
VValue
NNember

🔔 TODO

  • 했던 내용 전부 복습
  • 코드업 최대한 많이
  • WIKI 정리

💡느낀점

Array List 복습 필이 해야겠다!! Generic 다시 한 번 보자 그리고 현재까지 부족한 거 찾아서 보안!!

0개의 댓글