danbibibi
article thumbnail
Published 2022. 12. 29. 20:57
[JAVA] 기본 언어/JAVA

1학년 때 JAVA를 처음 배우고, 2학년 이후로는 JAVA를 쓸 일이 거의 없었던 것 같다. (그래도 1학년 때 나름 JAVA 공부 열심히 해뒀음 ㅎ) 현업에서는 JAVA를 많이 사용한다고 하니,,, SSAFY 입과 전에 열심히 복습해 보겠어 😎 (if, for, while 문 같은 내용은 정리하지 않았다! java 적인 것? 위주로 정리했다.)

 

JAVA

  • 객체 지향적 언어 (↔ 절차 지향적 언어)
  • write once run anywhere (동일한 프로그램이 운영체제 가리지 않고 실행)

* WROA - 현대에는 자바뿐만 아니라 대부분의 프로그래밍 언어가 이를 일부분에서 모두 지원

 

객체지향 프로그래밍

  • Object-Oriented Programming
  • 로직을 상태(state)와 행위(behave)로 이루어진 객체로 만드는 것
  • 객체들을 마치 레고 블럭처럼 조립해서 하나의 프로그램을 만드는 것 = 객체지향 프로그래밍
  • 복잡함 속에서 필요한 관점만을 추출하는 행위 = 추상화
  • 부품화 → 효율성 ↑, 문제 발생 원인 파악 및 해결이 쉬워짐 (부품화의 기준은 추상화?!)
  • 부품화보다 중요한 것은 적절함! 그래서 설계가 어려운 것,,
  • 연관된 메소드와 그 메소드가 사용하는 변수들을 분류하고 그룹핑하는 것이 핵심
  • 내부의 동작 방법을 단단한 케이스 안으로 숨기고 사용자에게는 그 부품의 사용방법만을 노출 = 은닉화, 캡슐화
  • 부품들 간의 약속 = 인터페이스

 

환경 마련하기

나는 mac을 사용해서 모두 macOS 용으로 다운 받았다.

 

1. JAVA 설치

다운로드
설치된 jdk 확인

# 설치된 jdk 확인 
cd /Library/Java/JavaVirtualMachines 

# 경로 이동
cd (설치된jdk이름).jdk/Contents/Home

# 반환 받은 경로 복사 
pwd

# bash_profile 파일을 열고 
vi ~/.bash_profile

# JAVA_HOME 지정 후 저장
export JAVA_HOME = /Library/Java/JavaVirtualMachines/jdk1.8.0_351.jdk/Contents/Home

# java 버전 확인
java -version

 

2. Eclipse(IDE) 설치

다운로드

3. Project 생성 → Package 생성 → Class 생성

Hello World 출력하기

* 동작 원리 : 코드 작성(.java) → 컴파일 (.class) → 실행

 

자료형

1. 정수형

 데이터 타입  메모리 크기  표현 가능 범위
 byte  1 byte  -128 ~ 127
 short  2 byte  -32,768 ~ 32,767
 int  4 byte  -2,147,483,648~2,147,483,647
 long  8 byte  -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
int a = 2147483648; // 범위를 벗어나서 오류 발생

long a = 2147483648; // 오류 발생
long a = 2147483648L; // long type 임을 명시 (byte, short의 경우 명시할 필요 x)

 

2. 실수형

 데이터 타입  메모리 크기  표현 가능 범위
 float  4byte  ±(1.40129846432481707e-45 ~ 3.40282346638528860e+38)
 double  8byte  ±(4.94065645841246544e-324d ~ 1.79769313486231570e+308d)
float a = 1.1; // 오류 발생
float a = 1.1F; // float type 임을 명시

double a = 1.1; // 정상 (자바에서 실수형 상수는 double type)

 

3. 문자

 데이터 타입  메모리 크기  표현 가능 범위
 char  2byte  모든 유니코드 문자

 

4. 문자열 - String

String a = "Hello world";
String b = new String("Hello world");

System.out.println(a == b); // false (두 데이터 타입이 동일한 객체인지)
System.out.println(a.equals(b)); // true (문자열 비교 시 .equals를 사용)

 

주석

  • 로직에 대한 설명이나 코드를 비활성화 할 때 사용
  • 프로그래밍적으로 해석되지 않음
// 한줄 주석

