Java

05.08 제네릭 와일드카드, Object, 예외처리

amungstudy 2023. 5. 8. 15:41

타입 파라미터에 지정되는 구체적인 타입 제한할 필요

상속 및 구현 관계 이용해 타입 제한

상위 타입은 클래스 뿐만 아니라 인터페이스도 가능

타입 파라미터를 대체할 구체적인 타입

상위타입이거나 하위 또는 구현 클래스만 지정 가능

 

숫자타입만 제네릭으로 받아야 할때 extends Number할 수 있다.(타입 제한)


 

 

 

와일드 카드 사용 generic 타입 제한

 

extends : 본인, 하위객체만 가능.

super : 하위제한. 본인,부모,object 가능

 


package generic05_wild_card;

 

// 교육 과정 별 학생을 관리하는 class

public class Course<S> {

 

private String title; // 교육 과정 명

private S[] students; // 학생 목록

 

// 교육과정명과 등록 가능한 학생 인원수

@SuppressWarnings("unchecked")

public Course(String title, int capacity) {

this.title = title;

this.students = (S[])new Object[capacity];

}

 

public String getTitle() {

return title;

}

 

public S[] getStudnets() {

return students;

}

 

//학생 정보 추가

public void add(S s) {

for(int i = 0; i< students.length;i++) {

if(students[i] == null) {

students[i] = s;

break;

}

}

}

 

 

}


 

package generic05_wild_card;

 

public class CourseExample {

 

//<?> : 매개변수가 전달될때 데이터타입 결정된다고 알려주는 것

public static void registerCourse(Course<?> course) {

System.out.println("["+course.getTitle()+"]");

}

 

// 학생 과정 등록

public static void registerStudent(Course<? extends Student> course) {

System.out.println("["+course.getTitle()+"]");

}

//직장인, 일반인 과정 등록

public static void registerWorker(Course<? super Worker> course) {

System.out.println("["+course.getTitle()+"]");

}

 

 

public static void main(String[] args) {

Person person1 = new Person("일반인1");

Person person2 = new Person("일반인2");

Student student = new Student("학생");

HighStudent highStudent = new HighStudent("고등학생");

Worker worker = new Worker("직장인");

 

 

Course<Person> normalCourse = new Course<>("일반인과정",5);

normalCourse.add(person1);

normalCourse.add(person2);

normalCourse.add(student);

normalCourse.add(highStudent);

normalCourse.add(worker);

 

// 학생만 등록 가능

Course<Student> studentCourse = new Course<>("학생 과정",5);

// studentCourse.add(person1);

//studentCourse.add(worker);

studentCourse.add(student);

studentCourse.add(highStudent);

 

Course<HighStudent> highCourse = new Course<>("입시과정", 5);

highCourse.add(highStudent);

 

Course<Worker> workerCourse = new Course<>("재직자 과정",5);

workerCourse.add(worker);

 

System.out.println("============================");

registerCourse(normalCourse);

registerCourse(studentCourse);

registerCourse(highCourse);

registerCourse(workerCourse);

 

System.out.println("============================");

//registerStudent(normalCourse);

registerStudent(studentCourse);

registerStudent(highCourse);

 

System.out.println("============================");

registerWorker(normalCourse);

registerWorker(workerCourse);

 

}

 

}


 

package generic05_wild_card;

 

//고등학생

public class HighStudent extends Student{

 

public HighStudent(String name) {

super(name);

}

 

}


 

package generic05_wild_card;

 

//강의를 수강하는 학생의 정보를 저장

public class Person {

 

private String name;

 

//이름을 전달받는 생성자만 존재

public Person(String name) {

this.name = name;

}

 

public String getName() {

return this.name;

}

 

public String toString() {

return "Person [name = "+name+"]";

}

 

}


 

package generic05_wild_card;

public class Student extends Person{

 

public Student(String name) {

super(name);

}

 

}


package generic05_wild_card;

 

// 직장인

public class Worker extends Person{

 

public Worker(String name) {

super(name);

}

 

}

 



2. object

 

객체 문자정보(toString())

객체를 문자열로 표현한 값

Object 클래스의toString() 메소드는 객체의 문자 정보 리턴

일반적으로 의미 있는 문자정보가 나오도록 재정의

Date 클래스- 현재 시스템의 날짜와 시간 정보 리턴

String 클래스 - 저장하고 있는 문자열 리턴

System.out.pritnln(Object) 메소드

ObjecttoString()리턴값 출력

package a_object.toString;

 

class Person extends Object

{

String name;

int height;

double weight;

 

public Person(String name, int height, double weight) {

this.name = name;

this.height = height;

this.weight = weight;

}

 

@Override

public String toString() {

return "Person [name = "+name+", height = "+height+", weight = "+weight+"]";

}

 

}

 

public class ToStringExample {

 

public static void main(String[] args) {

Person person = new Person("최기근",180,75);

System.out.println(person);

 

}

 

}


객체 비교(equals() 메소드)

기본적으로 == 연산자와 동일한 결과 리턴 (번지 비교)

논리적 동등 위해 오버라이딩 필요

논리적 동등이란?

같은 객체이건 다른 객체이건 상관없이 객체 저장 데이터 동일

Object equals() 메소드

재정의하여 논리적 동등 비교할 때 이용

 

 

 

package a_object.equals;

 

