객체지향프로그래밍 태그 기말고사 PDF
Document Details
Uploaded by Deleted User
임현우
Tags
Summary
이 문서는 객체 지향 프로그래밍에 대한 태그 기말고사 자료입니다. 배열과 ArrayList, 클래스, 메서드, primitive type, wrapper class , Java의 기본 개념에 대한 설명과 예제가 포함되어 있습니다.
Full Transcript
객체지향프로그래밍 태그 기말고사 ✏️Chap.7 : Arrays and Array List 💡 업케스팅 다운케스팅 다형성 , , Array : 정적 자료형 충분한 배열 크기를 잡고 사용 ( 숫자 , 문자열 배열) double [] values = new double [Length]; // 배열 선언...
객체지향프로그래밍 태그 기말고사 ✏️Chap.7 : Arrays and Array List 💡 업케스팅 다운케스팅 다형성 , , Array : 정적 자료형 충분한 배열 크기를 잡고 사용 ( 숫자 , 문자열 배열) double [] values = new double [Length]; // 배열 선언 String [] words = new String; String [] words = {"Hi","bye"}; Array References int [] scores = {10,9,7,4,5}; // 배열 선언 int [] values = scores ; // socres 참조 주소 할당 // 값 할당 아님 Using Arrays with Methods public wovid addScores(int[] values) // 매개변수로 객체지향프로그래밍 1 int [] scores = {10 , 9 , 7 , 6}; fred.addsocres(socres); // 값으로 집어 넣ㅇ르 수 있음 반복문과 array ( 배열로 입력 받기) int currenSize = 0 Scanner in = new Scanner(System.in) while(in.hasnextDouble()){ if(courrentSize < values.lenth){ values[currentSize] = in.nextDouble(); currentSize++; // 반복문 돌 } } Arrays.copyOf : Array 내용 복사 하고 싶을 때 객체지향프로그래밍 2 Array Lists : 가변적 Array를 다루기 위해 요소를 삭제 및 삽입하는데 좋다. - import java.util.ArrayList 객체지향프로그래밍 3 add methods 로 리스트에 값 추가 가능 , 맨 뒤에 names.set (2, “Carolyn”); 인덱스 2에 Carolyn 변경 names.remove(1) // remove(int index) 형식 names.remove(Integer.valueOf(1)) ⇒ 1인 값의 첫번 째만 제거. // remove(Object o) 형식 객체지향프로그래밍 4 ArrayList 값복사와 참조 ArrayList newNames = new ArrayList (names) // 값 복사 ArrayList 는 클래스 형태로 객체로 다뤄줘야한다.!!! ArrayList squares = new ArrayList();S ArrayList newNames = names // names 주소 할당 자바 데이터 타입 유형 2가지 Primitive Type ( 원시타입) vs Wrapper Class ( 참조타입) 객체지향프로그래밍 5 원시 타입 : 실제 값을 저장하는 타입 참조타입 : 객체의 참조(주소저장)를 하는 타입, 번지 값을 통해 객체를 참조하는 타입 ArrayList 에서 입력 받으면서 저장하는 방법 // 가장 간편!! ArrayList inputs = new ArrayList(); while (in.hasnextDouble()){ input.(in.nextDouble()); } Array vs ArrayList 대부분의 작업에 있어서 ArrayList가 Array보다 쉽다. 배열의 길이가 변하지 않는다면 Array를 쓰는 걸 추천한다! 일주일 목록 같은 것! 변하지 않는 데이터이니까 긴시퀀스의 원시타입 데이터를 다루는 경우 Array를 추천한다 이외에는 ArrayList 쓰자 객체지향프로그래밍 6 8 장 클래스 설계 (Design Classes) 클래스 설계 방법 클래스는 하나의 컨셉을 가지고 있어야함 응집력이 있어야한다. 공통의 목표를 가지고 있어야함 print 메소드를 해당 클래스에 직접 구현 x, 값을 참조할 수 있게 get 메소드만 구현! main에서 묶어줄 것임 클래스의 목적에 따라 이름을 자세하게 Paycheck (x) , PaycheckProgram (ㅇ) 이름은 행동하는 것 처럼 ( Actors ) 클래스를 찾기위한 방법 - > 문제에 대한 명사를 찾는다 명사 좋은 메소드 설계 객체지향프로그래밍 7 클래스는 하나의 컨셉을 표현해야한다 클래스의 멤버들은 컨셉과 관련 있어야함 공동된 목표를 가지고 있어야함 의존성 최소화 객체지향적으로 생각했을 때 System.out은 모든 언어에 존재 하지 않는다 그래서 클래스를 만들 때 print는 따로 만들던가 main에서 처리 해주자 Accessor vs Mutator 는 객체의 상태를 읽고, Mutator는 상태를 변경합니다. Accessor 둘을 명확히 분리하면 코드가 더 이해하기 쉬워지고 유지보수성이 높아집니다. Immutable 클래스 상태가 변경되지 않는 클래스. Java의 클래스는 불변성을 유지하여 안전한 멀티스레드 환경을 제공합니다. String String Intern Pool 동일한 문자열 리터럴을 재사용하는 메모리 관리 기법. 효율적이지만, 을 사용할 경우 별도의 객체가 생성됨. new String() UML : Unified Modeling Language 객체지향프로그래밍 8 불변 클래스 vs 가변 클래스 immutable (불변) 클래스는 돌연변이(mutator) 메소드 없음 String이 불변 클래스임 → 돌연변이 즉, 값을 바뀌게 하는 메소드 없는 클래스, 수 정만 가능 참조를 하여 객체에 값을 담아 다루니까 안전하게 사용가능 한 클래스임 dependence 의존도 이슈 해결 Rectangle 클래스는 돌연변이 클래스 translate의 메소드가 존재하므로 가변 클래스다 mutable (가변) 클래스는 돌연변이와 접근 메소드로 나뉨 보통 돌연변이 메소드는 반환형이 void임 가끔 정보를 반환하는 가변 있음 ArrayList의 remove는 제거를 성공하면 return ture를 반환함 Mutator( 객체 값 변경) vs Accessor ( 변경 x) String클래스의 substring() → 접근자 메소드임 값변경 x 활용만함 Rectangle의 translate() → mutator Minimizing Side Effects 메소드가 외부세계에 영향을 미치는것/ 매개변수 변경하는 것 즉 Side effect : ArrayList를 매개변수로 받고 구현에서 remove나 다른 메소드로 변경하는 것 → 외부 변수에 영향을 주는것 내부의 값이 콘솔에 print 될 때 → 외부 콘솔에 영향을 줌 객체지향프로그래밍 9 외부 값이 내부 값에 영향을 줄대, 내부 값이 외부 값에 영향을 줄 때 발생함 클래스가 목적에 맞지 않는 출력이나 행동을 할 때 부작용 side effect가 일어남 매개변수의 값을 변경하는 것은 좋지 않음 그대로 유지하는 게 중요함 모든 클래스들의 (메인제외) 입출력으로 부터 멀리하게 하길바람. 클래스를 디자인 하는데 있어서 사이드 이팩트를 최소화 하는게 중요함 은 잔액에서 100만큼 빼서 객체 내부상태를 변경한다. a.deposit(100) 객체의 상태를 변경하므로 Side Effect에 해당합니다. Static Variables 공유해서 쓰고 싶으면 선언! method에 선언 x , ZWzzZW 이렇게하면 public static final double Overdraft_fee = 29.95; BankAccount.OVERDRAFT_FEE. 이렇게 참조 가능! (final 까지 해줬으니까) Math.PI 같은 static 상수 Static Method Math.sqrt(x) 이런식으로 sqr이 static method임 , 객체 선언 없이 클래스 이름에서 바로 불러 버림 내부에서 조적아니 변환이 없는 메소드 예를들어 매개변수만 단순히 제곱ㅎ나는 메소는 static으로 선언하여 메모리의 효율을 높이면 좋다 ex) Financial.percentOf(x,y) 이런식으로 Financial에서 바로 부름 메인 메서드의 역할 객체지향프로그래밍 10 Java 프로그램이 실행될 때, **JVM(Java Virtual Machine)**은 실행 시작점을 찾습 니다. main메서드는 Java 프로그램의 **시작점(entry point)**으로 사용됩니다. JVM은 프로그램 실행 시 클래스의 객체를 생성하지 않고 메서드를 호출하여 프로 main 그램을 시작합니 main 이 이어야 하는 이유 static 객체 없이 호출 가능해야 함: 프로그램이 시작될 때 JVM은 클래스의 객체를 생성하지 않습니다. 메서드는 객체 없이 호출할 수 있으므로, 메서드를 실행할 수 있습니다. static main Packages ( 중요) 비슷한 클래스의 집합 packages : Sef of related classes , Rectangle 클래스 여러개가 있을 건데, 누가 만든건지 (어떤 패키지 이름)인지 중요 패키지 문이 없으면 기본 패키지에 속함 객체지향프로그래밍 11 패키지 이름 규칙 패키지 이름은 유니크 해야함 패키지 이름은 도메인 이름을 역순으로 사용하는 것이 좋음. 예: com.horstmann.bigjava 해당 파일에 있는 클래스들은 지정된 패키지에 속하게 됨. import 없이 클래스 사용 없이도 클래스 사용은 가능하나, 클래스의 전체 이름(fully qualified name)을 import 사용해야 함. 예: java java.util.Random random = new java.util.Random(); java.awt.Rectangle rect = new java.awt.Rectangle(); 단, 이는 코드 가독성이 떨어지고 비효율적일 수 있음.. java.lang 패키지 (자동으로 유일 패키지!) 은 자동으로 포함되므로 java.lang 가 필요 없음. import 예: , 클래스 등은 바로 사용 가능. String Math Tip: import를 사용하여 코드 가독성을 높이는 것이 일반적입니다 9 장 상속 (Inheritance) 상속 상속은 복제보다는 재사용의 개념 sub클래스는 sup 클래스로부터 모든 public 메소드를 상속받는다 상속받은 메소드를 Override 할 수 있다 객체지향프로그래밍 12 자식 클래스 구현 : extends 로 상속 받고 extends sub 클래스에서 새로운 메소드 만들기 or sup에서 override해서 새로운 메소드 만들 기 sub에서 sup 클래스의 private 인스턴스 변수는 직접적 접근 불가 supd의 method를 통해 접근 가능 sub가 sup의 private 변수 값을 가지고 있기는 함! 객체지향프로그래밍 13 부모 클래스의 메소드는 자식이 접근 가능하다는 점 !! 알고 있기 상속에서 흔한 에러 Common Error 클래스의 private 변수를 직접 바꾸려 하는것 → set 메소드로 바꾸셈 super 부모클래스에 있는 변수를 또 선언하지말것 클래스에서 display 메서드를 오버라이드하려고 할 ChoiceQuestion 때, 상위 클래스인 Question 의 text 변수가 private 접근 제한자로 인해 직접 접근할 수 없음. 해결 방법: 키워드를 사용하여 상위 클래스의 super 메서드를 호출. display 이렇게 하면 상위 클래스의 로직을 재사용하면서 하위 클래스의 메소드만의 기능을 추 가 가능. 코드 설명: java 코드 복사 public void display() { // 상위 클래스의 display 메서드 호출 super.display(); // 추가적으로 하위 클래스의 선택지 출력 로직 추가 // Display the answer choices 객체지향프로그래밍 14 } 주요 포인트: 1. 키워드: super 상위 클래스의 메서드를 명시적으로 호출. 오버라이딩된 메서드에서도 상위 클래스의 구현을 활용 가능. 2. 오버라이딩의 장점: 상속 구조에서 기존 메서드를 확장하면서 새로운 동작 추가 가능. 결과: 의 ChoiceQuestion 메서드는 상위 클래스의 출력 로직을 그대로 사용하고, 선택 display 지 출력 같은 하위 클래스만의 기능을 추가할 수 있 오버로딩과 오버라이딩의 차이 및 주의점 1. Overloading (오버로딩): 정의: 동일한 이름의 메서드를 다른 매개변수 타입으로 정의. 특징: 매개변수의 수나 타입이 달라야 함. 같은 클래스 내에서 주로 사용. 예시: java 코드 복사 public int add(int a, int b) { return a + b; } public double add(double a, double b) { return a + b; } 2. Overriding ( 오버라이딩): 정의: 하위 클래스가 상위 클래스의 메서드를 재정의. 객체지향프로그래밍 15 특징: 메서드 이름, 매개변수 타입, 반환 타입 모두 동일해야 함. 상위 클래스의 메서드를 하위 클래스에서 덮어씀. 예시: java 코드 복사 @Override public String toString() { return "Custom toString implementation"; } 3. Common Error: Accidental Overloading ( 실수로 오버로딩): 오버라이딩하려 했으나 매개변수 타입이나 수를 변경해 오버로딩이 발생하는 경우. 문제점: 상위 클래스의 메서드를 재정의하지 않기 때문에, 의도한 대로 동작하지 않음. 해결 방법: 매개변수 타입과 반환 타입이 상위 클래스 메서드와 완전히 일치하도록 확인. 핵심 포인트: 오버로딩: 같은 이름, 다른 매개변수. 오버라이딩: 같은 이름, 같은 매개변수(상속 관계).의도한 동작을 위해 매개변수와 반환 타입 일치에 주의해야 함. 객체지향프로그래밍 16. 중요 포인트 생략 시: super 컴파일러가 자동으로 상위 클래스의 기본 생성자(매개변수 없는 생성자)를 호출. 만약 상위 클래스에 기본 생성자가 없으면 컴파일 오류 발생. 추가 작업: 상위 클래스 생성자를 호출한 후, 하위 클래스만의 필드나 초기화 로직 추가 가능.. 요약 를 사용하여 상위 클래스의 생성자를 명시적으로 호출. super 상위 클래스에 기본 생성자가 없는 경우 반드시 를 사용하여 적절한 생 super(arguments) 성자를 호출해야 함. 상위 클래스 초기화 후 하위 클래스의 추가 작업을 수행 가능 1. 부모 클래스에 매개변수 없는 기본 생성자가 있는 경우 부모 클래스의 기본 생성자가 자동으로 호출됩니다. 명시적으로 를 호출하지 않아도 됩니다. super() 예제 객체지향프로그래밍 17 java 코드 복사 class SuperClass { public SuperClass() { // 기본 생성자 System.out.println("SuperClass Constructor"); } } class SubClass extends SuperClass { public SubClass() { // 부모 클래스 생성자가 자동 호출됨 System.out.println("SubClass Constructor"); } } public class Main { public static void main(String[] args) { SubClass obj = new SubClass(); } } 2. 부모 클래스에 기본 생성자가 없고, 매개변수 생성자만 있는 경우 자식 클래스는 반드시 ** *를 통해 부모 클래스의 생성자를 명시적으로 super(arguments) 호출해야 합니다. 그렇지 않으면 컴파일 에러가 발생합니다. 예제 java 코드 복사 class SuperClass { public SuperClass(String message) { // 매개변수 생성자만 있 음 System.out.println("SuperClass Constructor: " + mes sage); } 객체지향프로그래밍 18 } class SubClass extends SuperClass { public SubClass(String message) { super(message); // 부모 생성자를 명시적으로 호출 System.out.println("SubClass Constructor"); } } public class Main { public static void main(String[] args) { SubClass obj = new SubClass("Hello"); } } 3. 부모 클래스와 자식 클래스 모두 생성자를 가지는 경우 부모 클래스의 생성자를 명시적으로 호출할 수 있습니다. 호출하지 않으면 기본 생성자를 자동으로 호출하려고 시도하므로, 컴파일 에러가 발생 할 수 있습니다. 예제 java 코드 복사 class SuperClass { public SuperClass(String message) { System.out.println("SuperClass Constructor: " + mes sage); } } class SubClass extends SuperClass { public SubClass(String message) { super(message); // 부모 생성자 호출 System.out.println("SubClass Constructor"); } 객체지향프로그래밍 19 } public class Main { public static void main(String[] args) { SubClass obj = new SubClass("Hello"); } } 4. 부모 클래스의 생성자를 호출하지 않을 경우 부모 클래스의 생성자가 명시적으로 호출되지 않으면 기본 생성자( super() ) 를 호출하려 고 시도합니다. 부모 클래스에 기본 생성자가 없으면 컴파일 에러가 발생합니다. 컴파일 에러 예제 java 코드 복사 class SuperClass { public SuperClass(String message) { System.out.println("SuperClass Constructor: " + mes sage); } } class SubClass extends SuperClass { public SubClass() { // 기본 생성자를 호출하려고 시도 에러 발 ( 생 ) System.out.println("SubClass Constructor"); } } public class Main { public static void main(String[] args) { SubClass obj = new SubClass(); // 컴파일 에러 발생 } 객체지향프로그래밍 20 } 컴파일 에러: 해결 방법: 부모 클래스의 매개변수 생성자를 명시적으로 호출해야 합니다: java 코드 복사 class SubClass extends SuperClass { public SubClass() { super("Default Message"); System.out.println("SubClass Constructor"); } } 5. 부모 클래스의 매개변수 생성자를 선택적으로 호출하기 부모 클래스가 여러 생성자를 가지고 있다면, 필요한 생성자를 선택적으로 호출할 수 있 습니다. 예제 java 코드 복사 class SuperClass { public SuperClass() { System.out.println("Default SuperClass Constructo r"); } public SuperClass(String message) { System.out.println("SuperClass Constructor: " + mes sage); } 객체지향프로그래밍 21 } class SubClass extends SuperClass { public SubClass() { super(); //부모의 기본 생성자 호출 System.out.println("SubClass Constructor (Defaul t)"); } public SubClass(String message) { super(message); // 부모의 매개변수 생성자 호출 System.out.println("SubClass Constructor (Parameter ized)"); } } public class Main { public static void main(String[] args) { SubClass obj1 = new SubClass(); SubClass obj2 = new SubClass("Hello"); } } 객체지향프로그래밍 22 Polymorphism ( 다형성) 다형성 : 하나의 참조변수 (예 Question q)가 여러 타입의 객체( Question, ChocieQuestion)를 참조할 수 있는 능력. 핵심: 상위 클래스 타입의 변수로 하위 클래스 객체를 참조할 수 있음 다형성의 동작 원리 1. 상위 클래스 타입 변수 사용: : Question q 타입의 참조 변수는 Question Question 또는 그 하위 클래스 객체를 참 조할 수 있음. 예를 들어: java 코드 복사 Question q1 = new Question(); Question q2 = new ChoiceQuestion(); 2. 메서드 호출 시 동작: 를 호출하면 실제 객체의 타입에 따라 실행되는 메서드가 결정됨. q.display() 예: → q1.display() 클래스의 실행. Question display → q2.display() 클래스에서 오버라이딩된 ChoiceQuestion 실행. display 다형성의 장점 유연성: 상위 클래스 타입으로 여러 하위 클래스 객체를 처리할 수 있어, 코드의 유 연성 증가 코드 간결성: 하나의 메서드가 여러 타입의 객체를 다룰 수 있으니, 중복 코드를 줄 일 수 있음 확장성 : 새로운 하위 클래스 추가 시, 기존 코드 수정 없이 바로 사용 다형성 장점에 대한 예시 객체지향프로그래밍 23 상위 클래스 과 두 개의 하위 클래스 Question 및 ChoiceQuestion 을 사용합니다. TrueFalseQuestion 유연성: 하나의 메서드로 서로 다른 하위 클래스 객체를 처리합니다. 코드 간결성: 동일한 로직을 중복 작성하지 않고 재사용합니다. 확장성: 새로운 하위 클래스( )를 추가해도 기존 메서드를 수 FillInTheBlankQuestion 정할 필요가 없습니다. 다형성 동적 메서드 조회 When the virtual machine calls an instance method: JVM은 실행 시점에 객체의 실제 클래스에서 메서드를 찾아 호출합니다. 이를 **Dynamic Method Lookup(동적 메서드 조회)**라고 합니다. Dynamic method lookup allows us to treat objects of different classes in a uniform way. 다형성 덕분에, 부모 클래스 타입의 변수를 사용해 자식 클래스의 객체를 참조하면 서 일관된 방식으로 다룰 수 있습니다. 예를 들어, 여러 타입의 객체(Dog, Cat 등)를 공통된 방식으로 처리할 수 Animal 있습니다: java 코드 복사 Animal[] animals = {new Dog(), new Cat()}; for (Animal animal : animals) { animal.speak(); // 실제 객체에 따라 다른 메서드가 호출됨 } 1. 상위 클래스와 하위 클래스 정의 jav // 상위 클래스 public class Question { private String text; private String answer; 객체지향프로그래밍 24 public void setText(String text) { this.text = text; } public void setAnswer(String answer) { this.answer = answer; } public boolean checkAnswer(String response) { return response.equalsIgnoreCase(answer); } public void display() { System.out.println(text); } } // 하위 클래스 1: ChoiceQuestion import java.util.ArrayList; public class ChoiceQuestion extends Question { private ArrayList choices; public ChoiceQuestion() { choices = new ArrayList(); } public void addChoice(String choice) { choices.add(choice); } @Override public void display() { super.display(); // 상위 클래스의 display 호출 for (int i = 0; i < choices.size(); i++) { System.out.println((i + 1) + ": " + choices. get(i)); } 객체지향프로그래밍 25 } } // 하위 클래스 2: TrueFalseQuestion public class TrueFalseQuestion extends Question { @Override public void display() { super.display(); System.out.println("1: True"); System.out.println("2: False"); } } 2. 다형성을 활용한 메서드 정의 java 코드 import java.util.Scanner; public class Quiz { public static void presentQuestion(Question q) { q.display(); // 동적 바인딩에 따라 실제 객체의 display 호출 Scanner in = new Scanner(System.in); System.out.print("Your answer: "); String response = in.nextLine(); System.out.println("Correct? " + q.checkAnswer(r esponse)); } } 3. 실행 코드 java 코드 복사 public class Main { 객체지향프로그래밍 26 public static void main(String[] args) { // Question객체 생성 Question basicQuestion = new Question(); basicQuestion.setText("What is the capital of Fr ance?"); basicQuestion.setAnswer("Paris"); // ChoiceQuestion 객체 생성 ChoiceQuestion choiceQuestion = new ChoiceQuesti on(); choiceQuestion.setText("What is 2 + 2?"); choiceQuestion.addChoice("3"); choiceQuestion.addChoice("4"); choiceQuestion.addChoice("5"); choiceQuestion.setAnswer("4"); // TrueFalseQuestion 객체 생성 TrueFalseQuestion trueFalseQuestion = new TrueFa lseQuestion(); trueFalseQuestion.setText("The earth is flat."); trueFalseQuestion.setAnswer("False"); // 다형성을 활용해 질문 출력 및 정답 확인 Quiz.presentQuestion(basicQuestion); Quiz.presentQuestion(choiceQuestion); Quiz.presentQuestion(trueFalseQuestion); } } 4. 실행 결과 yaml 코드 복사 What is the capital of France? Your answer: Paris Correct? true 객체지향프로그래밍 27 What is 2 + 2? 1: 3 2: 4 3: 5 Your answer: 4 Correct? true The earth is flat. 1: True 2: False Your answer: False Correct? true 장점 요약: 1. 유연성: 메서드는 presentQuestion , , Question ChoiceQuestion TrueFalseQuestion 등 어떤 하위 클래스도 처리 가능. 2. 코드 간결성: 각 질문 유형별로 별도 메서드를 작성할 필요 없이 하나의 메서드로 처 리. 3. 확장성: 새로운 질문 유형 ( ) 추가 시에도 FillInTheBlankQuestion presentQuestion 메서드를 수정하지 않아도 동작. 예: 새로운 하위 클래스 추가 java public class FillInTheBlankQuestion extends Question { @Override public void display() { System.out.println(getText().replace("_", "___ _")); } } 객체지향프로그래밍 28 하위클래스 SavingAccount를 업캐스팅 해 상위 클래스에 저장 가능 c는 유효하지만 아무런 의미를 가지지 않는다 account 는 BankAccount 클래스이거나, BankAccount 의 하위 클래스 중 하나입니다. 이유: 1. 변수의 타입이 account 로 선언되었으므로, 이 변수는 BankAccount 타입 객 BankAccount 체나 그 하위 클래스 객체를 참조할 수 있습니다. 2. 객체 참조가 이 아니므로 실제로 특정 객체를 가리키고 있습니다. null 3. 따라서 이 객체는 클래스의 인스턴스이거나, BankAccount 를 상속받은 하위 BankAccount 클래스의 인스턴스라는 것을 알 수 있습니다. 이것은 Java의 다형성(Polymorphism) 개념에 기반합니다 Java 의 Object 클래스 객체지향프로그래밍 29 핵심 내용: 1. Object 클래스란? Java에서 모든 클래스는 명시적으로 하지 않아도 자동으로 extends 클래스 Object 를 상속합니다. 즉, 클래스는 Java의 모든 클래스의 직접 또는 간접적인 최상위 슈퍼클래스 Object 입니다. 2. Object 클래스에서 제공하는 주요 메서드: toString() 객체를 설명하는 문자열을 반환합니다. 기본 구현은 객체의 클래스 이름과 해시코드를 반환하지만, 종종 오버라이딩하 여 객체의 의미 있는 정보를 출력하도록 수정합니다. equals(Object obj) 두 객체를 비교합니다. 기본적으로 참조값(메모리 주소)을 비교하지만, 논리적 동등성을 확인하려면 오버라이딩해야 합니다. hashCode() 객체의 해시코드를 반환합니다. 객체지향프로그래밍 30 객체를 해시 기반 컬렉션(Set, HashMap 등)에서 사용할 때 중요한 역할을 합 니다. legnth 없음!!!! 3. Object 클래스의 중요성: Java의 모든 객체는 클래스의 메서드를 사용할 수 있으므로, 이 클래스는 Object Java의 기본적인 동작에 필수적입니다. 활용: toString() 디버깅이나 로깅 시 유용하게 사용. : equals() 와 : 객체 비교와 해시 기반 데이터 구조에서 사용. hashCode() toString() 매서드 해시코드로 변환가능 Object 클래스의 기본 toString 메서드 Object 클래스의 기본 toString 구현은 다음과 같습니다: java 코드 복사 public String toString() { return getClass().getName() + "@" + Integer.toHexStr ing(hashCode()); } 클래스 이름과 **해시 코드(16진수)**를 반환합니다. 클래스는 이를 오버라이딩하지 않았기 때문에, 기본 동작이 유지됩니 PrintStream 다. toString() 메서드 재정의(Overriding) 요약 1. 기본 동작 메서드는 객체의 문자열 표현을 반환합니다. toString() 디버깅에서 유용하게 사용됩니다. 기본 구현은 객체의 클래스 이름과 해시코드를 포함 한 정보를 반환합니다. 객체지향프로그래밍 31 2. 재정의(Overriding)의 이유 기본 구현은 객체의 메모리 주소를 나타내는 해시코드를 반환하기 때문에 의미 있는 정 보를 제공하지 않습니다. 따라서, 객체의 **유의미한 정보(속성값 등)**를 문자열로 표현하고자 할 때 을 재정의합니다. toString() 3. 사용 예시 java Rectangle box = new Rectangle(5, 10, 20, 30); String s = box.toString(); // 기본 반환 값: "java.awt.Rectangle[x=5,y=10,width=20,height =30]" 4. 문자열 연결 시 자동 호출 객체와 문자열을 연결(concatenate)할 때 toString() 메서드가 자동으로 호출됩니다. java String result = "box=" + box; // 출력 : "box=java.awt.Rectangle[x=5,y=10,width=20,height=3 0]" 5. 왜 항상 toString() 메서드를 사용할 수 있나? 모든 클래스는 암묵적으로 Object 클래스를 상속받으며, Object 클래스는 toString() 메서드를 선언하고 있습니다. 6. 재정의 예시 java class Rectangle { int width, height; 객체지향프로그래밍 32 Rectangle(int width, int height) { this.width = width; this.height = height; } @Override public String toString() { return "Rectangle[width=" + width + ", height=" + h eight + "]"; } } Rectangle rect = new Rectangle(20, 30); System.out.println(rect); // 출력: Rectangle[width=20, heig ht=30] equals 메서드 오버라이딩 설명 핵심 요약 ==두 객체가 같은 메모리 주소를 참조하는지 확인. : : 두 객체의 **내용(값)**이 같은지 확인. equals 오버라이딩된 메서드를 사용하면, 객체의 내용 기반 비교가 가능. equals 메서드를 구현할 때는 equals 메서드도 함께 오버라이딩해야 올바른 동작을 hashCode 보장합니다. 매개변수 타입 캐스팅 캐스팅이 필요한 이유: 매개변수 타입이 이기 때문에, 실제 클래스( Object Stamp ) 에서 정의한 필드에 접근 하려면 타입 캐스팅이 필요합니다. 캐스팅 방법: java 코드 복사 객체지향프로그래밍 33 Stamp other = (Stamp) otherObject; 주의: 캐스팅 전에 instanceof 로 타입 검사를 해야 안전합니다. 타입이 다르면 ** *이 발생할 수 있습니다. ClassCastException 새로운 개념: instanceof 와 getClass instanceof : 객체가 특정 클래스나 그 하위 클래스의 인스턴스인지 확인. 사용 예: java 코드 복사 if (otherObject instanceof Stamp) { Stamp other = (Stamp) otherObject; } getClass() : 객체의 정확한 클래스를 반환. 같은 클래스인지 확인할 때 사용: java 코드 복사 if (getClass() != otherObject.getClass()) return fals e; 객체지향프로그래밍 34 질문 분석 질문: 왜 모든 객체를 가장 상위 클래스인 Object 타입 변수에 저장하지 않는가? 답변: Object타입 변수로는 제한된 메서드만 호출할 수 있기 때문입니다 4가지 , toString(), equals(Objects obj), hashCode(),getClass(), no 10 장 인터페이스 (Interface) 인터페이스란? 정의: 자바에서 인터페이스는 클래스가 따라야 하는 일련의 규약(메서드의 시그니처)을 정의합니다. 인터페이스는 메서드의 선언만 포함하며, 구현은 하지 않습니다. 특징: 1. 추상적 메서드: 인터페이스의 모든 메서드는 기본적으로 추상적이며, 자바 8 이후에 는 또는 default 메서드를 사용할 수 있습니다. static 2. 다중 구현 가능: 한 클래스는 여러 개의 인터페이스를 구현할 수 있습니다. 3. 인스턴스 변수 없음: 인터페스에는 필드를 가질 수 없습니다. 다만, 상수(기본적으로 )는 가능합니다. public static final 4. 생성자 없음: 객체를 직접 생성할 수 없습니다. 인터페이스 선언 public interface Measurable { double getMeasure(); } 이 예시는 측정 가능한 객체를 나타내는 인터페이스입니다. 메서드를 모든 구현 클래스가 제공해야 합니다. getMeasure 인터페이스 이름이 목적에 맞게 그리고 모듈화가 잘 되어야함, 목적성에 어긋나는 것 x 인터페이스 구현 객체지향프로그래밍 35 public class BankAccount implements Measurable { private double balance; public BankAccount(double balance) { this.balance = balance; } @Override public double getMeasure() { return balance; // BankAccount 의 측정 기준은 balance } } implements 키워드를 사용해 인터페이스를 구현합니다. getMeasure 메서드를 구체적으로 구현합니다. 인터페이스를 활용한 다형성 인터페이스 타입의 변수는 그 인터페이스를 구현한 객체를 참조할 수 있습니다. BankAccount에서 인터페이스를 사용했어야만 함! 사용 안되어있으면 안됨!ㅋㅈ Measurable obj = new BankAccount(1000); 하지만 인터페이스 타입 변수로는 인터페이스에 선언된 메서드만 호출 가능합니다. 인터페이스에 정의된 메서드를 호출하면, 실제 객체의 타입에 따라 알맞은 구현이 실행 됩니다. 이 동작은 **런타임(runtime)**에 결정됩니다. System.out.println(m1.getMeasure()); // 출력: 1000.0 System.out.println(m2.getMeasure()); // 출력: 176220.0 메서드를 호출하면: getMeasure() 은m1 의 구현을 호출. BankAccount 는m2 의 구현을 호출. Country 이 동작은 컴파일 시점이 아니라 런타임에 결정됩니다 객체지향프로그래밍 36 사용 사례 1. 코드 재사용 Measurable 인터페이스를 사용하는 평균 계산 메서드: public static double average(Measurable[] objects) { double sum = 0; for (Measurable obj : objects) { sum += obj.getMeasure(); } return objects.length > 0 ? sum / objects.length : 0; } 다양한 클래스(BankAccount, Country 등)에서 Measurable 인터페이스를 구현하고 메서드를 재사용 가능. average 2. 다중 인터페이스 구현 public interface Named { String getName(); } public class Country implements Measurable, Named { private String name; private double area; public Country(String name, double area) { this.name = name; this.area = area; } @Override public double getMeasure() { return area; } @Override public String getName() { 객체지향프로그래밍 37 return name; } } 자주 묻는 질문 1.인터페이스와 클래스의 차이점은? 클래스는 상태와 동작(필드와 메서드)을 가질 수 있지만, 인터페이스는 동작의 규약 만 정의합니다. 2. 왜 인터페이스를 사용할까요? 서로 다른 클래스가 공통된 동작을 가지도록 보장하면서 코드 결합도를 낮추고 재 사용성을 높이기 위함입니다. 3. 인터페이스란? Comparable 객체를 비교하기 위한 인터페이스로, 메서드를 구현해야 합니다. 이를 통 compareTo 해 객체 배열을 정렬하는 등 기능을 수행합니다. 필요한 부분을 더 깊이 알고 싶거나, 구체적인 예제를 원하면 말씀해주세요! 인터페이스를 통해 배열이나 객체 다루는 방법 1. 인터페이스 타입을 사용하는 방법 (재사용하기!) 인터페이스 타입(예: )을 사용하면, 인터페이스를 구현한 다양한 클래스의 객체 Measurable[] 를 동일한 배열이나 변수에서 처리할 수 있습니다. 예시: Measurable 타입 배열 사용 java 코 public interface Measurable { double getMeasure(); } public class BankAccount implements Measurable { private double balance; public BankAccount(double balance) { 객체지향프로그래밍 38 this.balance = balance; } @Override public double getMeasure() { return balance; } } public class Country implements Measurable { private String name; private double area; public Country(String name, double area) { this.name = name; this.area = area; } @Override public double getMeasure() { return area; } } // Main 메서드에서 사용 Measurable[] objects = { new BankAccount(1000), new Country("Korea", 100000) }; for (Measurable obj : objects) { System.out.println("Measure: " + obj.getMeasure()); } 결과 1. BankAccount 와 Country 는 모두 Measurable 인터페이스를 구현. 객체지향프로그래밍 39 2. 배열 은 다양한 클래스의 객체를 동일한 타입으로 다룰 수 있도록 함. Measurable[] 3. 인터페이스 타입 배열을 사용하면 코드의 다형성(polymorphism)을 극대화할 수 있습 니다. 2. implements 키워드를 사용하여 인터페이스 구현 는 클래스가 특정 인터페이스를 구현하도록 강제합니다. 인터페이스에 선언된 모 implements 든 메서드를 클래스에서 반드시 구현해야 합니다. 예시: implements 사용 java public interface Measurable { double getMeasure(); } public class BankAccount implements Measurable { private double balance; public BankAccount(double balance) { this.balance = balance; } @Override public double getMeasure() { return balance; } } BankAccount 클래스는 인터페이스를 **구현(implements)**합니다. Measurable getMeasure 메서드를 반드시 구현해야 하며, 값을 반환하도록 구현되었습니다. balance 두 방법의 차이점 특징 인터페이스 타입 사용 implements 사용 객체지향프로그래밍 40 목적 여러 구현체를 동일한 인터페이스로 다 특정 클래스가 인터페이스 규약을 따르 루기 게 하기 사용 위치 객체 참조, 배열, 메서드 매개변수 등 클래스 선언 구현 필수 여부 인터페이스를 참조할 때는 구현된 메서 클래스에서 반드시 인터페이스 메서드 드 사용 가능 구현 필요 Measurable[] 배열로 다양한 클래스 예시 처리 class BankAccount implements Measurable 정리 1. 처럼 인터페이스 타입을 사용하면 여러 구현 클래스의 객체를 공통된 방식 Measurable[] 으로 처리할 수 있습니다. 2. 는 클래스가 특정 인터페이스를 따르도록 강제하며, 인터페이스의 모든 메서 implements 드를 구현해야 합니다. 두 개념은 서로 보완적인 관계로, 를 통해 인터페이스를 구현한 후, 인터페이스 implements 타입으로 객체를 참조하여 다형성을 활용할 수 있다. 인터페이스 사용 목적 여러 다른 클래스들을 공통된 방식으로 처리 할 때 ! 인터페이스와 상속의 차이점 인터페이스: 다중 구현이 가능 ( implements Measurable, Named ). 상속: 한 번에 하나의 슈퍼클래스만 상속 가능 ( extends ). 질문: 왜 메서드를 사용하여 average 객체의 평균 길이를 구할 수 없는가? String 답변 요약: 클래스는 라이브러리 클래스이기 때문에 수정할 수 없습니다. String 따라서 인터페이스를 구현하도록 Measurable 클래스를 변경할 수 없습니다.String 내가 만든 클래스 이면 수정할 수 있다. 객체지향프로그래밍 41 클래스타입 변수 vs 인터페이스 타입 변수 클래스 타입 변수: Country thailand =.. 모든 메서드와 필드에 접근가능 인터페이스 타입 변수(객체)ㅋㅈ : Measurable max =.. 인터페이스에서 정의한 매서드에만 정의 가능 인터페이스 변수의 다형성 어떤 클래스의 객체든 참조 가능 ( Measurable을 구현 되어있으면) Casting 인터페이스를 클래스로 Country maxCountry = max 처럼 max가 인터페이스 변수이면 클래스 변수에 참조 되지가 않음 이처럼 캐스팅 해줘야함 그 대신! → Country maxCountry = (Country) max Country가 인터페이스를 사용했어야함 위 Casting을 하는 이유? 위 코드에서 와 같은 **캐스팅(Casting)**을 하는 이유는, 인터페이스 타입으로 선언 (Country) max 된 변수 를 특정 클래스 타입인 max 로 변환하여, 클래스에 정의된 메 Country Country 서드( )를 호출하기 위함입니다. 이를 좀 더 자세히 설명해 보겠습니다: getName() Comparable 인터페이스 핵심 요약 1. Comparable 의 역할 ◦ 객체 간의 순서를 정의하기 위해 사용하는 인터페이스입니다. ◦ 기본적으로 **자연스러운 정렬(natural order)**을 제공합니다. ◦ 또는 Arrays.sort() 같은 정렬 메서드에서 사용됩니다. Collections.sort() 2. 객체지향프로그래밍 42 compareTo 메서드 java 코드 복사int compareTo(Object otherObject); ◦ 두 객체를 비교하여 순서를 결정합니다. ◦ 반환값의 의미: ▪ 음수 (-1): 현재 객체( )가 비교 대상( )보다 작음 → 가 앞에 와야 함. a b a ▪ 0: 두 객체가 동일함. ▪ 양수 (+1): 현재 객체가 비교 대상보다 큼 → 가 앞에 와야 함. b Measurable 인터페이스의 한계 제약사항: 1. 인터페이스는 통제 가능한 클래스에만 추가할 수 있습니다. Measurable 2. 하나의 기준으로만 객체를 측정할 수 있습니다.예: 자동차를 속도(speed)와 가격 (price) 두 가지 기준으로 동시에 분석할 수 없습니다. Callback 의 개념 콜백(Callback): 나중에 실행될 코드를 명시하는 메커니즘. 특정 작업을 처리하는 것이라고 생가갛면 편하다. 특정 연산을 처리하는 클래스에서 다른 연산이 필요할 때 특정 클래스에서 연산 처리를 넘기는 것이 콜백이다. 측정 방식의 책임을 객체 자신이 아닌 **별도의 측정 도구(콜백 인터페이스)**에 맡깁 니다. 대안: Measurer 인터페이스 평균 계산 메서드에 데이터를 전달할 때, 측정 방식을 정의하는 인터페이스도 함께 전달 합니다. 새로운 인터페이스 정의: Measurer 객체지향프로그래밍 43 java 코드 복사 public interface Measurer { double measure(Object anObject); } // measure 은 외부 객체를 처리하기 위함임 getMeasure 과 다른점 : 이것은 자기 자신을 처리하기 위함 이 인터페이스를 사용하면 다양한 기준으로 측정 가능하며, Object 를 기준으로 모든 객 체를 처리할 수 있습니다. 콜백 발생 상황: (Rectangle 관련 콜백 다시 봐두기!! 자료랑 p.43) average 메서드에서 반복문을 통해 measure 메서드를 호출합니다: java sum += meas.measure(obj); 여기서 는 클래스에서 구현된 meas.measure(obj) 메서드를 호출 AreaMeasurer measure 하는 것입니다. 1. 콜백 객체( ): AreaMeasurer 메서드를 구체적으로 구현하여 특정 작업(사각형 넓이 계산)을 수행합니 measure 다: java public double measure(Object anObject) { Rectangle aRectangle = (Rectangle) anObject; return aRectangle.getWidth() * aRectangle.getHeig ht(); } 콜백의 의미 객체지향프로그래밍 44 메서드는 직접적으로 사각형의 넓이를 계산하지 않고, average 라는 동작을 외 measure 부 객체( )에 위임합니다. AreaMeasurer 이처럼, 메서드( )가 자신의 작업 일부를 외부 객체의 메서드( average )에 위임하 measure 고 호출하는 것이 콜백입니다. 람다 표현식 (다시 정리하기) 람다 표현식은 인터페이스에 할당 되어야만한다 람다 형식: 매개변수 실행문 } ( ) -> { 예제와 함께 형식 정리 1) Runnable (매개변수 없음) java 코드 복사 Runnable r = () -> System.out.println("No parameters, just 객체지향프로그래밍 45 action!"); 2) Consumer ( 매개변수 1개) java 코드 복사 Consumer printer = message -> System.out.println(me ssage); 3) Comparator ( 매개변수 2개) java 코드 복사 Comparator comparator = (a, b) -> a - b; 4) Custom Functional Interface java 코드 복사 @FunctionalInterface interface Adder { int add(int a, int b); } Adder adder = (a, b) -> a + b; System.out.println(adder.add(10, 20)); // 출력: 30 1. Inner Classes ( 내부 클래스) 객체지향프로그래밍 46 핵심 내용 내부 클래스는 외부 클래스 안에 정의된 클래스로, 외부 클래스의 모든 메서드와 변수에 접근할 수 있습니다. 컴파일러는 내부 클래스를 독립적인 클래스 파일로 컴파일하되, 이름은 외부 클래스와 연결됩니다.(예: ) OuterClass$InnerClass.class 예시 : MeasurerTester$1AreaMeasuer.class // $1로 연결 사용 이유 외부 클래스와 강하게 연관된 유틸리티 클래스나 헬퍼 클래스를 정의할 때 사용. 가시성 제한: 내부 클래스는 외부 클래스에서만 사용되며, 다른 클래스에서는 보이지 않 음. 예시 java 코드 복사 public class OuterClass { class InnerClass { void display() { System.out.println("Inner class method."); } } public static void main(String[] args) { OuterClass outer = new OuterClass(); OuterClass.InnerClass inner = outer.new InnerClass (); inner.display(); // 출력: Inner class method. } } Mock Objects 핵심 내용 객체지향프로그래밍 47 Mock객체는 실제 객체의 간단한 대체품으로, 프로그램의 특정 부분을 테스트할 때 사 용됩니다. 전체 시스템이 완성되지 않은 상태에서도 개별 기능을 독립적으로 테스트할 수 있습니 다. 사용 이유 실제 객체 생성이 어렵거나 시간이 오래 걸리는 경우, 테스트를 단순화하고 효율성을 높 이기 위해 사용. 예시 java 코드 복사 // Mock 객체 생성 class MockDatabase { boolean isConnected() { return true; // 실제 데이터베이스 연결 없이 테스트 } } public class Test { public static void main(String[] args) { MockDatabase db = new MockDatabase(); System.out.println("Connected: " + db.isConnected ()); // 출력: Connected: true } } Event Handling ( 이벤트 처리) 핵심 내용 이벤트 기반 프로그래밍에서 사용자 인터페이스(UI) 입력(예: 버튼 클릭, 키 입력)을 처 리하는 메커니즘. 프로그램은 특정 **이벤트 리스너(listener)**를 등록하고, 이벤트가 발생하면 이를 처 리하도록 설계. 이벤트 소스를 적절하게 이벤트 리스너에 추가 객체지향프로그래밍 48 이벤트 발생시 이벤트 소스가 리스너에게 알림 사용 이유 사용자와 상호작용하는 프로그램에서 입력을 처리하기 위해 필요. 불필요한 이벤트는 필터링하고, 필요한 이벤트만 처리 가능. 예시 java 코드 복사 import java.awt.event.*; public class EventExample { public static void main(String[] args) { Button button = new Button("Click Me"); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println("Button Clicked!"); } }); } } 요약 개념 핵심 사용 이유 외부 클래스 안에 정의된 클래스. 외부 클래스에 강 가시성 제한, 코드 간결화 Inner Classes 하게 연결된 헬퍼 클래스 정의 실제 객체를 대체하는 간단한 테스트용 객체 테스트 효율성, 복잡도 감 Mock Objects 소 UI 상호작용, 특정 이벤트 Event Handling 사용자 입력(이벤트)을 처리하는 메커니즘 만 처리 이 세 가지는 각각 코드 간결화, 테스트 단순화, 사용자 인터페이스 상호작용 처리에 초점을 맞춘 프로그래밍 기술입니다. 객체지향프로그래밍 49 11 장 Input_Output and Exception Reading Files File inputFile = new File("Text.txt"); 파일 내용 담을 객체 가져오기 Scanner in = new Scanner(inputFile); 가져온 파일 스캔할 스캐너 생성 While(in.hasnextDouble()) { double value = in.nextDouble() } Writing Files PrintWriter out = new PrintWriter("output.txt") 쓰기 객체 생성 있는 내용 지우고 씀 , 파일 이름이 없으면, 파일을 생성해서 작성 out.println("Hello, World!"); 쓰기방법 파일 닫기 in.close() out.close() 객체지향프로그래밍 50 내용을 바로 쓰거나 읽는게 아니라, 버퍼에 담았다가 쓰기 때문에 이 행위를 그만하기 위해, 작동하지 않을 때 닫아 줘야함. 파일 예외처리 : FileNotFoundException public static void main(String [] args) throws FileNotFoundExc 문자열 파일 입력 출력 next 메소드로 string을 읽음 입력 파일의 끝에 도달했을 경우: 입력 파일의 끝에 도달했지만 어떤 단어도 반환하지 못한다면, "NoSuchElementException" 예외가 발생합니다. delimited 라는 개념 등장! delimited는 구분자로 보면됨 ( 구분 기준 : white space, 설정 가능) white space : 스페이스, 탭, 새로운 공간. 다양한 Scanner 메서드 활용 메서드: useDelimiter 특정 패턴으로 입력을 구분하도록 설정. 예: in.useDelimiter("[^A-Za-z]+"); 문자(AZ, az)가 아닌 것을 단어의 구분자로 사용. 줄 별로 Reading String line = in.nextLine() hasNextLine() 으로 줄이 있는지 유효성 검사 객체지향프로그래밍 51 문자열 앞 뒤 빈 공백 제거 Trim() : 헷갈리는 것 가 lineScanner.next() 가 되는 이유는 "States" 클래스의 메서드가 공백 Scanner next() (whitespace)을 기준으로 문자열을 읽기 때문입니다. 자세히 설명하자면: lineScanner.next() 의 동작 1. 는 입력 문자열( )을 공백(스페이스, 탭, 줄바꿈)으로 구분하여 단어 단위로 Scanner line 읽어옵니다. 2. 첫 번째 호출: 가 처음 호출되면 첫 번째 단어(공백으로 구분된 첫 번째 문자 lineScanner.next() 열)를 반환합니다. 예: 에서 반환. "United States 1234567" "United" 3. 다음 호출: 이후 호출될 때는 다음 단어를 반환하며, 읽은 값은 내부적으로 소비됩니다. 예: 두 번째 호출에서 반환. "States" 문자열이 숫자일 때 변환 Integer.parseInt( ); Double.parseDouble( ); 줄바꿈 문자 소비 은 줄바꿈 문자 소비를 함 nextline nextdouble , nexttInt는 줄바꿈 문자 소비 안함 객체지향프로그래밍 52 줄바꿈 소비를 위해 3번째 명령어 실행 printf %-10s : 왼쪽으로 정렬하고, 10자리에 스트링 %10.2f : 오른쪽 정렬이고, 10자리고 , 10자리 중 2자리 소숫점 , 실수형 커맨드라인 인자 프로그램 실행 시 추가 입력값을 전달하는 방법 main(String[] args)의 args 배열로 전달받으며, 배열의각 요소가 입력값에 해당한다. 프로그램 내에서 다양한 유홍한 기능 java ProgramClass -v input.dat args : “-v” args : “input.dat” Exception Handling ( 에러 핸들러) 1. 예외 처리 목적 에러가 발생한 시점에서 이를 감지하고, 에러를 처리할 수 있는 핸들러로 넘긴다 객체지향프로그래밍 53 코드가 얘기치 못한 상황에서도 안전하게 종료되거나 복구되도록 돕는다. 2. 예외를 던지는 방법 (throw) 예외를 던질 때, thorw 키워드 사용 자바 예외 계층구조 (Hierarchy of Exception Classes) 검사 예외) : 사용자 잘못으로 인한 예외 1. Checked Exception ( Exception 클래스를 상속받는 Runtime Exception 을 제외한 예외가 해당 2. Unchecked Exception (비검사 예외) : 프로그래머의 실수로 인해 발생 try {.. } catch (IOException exception) { exception.printStackTrace(); } catch (NumverFormatiException exception) { exception.println(exception.getMessage()); } 객체지향프로그래밍 54 관련 Throw 예외 Scanner : FileNotFoundException Scanner.next :NoSuchElementException Integer.parseInt : NumberFormatException 상속 계층 구조에 따라 처리되는 예외 순서 주의, 하위클래스 예외를 개별 처리하려면 catch 순서를 하위 클래스가 먼 catch 저 나오게 해야한다. 상위 클래스가 먼저나오면 밑 클래스는 절 때 실행 안됨 try { throw new FileNotFoundException(); } catch (IOException e) { // 상위 클래스 System.out.println("Caught IOException."); } catch (FileNotFoundException e) { // 하위 클래스 // 이 블록은 절대 실행되지 않음 System.out.println("Caught FileNotFoundException."); } 처리되지 않은 예외는 다른 try-catch로 전달되거나 프로그램이 종료된다. 구체적인 예외를 먼저 처리한다. Java 예외의 세 가지 범주 1. 계열 예외 (내부 시스템 오류): Error 프로그램에서 복구할 수 없는 심각한 문제. 예: , OutOfMemoryError. StackOverflowError 특징: 대부분 JVM 내부에서 발생. 프로그래머가 처리하지 않음. 2. 계열 예외 (Unchecked Exception): RuntimeException 코드의 논리적 오류로 인해 발생하는 문제. 객체지향프로그래밍 55 예: , , IndexOutOfBoundsException NullPointerException IllegalArgumentException. 특징: 프로그래머가 예방해야 함. 컴파일러가 예외 처리 강제하지 않음. 3. 기타 예외 (Checked Exception): 외부 환경의 문제로 인해 발생. 예: , IOException. SQLException 특징: 컴파일러가 예외 처리를 강제. 프로그램이 안정적으로 동작하도록 하기 위해 필수적. Checked Exception vs Unchecked Exception (1) Checked Exception 정의: 외부 환경에 의해 발생하며, 프로그래머가 이를 처리해야 컴파일이 성공. 유저에 의 해 발생 예: , IOException. SQLException 특징: 프로그래머가 처리 방법을 반드시 명시해야 함. 예외를 처리하거나 키워드를 통해 상위 호출자에게 넘길 수 있음. throws 예제: java 코드 복사 try { FileReader file = new FileReader("input.txt"); // 파일이 없으면 IOException 발생 } catch (IOException e) { System.out.println("File not found: " + e.getMessage ()); 객체지향프로그래밍 56 } (2) Unchecked Exception 정의: 코드의 논리적 오류로 인해 발생. 프로그래머의 잘못 예: , NullPointerException. ArithmeticException 특징: 컴파일러가 예외 처리를 강제하지 않음. 예외를 방지하기 위해 코드를 올바르게 작성하는 것이 중요. 예제: java 코드 복사 int[] numbers = {1, 2, 3}; System.out.println(numbers); // IndexOutOfBoundsExceptio n 발생 3. 주요 차이점 구분 Checked Exception Unchecked Exception 발생 원인 외부 환경 문제 (파일, 네트 코드의 논리적 오류 (프로그래머 실수) 워크 등) 컴파일 시점 예외 처리를 강제함 예외 처리를 강제하지 않음 대표 예 IOException , SQLException NullPointerException , IndexOutOfBoundsException = Checked 예외에서 - thorws Best Practice: "Throw Early, Catch Late" Throw Early: 객체지향프로그래밍 57 문제가 발생한 즉시 예외를 던집니다. 문제를 감지한 위치에서 예외를 발생시켜 프로그램의 상태를 명확히 합니다. Catch Late: 예외를 가능한 한 가까운 상위 수준에서 처리합니다. 여러 메서드에서 발생하는 예외를 한 곳에서 처리할 수 있습니다. checked ,unchecked 예외 둘다 던지기 가능. try - with - resources 구문 자동으로 리소스를 닫아주는 구문 ( 닫아주는게 필수 인데) try 문 끝에 끝남! 사용자 정의 예외란? (Custom Exception) *사용자 정의 예외(Custom Exception)**는 특정 상황에 맞게 새로 정의된 예외 클래 스입니다. Java의 또는 Exception 클래스를 상속받아 만듭니다. RuntimeException 객체지향프로그래밍 58 사용자 정의 예외 만들기 (1) 기본 구조 사용자 정의 예외는 Java의 기존 예외 클래스를 확장합니다. Checked Exception: 을 상속. Exception Unchecked Exception: 또는 다른 Unchecked Exception을 상 RuntimeException 속. (2) 구현 예제 java 코드 복사 public class InsufficientFundsException extends IllegalArgu mentException { // 기본 생성자 public InsufficientFundsException() {} // 메시지를 받는 생성자 public InsufficientFundsException(String message) { super(message); // 상위 클래스의 생성자 호출 } } 3. 예외 발생 및 처리 (1) 예외를 발생시키기 사용자 정의 예외는 일반 예외처럼 throw 키워드를 사용하여 발생시킵니다. 예제: java 코드 복사 if (amount > balance) { throw new InsufficientFundsException( "Withdrawal of " + amount + " exceeds balance of " + balance 객체지향프로그래밍 59 ); } 동작: 잔액보다 큰 금액을 출금하려고 하면 InsufficientFundsException 이 발생. 예외 메시지는 생성자에서 제공한 메시지로 설정됩니다. (2) 예외 처리 발생한 예외는 try-catch 블록으로 처리합니다. 예제: java 코드 복사 try { withdraw(amount); } catch (InsufficientFundsException e) { System.out.println("Error: " + e.getMessage()); } 출력: javascript Error: Withdrawal of 100 exceeds balance of 50 객체지향프로그래밍 60 좋은 문제, 예외처리 여부와 설명까지 해야하는 문제 프로그래머가 예방 처리가 가능한 것이므로 예외로 처리하기 보다는 프로그래머가 코드 예방하는 것이 더 중요하다. 객체지향프로그래밍 61 2 가지 문제 존재 PrintWriter 생성자 예외 미처리 문제 파일 생성하거나 열 수 없으면 FileNotFounException 발생함 Checked Exception 이므로 , try-catch를 하거나 throws를 통해 호출자에 게 전달해야함. lines 배열 요소 중 NullPointerException 발생할 수 있음 그래서 out.close 못할 수 있음 try-with-resources 구문 호출하기 line이 null인지 확인하는 조건문 추가 객체지향프로그래밍 62 정답 : 예외 클래스에서 부모 클래스에 전달하기 메세지를 커스텀 예외처리 할 때 사용했던것 같음 InsufficientFundsException 예제 사용자 정의 예외 코드: java 코드 복사 public class InsufficientFundsException extends IllegalArgu mentException { // 기본 생성자 public InsufficientFundsException() { super(); // 부모 클래스의 기본 생성자 호출 } // 메시지를 받는 생성자 public InsufficientFundsException(String message) { super(message); // 부모 클래스에 메시지 전달 } } 동작: super() : 부모 클래스의 기본 생성자를 호출. super(message) : 부모 클래스의 생성자에 예외 메시지를 전달. 객체지향프로그래밍 63 3. 메시지 전달의 목적 메시지는 예외의 원인이나 상태를 설명하는 데 사용됩니다. 예외가 발생했을 때, 메서드를 통해 메시지를 확인할 수 있습니다. getMessage() 예제 코드: java 코드 복사 try { throw new InsufficientFundsException("Insufficient fund s for withdrawal."); } catch (InsufficientFundsException e) { System.out.println(e.getMessage()); } 외부요인으로 checked exception 으로 처리 해야함 그리고 입출력과 관련 있으니 IOException의 IllegalArgumentException이 적절함. Finally 블록 블록: finally 예외 발생 여부와 관계없이 항상 실행되는 코드를 작성. 리소스 정리, 클린업 작업에 사용. 객체지향프로그래밍 64 try-with-resources : AutoCloseable 을 구현한 리소스의 정리 작업에 적합. try/finally 를 대체하는 현대적인 방식. 권장 사항: 가능하다면 try-with-resources 를 사용하여 코드를 간결하고 안전하게 작 재사용이 가능한 범용 클래스이니까 예외를 잡아도 처리할 방법 제약적임 예외를 직접 처리하지 않고 throws로 호출자에게 전달한다. 객체지향프로그래밍 65 예외처리 필요 없음 , unchecked exception 이기 때문 * *은 기본적으로 nextDouble() 또는 NoSuchElementException 을 InputMismatchException 던지며, 이를 추가로 선언할 필요가 없습니다. 대신 BadDataException 을 사용하면 구현이 간단해집니다. NoSuchElementException 그러나 Checked Exception( )은 호출자가 반드시 처리하도록 강제 BadDataException 하는 반면, Unchecked Exception( )은 처리 여부가 선택 사항 NoSuchElementException 입니다. 12 장 Object-Oriented Design Object-Oriented Design ✅ To use Class-Responsibility-Collaboration(CRC) cards ✅To identify inheritance, aggregation and dependency relationships betwwen classes Discovering Classes 어떤 요구사항을 원하는지 파악하고 어떻게 만족해야할 지 파악 To discover classes 요구 사항에서 명사(nouns)를 찾아 클래스 리스트업 리스트업한 클래스이 요구상항에 맞는 지 파악후 첨삭 method를 찾기 위해 verbs를 찾아 적절한 class와 매칭 CRC Card Method 를 가진 후에, Behavior(method)를 정의 해야함 Set of Classes Verbs를 찾아 method를 연결시키기 class간의 responsibiliteis를 찾기위해 CRC card 방법을 사용 CRC Card → classes, respoonsibilities, collaborators 3개로 구성 객체지향프로그래밍 66 Relationships between Classes Dependency( 의존) compile 하기 위해서는 다른 class가 필요할 때, 우리는 dependecy가 있다고 판 단 잠시 argument 정도로 잠시 사용하는 관계 반면, aggregation은 집합관계 최대한 Dependnecy 가 적게하기 (minmize the coupling)(스파게티 코드가 되 면 복잡) Aggregation (포함) Has-a 관계 , 앞뒤로 바꾸면 말이 안됨 예를 들어, Quiz class ㅁggregates a Quesion Class라고 한다면, Quiz class 는 Question object 여러개로 구성되어 Quiz가 나오므로, Aggregation 관계에 있다고 판단. aggregation은 dependency보다 더 쌤 instance variable 취금? A class may use the SCanner class without ever declaring an instance 로 정의를 해주지 않으면 variable of class Scanner → instance variable 객체지향프로그래밍 67 dependecy Scanner 도 인스턴스 변수로 정의하지 않으면 argument로 넘겨주니까 dependency( 의존)이다. 💡 public class Quiz{ privat ArrayList questions; } 상속) Inheritance( IS-a 관계, 앞뒤로 말 바꾸면 말이 됨 일반적 superclass 와 세부적인 subclass 사이의 관계 만약 has -a 관계에서 재사용률이 적다면 inheritance (is-a)관계 UML 관계 심볼 Aggregation만 반대로 되어있는거 조심 다른 것들은 사용하는 곳에서 사용하는 걸 가르키는데 Aggregation은 사용되는게 사용되어지는 곳을 가르킨다. 객체지향프로그래밍 68 Five-part program development process 1. Gather requirements ( 요구사항 분석) 2. Use CRC card tod find classes, responsibilities and collaborators 3. Use URM diagrams to record class relationships 4. Use javadoc to document method behaivor 5. Implement your program a. classes 의 body 구현 객체지향프로그래밍 69