/*
여려줄
주석
*/

 

형 변환

1. 자동(암시적) 형 변환

: 표현범위가 좁은 데이터 타입에서 넓은 데이터 타입으로의 변환만 허용

double a = 3.0F; // possible
float a = 3.0; // impossible

 

2. 명시적 형 변환

: 자동 형 변환이 적용되지 않는 경우에는 수동으로 형 변환

// (데이터 type) 데이터 값

float a = 100.0;
int b = 100.0F;

float a = (float)100.0;
int b = (int)100.0F;

 

* 프로모션 캐스팅 - 큰 자료형에 작은 자료형 대입 (자동)

* 디모션 캐스팅 - 작은 자료형에 큰 자료형 대입 (수동)

 

배열

// 배열 선언 및 생성
// 타입[] 배열이름 = new 타입[배열길이] ; 
int[] arr = new int[4];
String[] food = { "마라탕", "닭강정", "김밥" };

// 1과 2의 결과는 같음 !
for (int i = 0; i < food.length; i++) { // 1
	System.out.println(food[i] + "을 추천합니다.");
}

for (String f : food) { // 2 (자바 5.0부터 도입된 기능)
	System.out.println(f + "을 추천합니다.");
}

 

메소드

public class MethodDemo4 {
    public static void counting(int limit) { // method 정의 (반환 값 없음 - void)
        int i = 0;
        while (i++ < limit) { // 1~limit 까치 출력
            System.out.println(i);
        }
    }
 
    public static void main(String[] args) {
        counting(5); // method 호출
    }
}

 

입출력

import java.util.Scanner;

// input
Scanner scan = new Scanner(System.in);
int num = scan.nextInt();

// file 에서 읽기
try {
    File file = new File("out.txt"); // if, 2
    Scanner scan = new Scanner(file);
    while(scan.hasNextInt()) { // 입력값이 생기기 전까지 실행을 유보
        System.out.println(scan.nextInt()*10); // then, 20
    }
    scan.close();
} catch(FileNotFoundException e){
	e.printStackTrace();
}
            

// output
System.out.println(num);

 

클래스, 인스턴스, 객체

클래스

  • 객체를 정의하고 만들어 내기 위한 틀
  • 연관되어 있는 변수와 메소드의 집합 (상태를 나타내는 field와 행동을 나타내는 method로 구성)
  • 클래스 선언 : 접근제어자 class 클래스이름
public class Robot {

    // field (클래스 변수)
    int battery;
    
    // method
    public void increase_battery(){
    	battery++;
    }

    public void decrease_battery(){
    	battery--;
    }
}

 

객체

  • 소프트웨어 세계에 구현할 대상
  • 클래스에 선언된 모양 그대로 생성된 실체
  • 클래스의 인스턴스

 

인스턴스

  • 객체를 소프트웨어에 실체화 한 것
  • 실체화된 인스턴스는 메모리에 할당됨
  • oop의 관점에서 객체가 메모리에 할당되어 실제 사용될 때 '인스턴스'라고 부름
  • 클래스이름 객체참조변수 = new 생성자();

* 생성자 : 클래스와 이름이 같은 특별한 method로, 주로 객체 field 초기화 시 이용!

* this : 클래스를 통해 만들어진 인스턴스 자신을 가리킴

 

//참조 변수 선언과 인스턴스 생성 동시에
Robot r1 = new Robot();

 

클래스 멤버와 인스턴스 멤버

  • 인스턴스 메소드는 클래스 맴버에 접근 할 수 있음 
  • 클래스 메소드는 인스턴스 맴버에 접근 할 수 없음 ( = 존재하지 않는 인스턴스 변수에 접근하는 것)
  • 인스턴스 변수 = Non-Static Field
  • 클래스 변수 = Static Field
class C1{
    static int static_variable = 1;
    int instance_variable = 2;
    static void static_static(){
        System.out.println(static_variable);
    }
    static void static_instance(){
        // 클래스 메소드에서는 인스턴스 변수에 접근 할 수 없음
        //System.out.println(instance_variable);
    }
    void instance_static(){
        // 인스턴스 메소드에서는 클래스 변수에 접근 할 수 있음
        System.out.println(static_variable);
    }
    void instance_instance(){        
        System.out.println(instance_variable);
    }
}

 