public class Member {

 

String id;

 

public Member(String id) {

this.id = id;

}

 

 

// alt +s +s +s

@Override

public String toString() {

return "Member [id=" + id + "]";

}

 

 

@Override

public boolean equals(Object obj) {

if(this == obj) { return true;}

if(obj instanceof Member) {

Member member = (Member)obj;

if(this.id.equals(member.id)) {

return true;

}

}

return false;

}

 

 

 

 

 

}

 


package a_object.equals;

 

public class EqualsExample {

 

public static void main(String[] args) {

Member member1 = new Member("id001");

Member member2 = new Member("id001");

System.out.println(member1==member2);

System.out.println(member1.equals(member2));

}

 

}

 


객체 복제(clone())

원본 객체의 필드 값과 동일한 값을 가지는 새로운 객체 생성하는 것

복제 종류

얕은 복제(thin clone): 필드 값만 복제 (참조 타입 필드는 번지 공유)

깊은 복제(deep clone): 참조하고 있는 객체도 복제

 

package a_object.clone;

 

public class Car {

 

String model;

//생성자

public Car(String model) {

this.model = model;

}

 

@Override

public String toString() {

return "Car [model=" + model + "]";

}

 

}


package a_object.clone;

 

public class CloneExample {

 

public static void main(String[] args) throws CloneNotSupportedException {

Member member = new Member(

"최기근",

28,

new int[] {100,95,99},

new Car("캐스터")

);

System.out.println(member);

 

Member cloned = (Member)member.clone();

System.out.println(cloned);

 

cloned.scores[0] = 90;

System.out.println(member.scores == cloned.scores);

System.out.println(cloned);

System.out.println(member);

}

}


 

package a_object.clone;

 

import java.util.Arrays;

 

//implements Cloneable : 복제 허용 (마커형 인터페이스)

public class Member implements Cloneable{

 

public String name;

public int age;

public int[] scores;

public Car car;

 

//모든 값을 넘겨받는 생성자 추가

public Member(String name, int age, int[] scores, Car car) {

this.name = name;

this.age = age;

this.scores = scores;

this.car = car;

}

 

@Override

public String toString() {

return "Member [name=" + name + ", age=" + age + ", scores=" + Arrays.toString(scores) + ", car=" + car + "]";

}

 

@Override

protected Object clone() throws CloneNotSupportedException {

Member cloned = (Member)super.clone(); // 얕은 복제

//참조타입은 주소값이 들어가있기 때문에 서로 다른 곳을 참조할때는 직접 구현해야함.(깊은 복제)

// scores, Car

int[] score = new int[this.scores.length];

for(int i = 0; i < this.scores.length;i++) {

score[i] = this.scores[i];

}

cloned.scores = score;

Car car = new Car(this.car.model);

cloned.car = car;

// return super.clone();

return cloned;

}

 

 

}


 

객체 소멸자(finalize())

GC는 객체를 소멸하기 직전 객체 소멸자(finalize()) 실행

Object finalize() 는 기본적으로 실행 내용이 없음

객체가 소멸되기 전에 실행할 코드가 있다면?

Object finalize() 재정의

될 수 있으면 소멸자는 사용하지 말 것

GC는 메모리의 모든 쓰레기 객체를 소멸하지 않음

GC의 구동 시점이 일정하지 않음

 

package a_object.finalize;

 

public class FinalizeTest {

 

public static void main(String[] args) {

 

for(int i = 0; i< 50; i++) {

Counter counter = new Counter(i);

counter = null;

System.gc();

 

}

 

}

 

}


 

package a_object.finalize;

 

public class Counter {

 

private int no;

public Counter(int no) {

this.no = no;

}

 

@Override

protected void finalize() throws Throwable {

System.out.println(no+"번째 객체의 finalize() 호출");

}

 

 

 

 

}

 

 

예외처리

 

예외 처리 코드(try-catch-finally)

 

예외 처리 코드

예외 발생시 프로그램 종료 막고, 정상 실행 유지할 수 있도록 처리

일반 예외: 반드시 작성해야 컴파일 가능

실행 예외: 컴파일러가 체크해주지 않으며 개발자 경험 의해 작성

try – catch – finally 블록 이용해 예외 처리 코드 작성

 

catch 순서 상위 클래스가 밑에 위치해야함

package test1_try_catch;

 

import java.util.InputMismatchException;

import java.util.Scanner;

 

public class TryCatchExample {

 

public static void main(String[] args) {

System.out.println("MAIN START");

 

String str = null;

int[] scores = new int[4];

 

Scanner sc = new Scanner(System.in);

while(true) {

try {

System.out.println("배열에 삽입하려는 인덱스 번호를 입력 > ");

int index = sc.nextInt();

if(index < 0) break;

System.out.println("입력하려는 값을 작성하시오 > ");

scores[index] = sc.nextInt();

// System.out.println(str.equals("null"));

// }catch(Exception e) {

 

}catch(InputMismatchException e) {

System.out.println("정수가 입력되지 않음 : " + e.getMessage()); // 예외 관련 설명

sc.next();

continue;

}catch(ArrayIndexOutOfBoundsException e) {

e.printStackTrace(); //오류발생지점출력

System.out.println("잘못된 인덱스 번호입니다.");

continue;

}catch(Exception e) { // 예외 부모 클래스

System.out.println("Exception");

e.printStackTrace();

break;

}finally { // finally는 필수아님

// 오류가 발생하든 - try 오류 발생

// 오류가 발생하지 않든 - try 정상 실행

// 항상 마지막에 수행되는 블럭(return,break가 있어도 실행)

for(int i : scores) {

System.out.print(i+ " ");

}

System.out.println();

System.out.println("항상실행");

}

}

System.out.println("MAIN END");

}

}