# Sports
package com.kh.chap02_abstractAndInterface.part01_basic.mode.vo;
> 추상클래스
1. [표현법]
접근제한자 abstract class 클래스이름 {
abstract 예약어 -> 추상클래스, 추상메소드 선언할 때 붙임.
- 추상메소드가 존재하는 순간 추상클래스로 정의됨
* abstract라는 예약어를 사용해서 정의해야함
* 객체생성이 불가능함. 부모클래스 구실은 가능(다형성 적용 가능)
* 추상메소드는 있을수도 있고 없을수도 있음
* 추상클래스 == 일반필드 + 일반메소드 + 추상메소드(생략가능)
* => 추상메소드가 없어도 추상클래스로 정의 가능
* 언제사용? 개발자의 역량
* => 기술적으로 개발자가 판단했을 때 이 클래스는 객체생성이 불가능해야한다라고 생각이들면 추상클래스로 가능
* => 개념적으로 개발자가 판단했을 때 해당 클래스가 아직 구체적으로 덜 구현된 상태인 것 같다라고 생각이 들면 추상클래스로 가능
+ 일관된 인터페이스 제공, 꼭 필요한 기능 강제화
public abstract class Sports {
private int people;
public Sports() {
}
public Sports(int people) {
this.people = people;
}
public int getPeople() {
return people;
}
public void setPeople(int people) {
this.people = people;
}
> 추상메소드
1. [표현법]
접근제한자 abstract 반환형 메소드이름(); {뒤에괄호없음}
public abstract void rule();
* method body가 존재하지 않는 미완성 메소드
* abstract 예약어를 써서 정의해야 함.
* 미완성메소드가 하나라도 포함되는 순간 해당 클래스는 미완성 클래스(추상클래스)가 됨
* 해당 클래스 앞에도 abstract라고 써줘야함
@Override
public String toString() {
return "Sports [people=" + people + "]";
}
}
# Soccer
package com.kh.chap02_abstractAndInterface.part01_basic.mode.vo;
public class Soccer extends Sports {
@Override
public void rule() {
System.out.println("손으로 공잡지 않기");
}
}
- 만약 추상클래스의 메소드를 오버라이딩 하지 않으면, 에러가 발생함.
# Baseball
package com.kh.chap02_abstractAndInterface.part01_basic.mode.vo;
public class Baseball extends Sports {
@Override
public void rule() {
System.out.println("경기장에 맥주들고가지 않기");
}
}
# Run
package com.kh.chap02_abstractAndInterface.part01_basic.run;
import com.kh.chap02_abstractAndInterface.part01_basic.mode.vo.*;
public class Run {
public static void main(String[] args) {
//추상클래스로 객체 생성 불가!
//클래스가 미완성되었기때문
//Sports s = new Sports(); 생성자에만 에러
//Sports s; //참조형 변수로 사용가능 => 다형성으로 적용가능
//s = new Sports(); //객체생성 불가능
//Sports s = new Soccer();
//다형성을 이용해서 자식객체를 받아주는 용도로 사용가능
//객체배열
Sports[] arr = new Sports[2];
arr[0] = new Soccer();
arr[1] = new Baseball();
for(int i = 0; i<arr.length; i++) {
arr[i].rule();
}
}
}
# Person
package com.kh.chap02_abstractAndInterface.part02_family.model.vo;
public abstract class Person { //추상클래스
private String name;
private double weight;
private int health;
public Person() {
}
public Person(String name, double weight, int health) {
this.name = name;
this.weight = weight;
this.health = health;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
public abstract void eat(); //추상메소드
public abstract void sleep(); //추상메소드
@Override
public String toString() {
return "Person [name=" + name + ", weight=" + weight + ", health=" + health + "]";
}
}
# Mother
package com.kh.chap02_abstractAndInterface.part02_family.model.vo;
public class Mother extends Person implements Basic { //Person상속, Basic인터페이스
private int babyCount;
public Mother() {}
public Mother(String name, double weight, int health, int babycount) {
super(name, weight, health);
this.babyCount = babyCount;
}
public int getBabyCount() {
return babyCount;
}
public void setBabyCount(int babyCount) {
this.babyCount = babyCount;
}
@Override
public String toString() {
return super.toString() + "Mother [babyCount=" + babyCount + "]";
}
@Override
public void eat() { //추상메소드오버라이딩
super.setWeight(super.getWeight()+10);
super.setHealth(super.getHealth()+15);
}
@Override
public void sleep() { //추상메소드오버라이딩
super.setHealth(super.getHealth()+15);
}
}
# Baby
package com.kh.chap02_abstractAndInterface.part02_family.model.vo;
public class Baby extends Person implements Basic{ //인터페이스는 이중상속이 가능
//필드부
//없음
//생성자부
//기본 매개변수
public Baby() { }
public Baby(String name, double weight, int health) {
super(name, weight, health);
}
@Override
public String toString() {
return "Baby [" + super.toString() + "]";
}
@Override
public void eat() { //밥을 먹으면
//몸무게 5증가
//weight == 부모의 필드 + 5
//수정할 몸무게 == 기존의 몸무게 + 5 -> set
super.setWeight(super.getWeight()+5);
//건강도 5증가
super.setHealth(super.getHealth()+5);
}
@Override
public void sleep() {
//건강도 10증가
super.setHealth(super.getHealth()+10);
}
}
# Basic - 인터페이스
package com.kh.chap02_abstractAndInterface.part02_family.model.vo;
> 인터페이스
[표현법]
* 접근제한자 interface 인터페이스이름{
상수필드
추상메소드
}
* - 상수필드와 추상메소드만으로 이루어진 추상클래스의 변형체
* - 인터페이스의 필드는 "무조건" 상수필드
* - 인터페이스의 메소드는 "무조건" 추상메소드
* - 인터페이스는 다중상속을 허용한다. = 가장 큰 속성
* => 메소드가 겹치더라도 최종구현부분은 실제구현클래스에서 기술함(*문제없음)
* - "무조건"구현해야하는게 있을 때 인터페이스 틀만 만들어주고 상속하게 만듬 => 오버라이딩
* 추상클래스보다 좀 더 강한 규칙성, 강제성을 가진다.
* 추상클래스와 인터페이스
1. 공통점
- 객체 생성은 불가능하지만, 참조변수로 사용이 가능하다.(다형성을 적용할 수 있다)
- 상속받는 클래스에서 추상메소드를 오버라이딩 하도록 강제한다.
2. 차이점
- 추상클래스: 클래스 멤버로, 일반필드, 일반메소드 생성이 가능하고, 추상메소드가 포함되어있거나 abstract키워드를 통해 정의됨
- 인터페이스: 모든 필드는 다 상수 필드, 모든 메소드를 추상메소드로 정의해야 함
=> 존재하는 목적이 다름:
* 추상클래스는 추상클래스를 상속받아서 멤버변수(필드 메소드)를 이용하고 클래스를 확장하기 위한 용도
* 인터페이스는 클래스 기능(메소드)를 강제하기 위해서 사용.
* extends와 implements
* - 클래스 간의 상속관계: 자식클래스 extends 부모클래스
* - 클래스와 인터페이스 구현관계: 클래스 implements 인터페이스
* 만약 다중상속을 하는 경우,
* implements 인터페이스1, 인터페이스2
public interface Basic {
//인터페이스에서는 무조건 상수필드와 추상메소드밖에 정의가 불가하므로
//접근제한자, 예약어 생략 가능
int num = 10;//public static final(상수필드)
void sleep(); //public abstract(추상메소드)
void eat();
=> 인터페이스의 모든 필드들은 암묵적으로 public static final
=> 인터페이스의 모든 메소드들은 암묵적으로 public abstract
}
# Run
package com.kh.chap02_abstractAndInterface.part02_family.run;
import com.kh.chap02_abstractAndInterface.part02_family.model.vo.*;
public class Run {
public static void main(String[] args) {
//Person p = new Person();
//person은 추상클래스이므로 객체생성불가!
1. 다형성적용, 인터페이스적용 전
Person mom = new Mother("엄마", 50, 90, 1);
Person baby = new Baby("응애", 5.3, 90);
System.out.println(mom);
System.out.println(baby);
mom.eat();
baby.eat();
mom.sleep();
baby.sleep();
System.out.println("====다음날====");
System.out.println(mom);
System.out.println(baby);
2. 인터페이스 적용 후
//Basic b = new Basic(); //객체 생성 불가
Basic mom = new Mother("엄마", 50, 90, 1);
Basic baby = new Baby("응애", 5.3, 90);
System.out.println(mom);
System.out.println(baby);
mom.eat();
baby.eat();
mom.sleep();
baby.sleep();
System.out.println("====다음날====");
System.out.println(mom);
System.out.println(baby);
}
}
# Run
package com.kh.run;
import com.kh.controller.A_UncheckedException;
import com.kh.controller.B_CheckedException;
public class ExceptionRun {
> 에러(예외)의 종류
- 시스템 에러 : 컴퓨터의 오작동으로 인해 발생하는 에러
=> (심각) 소스코드로 해결이 안됨
- 컴파일 에러: 프로그램 실행 전 소스코드 상의 문법적인 문제로 발생하는 에러
=> 소스코드 수정으로 해결(빨간줄로 오류 알려줌)
- 런타임 에러: 프로그램 실행 중 발생하는 에러
소스코드 상 문법적인 문제는 없는데 발생
=> 개발자가 예측 가능한 경우 처리를 안했을 때
=> 사용자의 잘못일 가능성도 있음
- 논리 에러 : 소스코드 상 문법적인 문제도 없고, 실행했을 때도 굳이 문제가 발생하진 않지만
프로그램의도상 맞지 않는 것(기회과 설계가 잘못되었을 경우 발생)
* 예외: 시스템에러를 제외한 나머지 컴파일, 런타임, 논리에러와 같이 비교적 덜 심각한 에러들
특히 런타임에러를 주로 예외로 다룬다.
* 예외처리: 예외들이 발생했을 경우에 대비해서 처리하는 방법을 정의해두는 것
> 방법
1. try ~ catch문을 이용
2. throws를 이용(떠넘기기)
public static void main(String[] args) {
//A_UncheckedException a = new A_UncheckedException();
//a.method1();
//a.method2();
//a.method3();
B_CheckedException b = new B_CheckedException();
//b.method2();
b.method1();
}
}
# A_UncheckedException
package com.kh.controller;
import java.util.InputMismatchException;
import java.util.Scanner;
public class A_UncheckedException {
* RuntimeException
: 프로그램 실행 시 발생되는 예외들
* RuntimeException의 자식클래스들
- NullpointerException: 주소값 객체를 참조했더니 null이 들어있을 경우 발생하는 예외
- ArrayIndexOutOfBoundsException: 배열의 부적절한 인덱스로 접근할 때 발생하는 예외
- ClassCastException: 허용할 수 없는 형변환을 진행할 경우 발생하는 예외
- ArithmeticException: 나누기 연산을 0으로 나누면 발생하는 예외
- NagativeArraySizeException: 배열크기를 음수로 지정할 경우 발생하는 예외
.....
* 이러한 RuntimeException과 관련된 예외들의 공통점
=> 개발자가 예측이 가능한 것들이다.
* 굳이 예외처리를 할 필요가 없음 => 조건문으로 해결가능함.
ex) ArithmeticException
public void method1() {
//사용자에게 두 개의 정수값을 입력받아서 나눗셈결과 출력
Scanner sc = new Scanner(System.in);
System.out.println("첫 번째 정수>");
int num1 = sc.nextInt();
System.out.println("두 번째 정수>");
int num2 = sc.nextInt();
sc.nextLine();
방법1. 조건문으로 처리(예외발생을 막음)
: if문으로 조건검사 후에 계산을 진행 => 예외가 안나오도록
if(num2!=0) {
System.out.println("나눗셈 결과: " + (num1/num2));
} else {System.out.println("잘못된 값입니다.");
}System.out.println("종료합니다.");
방법2. 예외처리 구문
: 예외가 발생했을 때 실행할 내용을 정의해두는 것
> try ~ catch 문
[표현법]
try {
//예외가 발생할 법한 구문
(num1/num2)
(ArithmeticException) e
} catch (발생할예외클래스이름 변수명 => 일종의 매개변수) {
//해당 예외가 발생했을 때 실행할 구문
}
try {
System.out.println("나눗셈 결과: "+ (num1/num2));
System.out.println("문제가 발생하지 않았습니다."); //만약 문제 발생 시 이 구문은 무시한 채 바로 catch구문으로 넘어감
} catch(ArithmeticException e) {
//System.out.println("잘못된 값입니다.");
e.printStackTrace();//오류가 발생한 정보 , 오류를 추적할 수 있는 메소드
//현재 오류가 발생한 정보를 볼 수 있고, 어디서 에러가 났는지 나열해줌
//개발단계와 테스트단계에서만 써야 함. 반드시!! 에러문구를 사용자가 보면 안 됨. => 악의적으로 이용당할 수 있음.
}
System.out.println("종료합니다."); //문제를 해결하는 것이 아닌, 문제를 예방
//문제가 발생한 곳에서 프로그램이 종료되는 것이 아닌 문제 발생 시 실행할 구문을 실행하고
//그 다음 구문도 실행해줌.(if문과 try ~ catch구문의 차이점)
}
> 다중 catch문
public void method2() {
* 다중 catch블록
* catch할 예외가 여러개일 경우 주로 사용
Scanner sc = new Scanner(System.in);
System.out.println("정수입력(0제외) > ");
try {
int num = sc.nextInt(); //1. 정수 이외 입력
System.out.println("나눗셈결과: " + (100/num)); //2. 0입력
} catch(InputMismatchException e) { //1. 우선적으로 입력받은게 정수인지 판단
System.out.println("정수를 입력해주세요.");
} catch(ArithmeticException e) { //2. 정수라면 0인지 아닌지 판단
System.out.println("0을 제외하고 입력해주세요.");
}
System.out.println("종료합니다.");
}
public void method3() {
ex) 배열 활용
- ArrayIndexOutOfBoundsException : 배열의 부적절한 인덱스로 접근할 때 발생하는 예외
- NegativeArraySizeException : 배열의 크기를 음수로 지정할 때 발생하는 예외
//사용자로부터 배열의 크기를 입력받아서 배열 만들기
//100번째 인덱스 값을 출력하기
Scanner sc = new Scanner(System.in);
System.out.println("배열의 크기 > ");
try {
int size = sc.nextInt();//1. InputMismatchException
int[] arr = new int[size];//2. NegativeArraySizeException
System.out.println(arr[100]);//3. ArrayIndexOutOfBoundsException
}
//catch(RuntimeException e) { //부모클래스로 포괄적으로 접근
//System.out.println("배열에러");
1. if문 사용 시
if(e instanceof InputMismatchException) {
System.out.println("정수");
} else if(e instanceof NegativeArraySizeException) {
System.out.println("양수");
} else if (e instanceof ArrayIndexOutOfBoundsException ) {
System.out.println("100이상 입력");
} => 너무 귀찮
2. 다중 catch문 사용 시
catch(RuntimeException e) {
System.out.println("배열에러");
}
RuntimeException가 부모 클래스이기 때문에 처리가능
뭉뚱그려서 포괄적인 오류처리만 가능함 => 단점
//System.out.println("배열의 크기가 잘못됐거나, 부적적한 인덱스가 입력됐거나, 정수가 아닌 값이 입력됨..?");
catch(InputMismatchException e) {
System.out.println("정수를 입력해주세요.");
} catch(NegativeArraySizeException e) {
System.out.println("양수를 입력해주세요.");
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("100이상을 입력해주세요.");
}
//=> 다중 catch문 작성 시 범위가 작은 자식타입의 예외클래스부터 기술해야 함. 반대로 적으면 죽은 클래스가 됨.
# B_CheckedException
package com.kh.controller;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
public class B_CheckedException {
> CheckedException
* 문법적으로 반드시 예외처리를 해줘야하는 예외들!
* (예측불가한 곳에서 발생하기 때문에 미리 예외처리 구문을 작성해야함)
=> 주로 외부매체와 어떤 입출력 시 발생
public void method2() throws IOException {
System.out.println("아무 문자열이나 입력해주세요.>");
//Scanner sc = new Scanner(System.in);
//String str = sc.nextLine();
//Scanner와 같이 키보드로 값을 입력받을 수 있는 객체(단. 문자열로만 가능)
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
방법1. try ~ catch구문 사용
try {
String str = br.readLine();//예외에 대한 핸들링을 해줘야 함 (무조건 예외처리를 해줘야 함)
//이 메소드 호출 시 IOException발생할 수도 있음
System.out.println("문자열의 길이: " + str.length());//미리 빨간줄로 알려줌
} catch(IOException e) {
System.out.println("IOException발생하였습니다.");
}
방법2. throws(던짐) : 지금 여기서(method2)에서 말고 현재 이 메소드를 호출한 곳에서 예외를 위임해서 처리하게끔 하겠다.
String str = br.readLine();
System.out.println("문자열 길이: " + str.length());
} //method2 끝
public void method1() {
//method2();//IOException오류위임받음-throws로
try {
method2();
} catch (IOException e) {
System.out.println("예외 발생");
}
}
}
'클라우드 융합 Full-stack 웹 개발자 양성과정 > Java' 카테고리의 다른 글
프로그래밍 언어응용 - IO(Object),Collection(list) (0) | 2022.09.25 |
---|---|
프로그래밍 언어응용 - API(String, Math, Wrapper), IO (1) | 2022.09.25 |
프로그래밍 언어응용-다형성 (1) | 2022.09.25 |
프로그래밍 언어응용-상속 (1) | 2022.09.25 |
프로그래밍 언어응용-객체5 (1) | 2022.09.25 |