생성자

  • 객체를 생성할 때 호출 
  • 값을 반환하지 않는 메소드 (초기화 역할 수행!)
  • 반환 타입이 없지만, void를 사용하지 X
  • 생성자 이름은 클래스 이름과 동일
  • 매개변수가 있는 생성자가 있으면, 기본 생성자를 자동으로 만들어 주지 않음
  • 한 생성자에서 다른 생성자를 호출할 때에는 반드시 해당 생성자의 첫 줄에서만 호출할 수 있음
  • 접근제어자 이름(매개변수){ }

 

상속 

  • 어떤 객체가 있을 때 그 객체의 필드(변수)와 메소드를 다른 객체가 물려 받을 수 있는 기능
  • 기존의 객체를 그대로 유지하면서 기능을 추가하는 방법
  • 객체지향의 재활용성을 극대화시킨 프로그래밍 기법 (but, 객체 지향을 복잡하게 만들기도,,)
  • 코드의 중복 제거로, 유지보수가 편리해짐
  • 상속한 클래스를 다시 상속하는 것도 가능! (다중 상속은 불가능,, 모호성 때문!)
  • 자식클래스 extends 부모클래스
  • super() : 부모 생성자 호출  *super 는 상위 클래스를 가리키는 키워드

* 하위 클래스 생성자에서 super를 사용할 때, super를 제일 먼저 호출  (부모가 초기화되기 전에 자식이 초기화되는 것 방지)

 

class Calculator {
    int num1, num2;
    
    public Calculator(){} // 기본 생성자 (아래 매개변수를 가지는 생성자가 있기 때문에 필요한 경우 추가)
 
    public Calculator(int num1, int num2) {
        this.num1 = num1;
        this.num2 = num2;
    }
 
    public void sum() {
        System.out.println(this.num1 + this.num2);
    }
 
    public void avg() {
        System.out.println((this.num1 + this.num2) / 2);
    }
}
 
class SubstractionableCalculator extends Calculator { 

    // Calculator class를 상속 (기존 Calculator의 변수와 메소드를 가지고 있음)
	
    public SubstractionableCalculator(int num1, int num2) {
        super(num1, num2); // 부모 생성자 호출 
    }
	
    public void substract() { // 추가 메소드(기능) 정의
        System.out.println(this.num1 - this.num2);
    }
}

class MultiplicationableCalculator extends SubstractionableCalculator { // 재 상속도 가능
	
    public MultiplicationableCalculator(int num1, int num2) {
        super(num1, num2); // 부모 생성자 호출 
    }

    public void multiplication() {
        System.out.println(this.num1 * this.num2);
    }
}
 
public class JAVAExample {
 
    public static void main(String[] args) {
        
        // MultiplicationableCalculator는 SubstractionableCalculator클래스를, 
        // SubstractionableCalculator는 Calculator 클래스를 상속 받았으므로
        // sum(), avg(), substract() 메소드 사용이 가능하고, num1, num2 필드를 가짐 !
 
    	MultiplicationableCalculator c1 = new MultiplicationableCalculator(10, 20);
        c1.sum();
        c1.avg();
        c1.substract();
        c1.multiplication();
    }
 
}

 

Overriding, Overloading

Overriding

  • 하위 클래스에서 메소드를 재정의해서 사용하는 방식
  • 기본동작은 폭넓게 적용되고, 예외적인 동작은 더 높은 우선순위를 가짐
  • overriding을 하기 위해서는 메소드 이름, 매개변수 숫자/타입/순서, 리턴 타입이 같아야 함

* SubstractionableCalculator 클래스에 sum()을 오버라이딩하면 아래와 같다.

class Calculator {
    int num1, num2;
    
    public Calculator(){} // 기본 생성자 (아래 매개변수를 가지는 생성자가 있기 때문에 필요한 경우 추가)
 
    public Calculator(int num1, int num2) {
        this.num1 = num1;
        this.num2 = num2;
    }
 
    public void sum() {
        System.out.println(this.num1 + this.num2);
    }
 
    public void avg() {
        System.out.println((this.num1 + this.num2) / 2);
    }
}
 
class SubstractionableCalculator extends Calculator { 

    // Calculator class를 상속 (기존 Calculator의 변수와 메소드를 가지고 있음)
	
    public SubstractionableCalculator(int num1, int num2) {
        super(num1, num2); // 부모 생성자 호출 
    }
    
    public void sum() { // 메소드 오버라이딩 !!!!!
        System.out.println("실행 결과는 " + (this.num1 + this.num2) + "입니다.");
    }
	
    public void substract() { // 추가 메소드(기능) 정의
        System.out.println(this.num1 - this.num2);
    }
}

class MultiplicationableCalculator extends SubstractionableCalculator { // 재 상속도 가능
	
    public MultiplicationableCalculator(int num1, int num2) {
        super(num1, num2); // 부모 생성자 호출 
    }

    public void multiplication() {
        System.out.println(this.num1 * this.num2);
    }
}
 
public class JAVAExample {
 
    public static void main(String[] args) {
        
        // MultiplicationableCalculator는 SubstractionableCalculator클래스를, 
        // SubstractionableCalculator는 Calculator 클래스를 상속 받았으므로
        // sum(), avg(), substract() 메소드 사용이 가능하고, num1, num2 필드를 가짐 !
 
    	MultiplicationableCalculator c1 = new MultiplicationableCalculator(10, 20);
        c1.sum();
        c1.avg();
        c1.substract();
        c1.multiplication();
    }
 
}

 

Overloading

  • 매개변수의 개수나 타입을 다르게 하여, 같은 이름의 메소드를 중복 정의하는 것
  • 매개변수가 다르면 이름이 같아도 서로 다른 메소드가 되는 것 !!!
  • 상속 관계에서도 오버로딩 사용 가능
  • 메소드의 반환값은 메소드 호출 시점에 전달되지 않는 정보이기 때문에 오버로딩 대상이 될 수 없음
public class OverloadingDemo {
    void A (){System.out.println("void A()");} // 모두 
    void A (int arg1){System.out.println("void A (int arg1)");} // 다른
    void A (String arg1){System.out.println("void A (String arg1)");} // 메소드 !!

    public static void main(String[] args) {
        OverloadingDemo od = new OverloadingDemo();
        od.A();
        od.A(1);
        od.A("Hi there !");
    }
}

 

패키지

  • 클래스들의 모음집, 클래스명의 고유성을 보장하기 위해 사용
  • 패키지를 통해서 라이브러리 간 구분 가능

* 여러 패키지 선언 시, 같은 클래스가 있는 경우 다음과 같이 객체를 생성해야 함

package org.opentutorials.javatutorials.packages.example3;
import org.opentutorials.javatutorials.packages.example1.*; // example1 내부에 class를 사용하고 싶은 경우 import
import org.opentutorials.javatutorials.packages.example2.*;
 
public class D {
    public static void main(String[] args) { // example1 / example3 에 B 클래스 이름이 중복
        org.opentutorials.javatutorials.packages.example2.B b = new org.opentutorials.javatutorials.packages.example2.B();
    }
}

 

접근 제어자

: 클래스의 멤버인 변수와 메소드들의 접근 권한을 지정하는 역할

 

클래스 멤버 정의에 사용하는 접근자

 제한자  클래스 내부  패키지  상속받은 클래스  이외의 영역
 private  O  X  X  X
 default  O  O  X  X
 protected  O  O  O  X
 public  O  O  O  O

 

클래스 정의에 사용하는 접근자

제한자 의미
 default (지정 x)  같은 패키지에서만 사용 가능
 public  다른 패키지에서도 사용 가능

 

* public 클래스가 포함된 소소코드는 public 클래스의 클래스 명과 소스코드의 파일명이 같아야 함

* 하나의 소스 코드에는 하나의 public 클래스가 존재

 

추상 메소드 (abstract)

  • 메소드의 시그니처만이 정의된 비어있는 메소드
  • 구체적인 구현은 하위 클래스에서 오버라이딩 해야 함 (상속을 강제하기 위한 것)
  • (추상 클래스는 구체적인 메소드의 내용이 존재하지 않기 때문에 인스턴스화시켜서 사용할 수 없음)
  • 추상 메소드를 하나라도 포함하고 있는 클래스는 추상 클래스가 됨
  • 공통되는 부분을 상위 클래스에 두어서 코드의 중복, 유지보수의 편의성 등을 꾀할 수 있음
abstract class A{
    
    public abstract int b(); 
    
    //본체가 있는 메소드는 abstract 키워드를 가질 수 없음
    //public abstract int c(){System.out.println("Hello")}
    
    //추상 클래스 내에는 추상 메소드가 아닌 메소드가 존재 할 수 있음
    public void d(){ 
        System.out.println("world");
    }
    
}

class B extends A{ // class A 상속
    public int b(){return 1;} // 추상 메소드 오버라이드
}

public class AbstractDemo {
    public static void main(String[] args) {
        B obj = new B();
        System.out.println(obj.b());
    }
}

 

final

  • 상속/변경을 금지하는 규제
  • fianl 필드(변경 불가능), 메소드(오버라이딩 불가능), 클래스(상속 불가능) 

 

인터페이스 (interface)

  • 어떤 객체가 특정 인터페이스를 사용한다면 그 객체는 반드시 인터페이스의  메소드들을 구현해야 함
  • 하위 클래스에 특정한 메소드가 반드시 존재하도록 강제
  • 협업 시 편의성 증가 (규약을 미리 정하기 때문)
  • 하나의 클래스가 여러 개의 인터페이스를 구현할 수 있음
  • 상속이 가능함
  • 인터페이스의 멤버는 반드시 public (구현하여 사용하므로)
  •  public을 생략하면 접근 제어자 default가 되는 것이 아니라 public이 됨
  • interface 인터페이스이름
  • 하위클래스 implements 상위클래스
interface I{ // 인터페이스
    public void z();
    // private void x(); // error. 인터페이스의 맴버는 반드시 public
}
 
class A implements I{ // 클래스 A는 인터페이스 I를 '구현' 
    public void z(){} // 없으면 컴파일 에러 발생
}

 

interface I1{
    public void x();
}

interface I2{
    public void z();
}

class B implements I1, I2{ // 하나의 클래스가 여러개의 인터페이스를 구현 할 수 있음
    public void x(){}
    public void z(){}   
}

 

interface I3{
    public void x();
}
 
interface I4 extends I3{ // 인터페이스 상속
    public void z();
}
 
class B implements I4{
    public void x(){}
    public void z(){}   
}

 

* abstract vs interface

- interface는 class가 아닌 고유한 형태를 가지고 있는 반면, 추상 클래스는 일반적인 클래스 임

- interface는 구체적인 로직이나 상태를 가지고 있을 수 없고, 추상 클래스는 구체적인 로직이나 상태를 가지고 있음

- 추상 클래스의 목적 : 상속 받아서 기능을 이용하고, 확장

- interface의 목적 : 함수의 구현을 강제해서, 구현 객체의 같은 동작을 보장

 

다형성 (Polymorphism)

  • 하나의 메소드나 클래스가 있을 때 이것들이 다양한 방법으로 동작하는 것
  • 동일한 조작방법으로 동작시키지만 동작방법은 다른 것 ! ex) ESC(취소), ENTER(실행) / 공통 : 키보드를 누름
  • 오버로딩은 다형성의 한 예 !

클래스와 다형성

  • 클래스 B를 클래스 A의 데이터 타입으로 인스턴스화 했을 때 클래스 A에 존재하는 맴버만이 클래스 B의 맴버가 됨
  • 클래스 B에서 오버라이딩한 맴버의 동작방식은 그대로 유지

=  상속 오버라이딩 그리고 형변환을 이용한 다형성

 

class A{
    public String x(){return "x";}
}

class B extends A{
    public String y(){return "y";}
}

public class PolymorphismDemo1 {
    public static void main(String[] args) {
        A obj = new B();
        obj.x();
        // obj.y(); // 실행 불가 (클래스 B는 마치 클래스 A인것처럼 동작)
    }
}

 

class A{
    public String x(){return "A.x";}
}

class B extends A{
    public String x(){return "B.x";} // 메소드 오버라이딩
    public String y(){return "y";}
}

public class PolymorphismDemo1 {
    public static void main(String[] args) {
        A obj = new B();
        System.out.println(obj.x()); // B.x 출력
    }
}

 

인터페이스와 다형성

  • 특정 인터페이스를 구현하고 있는 클래스의 데이터 타입으로 인터페이스를 지정 할 수 있음
  • 다중 상속이 지원되는 인터페이스의 특징과 결합해서 상속과는 다른 양상의 효과를 만들어 냄
interface I{}

class C implements I{}

public class PolymorphismDemo {
    public static void main(String[] args) {
        I obj = new C(); // 클래스 C의 데이터 타입으로 인터페이스 I가 될 수 있음
    }
}

 

interface I2{
    public String A();
}

interface I3{
    public String B();
}

class D implements I2, I3{
    public String A(){
        return "A";
    }
    public String B(){
        return "B";
    }
}

public class PolymorphismDemo {
    public static void main(String[] args) {
        D obj = new D();
        I2 objI2 = new D();
        I3 objI3 = new D();
         
        obj.A();
        obj.B();
         
        objI2.A();
        //objI2.B(); // 오류 발생 (objI2의 데이터 타입이 인터페이스 I2이기 때문)
        //  objI2의 데이터 타입을 I2로 한다는 것
        // = 인스턴스를 외부에서 제어할 수 있는 조작 장치를 인스턴스 I2의 맴버로 제한한다는 의미
         
        //objI3.A(); // 오류 발생
        objI3.B();
    }
}

 

예외

try ... catch

  • 프로그래밍을 하면 많은 오류 상황에 직면
  • 오류를 잘 처리하기 위한 방법들이 필요!
  • e.getMessage() : 오류에 대한 기본적인 내용을 출력 (상세 x)
  • e.toString() : 조금 더 자세한 정보 제공
  • e.printStackTrace() : 리턴 값 x , 메소드가 내부적으로 예외 결과를 화면에 출력 (가장 상세함)
try { //  예외 발생이 예상되는 로직
	div = a/b;
} catch(Exception e){ // 예외클래스 인스턴스
	// e.getMessage() : 오류의 원인을 사람이 이해하기 쉬운 형태로 리턴
	System.out.println("오류 발생 : "+e.getMessage()); // 예외가 발생했을 때 실행되는 로직
}

 

// 다중 catch 도 가능 !
try {
	System.out.println(arr[first] / arr[second]);
} catch(ArrayIndexOutOfBoundsException e){
	System.out.println("ArrayIndexOutOfBoundsException");
} catch(ArithmeticException e){
	System.out.println("ArithmeticException");
} catch(Exception e){ // ArrayIndexOutOfBoundsException, ArithemeticException 보다 포괄적인 예외 (뒤에 작성해야 함!)
	System.out.println("Exception");
}

 

finally

  • 예외 여부와 관계없이 실행되는 로직
  • 예외와는 상관없이 반드시 끝내줘야 하는 작업이 있는 경우 사용
try {
    System.out.println(arr[first] / arr[second]);
} catch(ArrayIndexOutOfBoundsException e){
    System.out.println("ArrayIndexOutOfBoundsException");
} catch(ArithmeticException e){
    System.out.println("ArithmeticException");
} catch(Exception e){
    System.out.println("Exception");
} finally {
    System.out.println("finally");
}

 

throw와 throws

  • 예외 처리를 사용자에게 넘기는 방법
  • API 측에서 예외를 던지고 처리할 때 유용
  • throw : Exception을 발생시킬 때 사용하는 키워드
  • throws : 메소드에서 발생할 수 있는 Exception을 명시적으로 정의할 때 사용

 

class B{
    void run() throws IOException, FileNotFoundException{ // B.run -> C.run
        BufferedReader bReader = null;
        String input = null;
        bReader = new BufferedReader(new FileReader("out.txt"));
        input = bReader.readLine();
        System.out.println(input);
    }
}
class C{
    void run() throws IOException, FileNotFoundException{ // C.run -> main
        B b = new B();
        b.run();
    }
}
public class ThrowExceptionDemo {
    public static void main(String[] args) {
         C c = new C();
         try { // 예외처리
            c.run();
        } catch (FileNotFoundException e) {
            System.out.println("out.txt 파일은 설정 파일 입니다. 이 파일이 프로잭트 루트 디렉토리에 존재해야 합니다.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }   
}

 

class Calculator{
    int left, right;
    public void setOprands(int left, int right){        
        this.left = left;
        this.right = right;
    }
    public void divide(){
        if(this.right == 0){
            throw new ArithmeticException("0으로 나누는 것은 허용되지 않습니다."); // 예외를 발생시킴
        }
        try {
            System.out.print("계산결과는 ");
            System.out.print(this.left/this.right);
            System.out.print(" 입니다.");
        } catch(Exception e){
            System.out.println("\n\ne.getMessage()\n"+e.getMessage());
            System.out.println("\n\ne.toString()\n"+e.toString());
            System.out.println("\n\ne.printStackTrace()");
            e.printStackTrace();
        }
    }
}

 

* 기억할만한 주요 Exception

예외 사용해야 할 상황
IllegalArgumentException 매개변수가 의도하지 않은 상황을 유발시킬 때
IllegalStateException 메소드를 호출하기 위한 상태가 아닐 때
NullPointerException 매개 변수 값이 null 일 때
IndexOutOfBoundsException 인덱스 매개 변수 값이 범위를 벗어날 때
ArithmeticException 산술적인 연산에 오류가 있을 때

 

* IOException은 예외처리를 강제함

  • checked 예외 - RuntimeException을 제외한 Exception의 하위 클래스 (반드시 예외처리 필요)
  • unchekced 예외 - RuntimeException의 하위 클래스 (예외처리를 해도되고, 안 해도 됨)
package org.opentutorials.javatutorials.exception;
import java.io.IOException;
class E{
    void throwArithmeticException(){
        throw new ArithmeticException();
    }
    void throwIOException1(){
        try {
            throw new IOException(); // try ... catch가 없는 경우, 에러 발생
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    void throwIOException2() throws IOException{
        throw new IOException();
    }
}

 

나만의 예외 만들기

  • API 쪽에서 예외를 던졌을 때 API 사용자 쪽에서 예외 상황을 복구 할 수 있다면 checked 예외를 사용
  • checked 예외를 너무 자주 사용하면 API 사용자를 힘들게 할 수 있기 때문에 적정선을 찾는 것이 중요
  • 그냥 프로그램을 종료하는 것이 덜 위험 할 때 unchecked를 사용
class DivideException extends RuntimeException { // 예외 만들기 (unchecked) 
    DivideException(){
        super();
    }
    DivideException(String message){
        super(message);
    }
}

class Calculator{
    int left, right;
    public void setOprands(int left, int right){        
        this.left = left;
        this.right = right;
    }
    public void divide(){
        if(this.right == 0){
            throw new DivideException("0으로 나누는 것은 허용되지 않습니다."); // 예외 던지기
        }
        System.out.print(this.left/this.right);
    }
}

 

class DivideException extends Exception { // 예외 만들기 (checked)
    DivideException(){
        super();
    }
    DivideException(String message){
        super(message);
    }
}

// 방법 1 (예외처리)
class Calculator{
    int left, right;
    public void setOprands(int left, int right){        
        this.left = left;
        this.right = right;
    }
    public void divide(){
        if(this.right == 0){
            try { // 예외처리
                throw new DivideException("0으로 나누는 것은 허용되지 않습니다.");
            } catch (DivideException e) {
                e.printStackTrace();
            }
        }
        System.out.print(this.left/this.right);
    }
}


// 방법 2 (사용자에게 예외를 던짐)
class Calculator{
    int left, right;
    public void setOprands(int left, int right){        
        this.left = left;
        this.right = right;
    }
    public void divide() throws DivideException{ // 사용자에게 예외를 던짐
        if(this.right == 0){
            throw new DivideException("0으로 나누는 것은 허용되지 않습니다.");
        }
        System.out.print(this.left/this.right);
    }
}

public class CalculatorDemo {
    public static void main(String[] args) {
        Calculator c1 = new Calculator();
        c1.setOprands(10, 0);
        try { // 사용자가 예외처리
            c1.divide();
        } catch (DivideException e) {
            e.printStackTrace();
        }
    }
}

 

 

참고

생활코딩 JAVA

 

언어소개 - 생활코딩

Java의 역사 1995년 자바의 아버지라고 불리는 제임스 고슬링과 그의 동료들에 의해서 시작된 프로젝트다. Java는 원래 가전제품을 제어하기 위한 언어로 고안되었지만 웹의 등장으로 엄청난 성공

opentutorials.org

 

profile

danbibibi

@danbibibi

꿈을 꾸는 시간은 멈춰 있는 것이 아냐 두려워하지 마 멈추지 마 푸른 꿈속으로