티스토리 뷰

1.    인터페이스  - 디폴트 메소드

-      인터페이스만으로는 사용이 불가능하다.

-      Why? 디폴트 메소드는 인스턴스 메소드로, 구현 객체가 인터페이스에 대입되어야 호출할 수 있기 때문이다.

-      모든 구현 객체가 가지고 있는 기본 메소드로 사용되지만, 필요에 따라서 재정의가 가능하다.

-      인터페이스의 모든 멤버는 public이다.

 

2.    다형성

-      하나의 타입에 여러 가지 객체를 대입해 다양한 실행 결과를 얻는 것이다.

-      자동 타입 변환 ( Promotion ) : 인터페이스( 부모 ) 변수 = 구현( 자식 )객체 ;

-      Ex. A a1 = new b ; ( 부모인 A타입의 a라는 변수에 자식객체인 b를 넣은 것이다. )

-      자동형변환은 데이터 유실의 위험성이 없다.

-      필드의 다형성 : 다형성은 객체를 부품화시킨다.

-      Ex. 타이어 인터페이스를 만들어서 타이어의 규격을 정한 후, 규격에 맞는 다양한 타이어를 구현한다.

 

3.    인터페이스 상속

-      Public interface 하위인터페이스 extends 상위인터페이스1, 상위인터페이스2 { … }

-      다중인터페이스( implements )는 클래스에서 사용하고, 인터페이스의 상속( extends )은 인터페이스에서 사용한다.

-      하위 인터페이스는 상위 인터페이스의 규격을 모두 지켜야 한다.

-      하위 인터페이스 구현 클래스는 다음과 같은 메소드를 모두 재정의 해야 한다.

-      1. 하위 인터페이스의 추상 메소드 2. 상위 인터페이스1의 추상 메소드 3. 상위 인터페이스2의 추상 메소드

 

4.    예외( Exception ) 처리

-      자바에서는 컴파일할 때나 런타임에서 나타나는 오류를 예외라고 부른다.

-      오류의 종류 :

-      1 ) 에러 ( Error ) : 하드웨어의 잘못된 동작 또는 고장으로 인한 오류

-      2 ) 예외 ( Exception ) : 사용자의 잘못된 조작 또는 개발자의 잘못된 코딩으로 인한 오류

-       + 에러는 정상실행 상태로 돌아갈 수 없지만, 예외는 예외 처리 추가하면 정상실행 상태로 돌아갈 수 있다.

-      예외의 종류 :

-      1 ) 일반( 컴파일 체크 ) 예외 [ checked exception ] : 예외처리 코드가 없으면 컴파일 오류 발생

-      2 ) 실행 예외 ( Runtime Exception ) : 예외 처리 코드를 생략하더라도 컴파일이 되는 예외

-      예외 클래스의 상위 클래스 : Throwable - > java.lang.Exception

 

5.    실행 예외 ( Runtime Exception )

-      NullPointerException ( 객체 참조가 없는 상태 ) : 객체를 가지고 있지 않은데, 객체를 가지고 있는 것처럼 실행할 때 나타나는 예외

-      ArrayIndexOutOfBoundException : 배열의 인덱스 범위를 초과해서 사용할 경우 발생

-      ClassCastException : 타입 변환이 되지 않을 경우 발생하는 실행예외이다.

 

6.    예외 처리 코드 ( try – catch – finally )

-      예외 발생시 프로그램의 종료를 막고, 정상적으로 실행할 수 있도록 처리해준다!

-      일반 예외(checked exception)에서는 반드시 작성해야 컴파일이 가능하고, 실행 예외에서는 컴파일러가 체크하지 않기에 개발자 경험에 의해서 작성해야 한다.

-      Try – catch – finally 블록을 이용해 예외 처리 코드를 작성해야 한다.

-      Try { } catch (예외클래스 e) { } finally { }로 구성되어 있으며,

-      Try { } 블록 내에서는 예외 발생 가능 코드를 작성하고

-      Catch (예외클래스 e) { } 블록 내에서는 예외를 잡는 블록으로, 예외 처리를 어떻게 할지 대안 로직 코드를 작성하게 된다.

-      (예외클래스 e)에서는 import문을 사용해야 한다.

-      만약 예외가 발생하지 않으면 catch 블록을 스킵된다.

-      그러나 try블록은 예외가 발생하든 발생하지 않든 무조건 실행된다.

-      Finally 블록도 물론 항상 실행된다.

 

7.    .parsexxx(String number)

-      사용자가 입력한 문자열을 지정된 타입에 맞게 변환시켜준다.

-      기본정수타입 - - - > Wrapper Type.parsexxx(String number) :

-      byte - - - > Byte

-      short - - - > Short

-      char - - - > Character. parsexxx

-      int - - - > Integer.parseInt(String number)

-      long - - - > Long.parseLong(…)

-      기본실수타입 - - - > Wrapper Type.parsexxx(String number) :

-      float - - - > Float

-      double - - - > Double

-      기본논리타입 - - - > Wrapper Type.parsexxx(String number) :

-      boolean - - - > Boolean


01. 인터페이스 - 디폴트 메소드

 

package Interface06;

 

public interface RemoteControl { // 디폴트 메소드와 정적 메소드의 오버라이드 ( 재정의 )

      

       public static final int MAX_VOLUME = 10;

       public static final int MIN_VOLUME = 0;

 

       public abstract void turnOn();

       public abstract void turnOff();

       public abstract void setVolume(int volume);

      

 

       // 디폴트 메소드

       public default void setMute(boolean mute) {

             if(mute) {

                    System.out.println("무음 처리합니다.");

             } else {

                    System.out.println("무음을 해제합니다.");

             } // if - else

       } // default method - setMute

      

       public static void changeBattery() {

            

             System.out.println("건전지를 교환합니다.");

            

       }// changeBattery

 

} // end class


package Interface06;

 

import lombok.ToString;

 

@ToString

public class Audio implements RemoteControl {

      

       // 1. 인스턴스 필드

       private int volume;

      

      

//     -------------------- 인터페이스의 규격을 구현 ( 추상메소드 재정의 ) -----------------------

      

       // 2. 추상 메소드의 실체 메소드

      

       @Override // 오버라이딩을 할 때에는 반드시 @Override를 작성하자

       public void turnOn() {

             System.out.println("Audio를 켭니다.");

       } // turnOn

      

       @Override

       public void turnOff() {

             System.out.println("Audio를 끕니다.");

       } // turnOff

      

       @Override

       public void setVolume ( int volume ) {

             if ( volume > RemoteControl.MAX_VOLUME) {

                    this.volume = RemoteControl.MAX_VOLUME;

             } else if ( volume < RemoteControl.MIN_VOLUME) {

                    this.volume = RemoteControl.MIN_VOLUME;

             } else {

                    this.volume = volume;

             } // if - else if - else

            

             System.out.println("현재 Audio 볼륨 : " + volume );

            

       }

      

//     -------------------- 디폴트 ( default ) 메소드 재정의  -----------------------

 

       @Override

       public void setMute(boolean mute) {

             System.out.println("Audio::setMute invoked.");

       } // setVolume

      

       // 디폴트 메소드는 인터페이스에서 선언할때 default를 작성하라는 것이지 오버라이드할 때에도 작성하면 안된다.

       // 오버라이드할 때에는 default를 삭제하도록 하자!!

      

      

//     -------------------- 정적 ( static ) 메소드 재정의 - 불가능 -----------------------

      

//     @Override // xx!

//     public static void changeBattery() {

//          

//           System.out.println("건전지를 교환합니다.");

//          

//     }// changeBattery

      

       // 정적 메소드의 오버라이딩이란 개념은 없다!! 모든 정적멤버는 그 소속이 clazz이기 때문에 오버라이드가 불가능하다!!

      

} // end class


package Interface06;

 

public class Television implements RemoteControl {

      

       // 1. 인스턴스 필드

       private int volume;

      

      

//     -------------------- 인터페이스의 규격을 구현 ( 재정의 ) -----------------------

      

       // 2. 추상 메소드의 실체 메소드

      

       @Override

       public void turnOn() {

             System.out.println("TV를 켭니다.");

       } // turnOn

      

       @Override

       public void turnOff() {

             System.out.println("TV를 끕니다.");

       } // turnOff

      

       @Override

       public void setVolume ( int volume ) {

             if ( volume > RemoteControl.MAX_VOLUME) {

                    this.volume = RemoteControl.MAX_VOLUME;

             } else if ( volume < RemoteControl.MIN_VOLUME) {

                    this.volume = RemoteControl.MIN_VOLUME;

             } else {

                    this.volume = volume;

             } // if - else if - else

            

             System.out.println("현재 TV 볼륨 : " + volume );

            

       } // setVolume

      

//     -------------------- 디폴트 ( default ) 메소드 재정의  -----------------------

      

       @Override

       public void setMute(boolean mute) {

             System.out.println("Television::setMute invoked.");

       } // set Mute

      

} // end class


package Interface06;

 

 

//클래스나 패키지를 복사하게 되다보면, 실행 클래스에서 이름 충돌이 날 수 있는데, 그때는 import문을 수정해주자! 

 

public class RemotecontrolExample {

      

       public static void main(String [] args) {

            

             RemoteControl rc = null;

            

             rc = new Television();

             rc.setMute(true); // 출력 : Television::setMute invoked.

             System.out.println("rc1 : " + rc);

            

             rc.turnOn();

             rc.turnOff();

            

             rc = new Audio();

             rc.setMute(true); // 출력 : Audio::setMute invoked.

             System.out.println("rc2 : " + rc);

            

             rc.turnOn();

             rc.turnOff();

            

       } // main

 

} // end class

 

02. 인터페이스의 상속

 

package Interface07;

 

public interface InterfaceA {

      

       public abstract void methodA();

 

} // end interface


package Interface07;

 

public interface InterfaceB {

      

       public abstract void methodB();

 

} // end interface


package Interface07;

 

public interface InterfaceC extends InterfaceA, InterfaceB { // 인터페이스의 상속

      

       public abstract void methodC();

 

} // end interface


package Interface07;

 

public class ImplementationC implements InterfaceC {

       // InterfaceC가 A와 B 모두 상속받았기 때문에, 구현 클래스는 A B C 규격 모두 지켜야 한다. (***)

 

       @Override

       public void methodA() {

             System.out.println("ImplementationC::methodA() invoked.");

       } // methodA

 

       @Override

       public void methodB() {

             System.out.println("ImplementationC::methodB() invoked.");

       } // methodB

 

       @Override

       public void methodC() {

             System.out.println("ImplementationC::methodC() invoked.");

       } // methodC

 

} // end class


package Interface07;

 

public class Example {

      

       public static void main(String [] args ) {

            

             ImplementationC impl = new ImplementationC(); // 구현 객체 생성

            

             InterfaceA ia = impl; // 상위 인터페이스에 하위 인터페이스의 구현 객체를 받음

             ia.methodA();

             System.out.println();

            

//           ===================================================================

            

             InterfaceB ib = impl;

             ib.methodB();

             System.out.println();

            

//           ===================================================================

            

             InterfaceC ic = impl; // 인터페이스C는 A와 B모두 상속받았기 때문에 메소드 a b c 모두 사용이 가능하다.

             ic.methodA();

             ic.methodB();

             ic.methodC();

            

       } // main

 

} // end class

 

03. 다형성 1 - 추상메소드 오버라이드

 

package PracticePolymorphism03;

 

 

public interface Tire { // 다양성 - 추상메소드 오버라이드

      

       // + 규격을 정할 때에는 추상 메소드!!

       public abstract void roll(); // 규격

 

} // end interface


package PracticePolymorphism03;

 

public class HankookTire implements Tire {

      

      

       @Override

       public void roll() {

             System.out.println("HankookTire::roll() invoked.");

       } // roll

      

       // 추상메소드는 규격의 역할을 하기에, 만약 이러한 규격을 어기면 오류가 발생하게 된다.

       // 오류를 막기 위해서는 추상메소드를 지키거나 추상 클래스가 되는 수밖에는 없다.

 

} // end class


package PracticePolymorphism03;

 

public class KumhoTire implements Tire {

      

       @Override

       public void roll() {

             System.out.println("KumhoTire::roll() invoked.");

       } // roll

      

       // 추상메소드도 디폴트와 같이 인터페이스에서만 abstract를 붙이지,

       // 오버라이드할 때에는 abstract를 붙이지 않아야 한다!!

 

} // end class


package PracticePolymorphism03;

 

 

// 다형성 1에 의거해서 구현객체(자식객체)를 넣어준다.

public class Car {

      

       // Lvalue : 부모타입             Rvalue : 자식타입

       // 아래는 모두 다형성1로 필드 초기화 ( , 부품 장착 )

      

       Tire frontLeftTire = new HankookTire();

       Tire frontRightTire = new HankookTire();

       Tire backLeftTire = new HankookTire();

       Tire backRightTire = new HankookTire();

      

       void run() {

            

             // 다형성2 발현 : 부모타입의 필드의 메소드 호출 (roll) - >

             // 다형성 1에 의해 대입된 자식(구현)객체의 재정의된 메소드가 호출

            

             frontLeftTire.roll();

             frontRightTire.roll();

             backLeftTire.roll();

             backRightTire.roll();

            

       } // run

      

 

} // end class


package PracticePolymorphism03;

 

public class CarExample {

      

       public static void main (String [] args ) {

            

             Car myCar = new Car();

            

             myCar.run();

            

//           ===============================================

            

             // 부품교환

             myCar.frontLeftTire = new KumhoTire();

             myCar.frontRightTire = new KumhoTire();

            

//           ===============================================

            

             myCar.run();

            

//           ===============================================

            

             // 출력 : 바퀴가 4개이기에 4번씩 출력되는 것이며, 앞의 2개의 바퀴는 금호로 바뀌었기에 아래와 같이 출력된다.

            

//           HankookTire::roll() invoked.

//           HankookTire::roll() invoked.

//           HankookTire::roll() invoked.

//           HankookTire::roll() invoked.

//           KumhoTire::roll() invoked.

//           KumhoTire::roll() invoked.

//           HankookTire::roll() invoked.

//           HankookTire::roll() invoked.

            

       } // main

 

} // end class

 

04. 다형성 2 - 추상메소드 오버라이드 2

 

package PracticePolymorphism04;

 

public interface Vehicle {

      

       public abstract void run();

 

} // end interface


package PracticePolymorphism04;

 

public class Taxi implements Vehicle {

 

       @Override

       public void run() {

             System.out.println("Taxi::run() invoked.");

             System.out.println("택시가 달립니다.");

       } // run

 

} // end class


package PracticePolymorphism04;

 

public class Bus implements Vehicle {

 

       @Override

       public void run() {

             System.out.println("Bus::run() invoked.");

             System.out.println("버스가 달립니다.");

       } // run

 

} // end class


package PracticePolymorphism04;

 

public class Driver {

      

       public void drive ( Vehicle vehicle ) { // 어떤 차를 몰지 선택하게 하였다.

             vehicle.run();

       } // drive

 

} // end class


package PracticePolymorphism04;

 

public class DriverExample {

      

       public static void main (String[] args) {

            

             Driver driver = new Driver(); // 객체 생성 ( 다형성 x )

            

             Bus bus = new Bus();

             Taxi taxi = new Taxi();

            

//           ================================================

            

             driver.drive(bus);

             driver.drive(taxi);

            

             // 출력 :

//           Bus::run() invoked.

//           버스가 달립니다.

//           Taxi::run() invoked.

//           택시가 달립니다.

            

       } // main

 

} // end class

 

05. 다형성 3 - 강제형변환

 

package PracticePolymorphism05;

 

public interface Vehicle {

      

       public abstract void run();

 

} // end interface


package PracticePolymorphism05;

 

public class Bus implements Vehicle{

      

       @Override

       public void run() {

             System.out.println("Bus::run() invoked.");

       } // run

 

       public void checkFare() {

             System.out.println("Bus::checkFare invoked.");

       } // checkFare

 

} // end class


package PracticePolymorphism05;

 

public class VehicleExample {

      

       public static void main(String [] args) {

            

             Vehicle vehicle = new Bus(); // 다형성 1

            

             vehicle.run(); // 다형성 2

//           vehicle.checkFare(); // 컴파일 오류발생

             // why? 겉이 부모타입으로 되어있기에 부모타입에 선언된 멤버만 사용이 가능하다!!! (***)

            

//           ==========================================

            

//           Bus bus = (Bus) vehicle; // 강제타입변환 - 안전하지 않은 버전

            

             if( vehicle instanceof Bus bus ) { // 안전하게 강제형변환 할 수 있다.

                   

                    bus.run(); // 다형성2는 아니다. 단순히 자식객체로 불러온 것이다.

                    bus.checkFare();

                   

             } // if

            

       } // main

 

} // end class

 

06. 실행예외 1 - ArrayIndexOutOfBoundsException

 

package RuntimeException;

 

import java.util.Arrays;

 

public class ArrayIndexOutOfBoundsExceptionExample { // 배열의 원소의 개수보다 초과할 때 나타난다.

 

      

       public static void main (String [] args) { // 메인 메소드는 JVM의 메인 쓰레드가 구동한다.

            

             // main called by JVM "main" thread

             // main static이기에 클래스 명.main으로 부른다.

             // ex. ArrayIndexOutOfBoundsExceptionExample.main

            

             System.out.println(Arrays.toString(args)); // 출력 : [1, 2, 34, 5, 6, 7, 8, 9, 10]

            

             // main에 있는 문자열타입의 배열 args에 값을 넣는 방법은 런버튼에 있는

             // Run Configurations에 있는 알규먼트 탭에서 값을 넣을 수 있다.

             // 프로그램 알규먼트에서 값을 넣어야 한다.

            

             if(args.length == 2 ) { // 문자열을 원소로 갖는 배열 args의 원소가 2개라면...

                   

                    String data1 = args[0];

                    String data2 = args[1];

                   

                    System.out.println("args[0] : " + data1);

                    System.out.println("args[1] : " + data2);

                   

             } else { // 배열 args의 원소의 개수가 2개가 아니라면...

                   

                    System.out.println(" [ 실행 방법 ] ");

                    System.out.print("java ArrayIndexOutOfBoundsExceptionExample.");

                    System.out.print("1 2");

                   

             } // if-else

            

       } // main

 

} // end class

 

07. 실행예외 2 - ClassCastException

 

package RuntimeException;

 

public class ClassCastExceptionExample {

      

       public static void main (String [] args) {

            

             Dog dog = new Dog(); // Dog 객체 생성

             changeDog(dog); // 메소드 호출 ( 자식객체)

            

             Cat cat = new Cat(); // Cat 객체 생성

             changeDog(cat); // 메소드 호출 ( 자식객체 )

            

       } // main

      

       // 매개변수의 타입이 상속관계에서 부모타입으로 선언

      

       public static void changeDog( Animal animal) {  // 다형성1 발생

            

             // 다형성 1의 상태에서 자식객체를 강제로 끄집어 낸다.

             Dog dog = (Dog) animal; // cat이 들어올 수 있기에 ClassCastException이 발생한다.

            

//           if(animal instanceof Dog dog) { // 이렇게 하면 강제형변환이 없어지기에 예외가 발생하지 않는다. ( 안전한 버전 )

//                  ;;

//           } // if

            

             // 예외가 발생하게 되면, 발생한 예외의 이름을 파악하는 것이 중요하다.

             // 그 후에 예외이름 : 뒤에 있는 설명을 통해 왜 예외가 발생하고 있는지 파악하고

             // at ~~ ( )안에 예외가 발생한 클래스명과 행 번호를 알려준다.

             // ex. at RuntimeException.ClassCastExceptionExample.changeDog(ClassCastExceptionExample.java:20)

             // - > ClassCastExceptionExample클래스 20번째 행에서 예외가 발생했다는 의미이다.

             // at으로 적혀있는 예외 메세지(Stack Trace)는 아래에서 위로 읽어야 하며, 마지막 예외메세지를 확인하는 것이 좋다.

            

       } // changeDog

 

} // end class

 

class Animal {;;}

class Dog extends Animal {;;}

class Cat extends Animal {;;}

 

08. 실행예외 3 - NullpointerException

 

package RuntimeException;

 

public class NullpointerExceptionExample {

      

       public static void main (String[] args) {

            

             String data = null; // 객체를 가지고 있지 않다.

            

             System.out.println(data.toString());

             // 실행 예외 : 객체를 가지고 있지 않은데, 객체를 가지고 있는 것 처럼 객체 메소드를 실행해서 예외가 발생했다.

            

       } //main

 

} // end class

 

09. 실행예외 4 - NumberFormatException

 

package RuntimeException;

 

public class NumberFormatExceptionExample {

      

       public static void main(String [] args) {

            

             String data1 = "100"; // OK!

             String data2 = "a100"; // 어, 이건 문자열에 a라는 문자와 100이라는 숫자가 같이 있는데 변환이 가능할까? -> 예외발생

            

             // 예외 메세지 : Exception in thread "main" java.lang.NumberFormatException: For input string: "a100"

             // 예외 메세지는 내가 작성한 코드 내에서 발생한 것만 확인하면 된다.

            

             // parseInt ( " 문자열 " ) -> 정수타입으로 바꿔주는 메소드 (***)

             int value1 = Integer.parseInt(data1);

             int value2 = Integer.parseInt(data2);

            

             int result = value1 + value2;

             System.out.println(data1 + " + " + data2 + " = " +result);

 

       } // main

 

} // end class

 

10. 예외처리 코드 - try - catch - finally

 

package try_catch_finally;

 

public class TryCatchFinallyExample {

      

       public static void main (String [] args) { // 예외처리코드 : try - catch

            

             try {

                   

                    Class clazz = Class.forName("java.lang.String2");

                    // 문자열로 클래스 이름을 넣으면 해당하는 clazz객체를 주겠다는 메소드이다.

                   

             } catch(ClassNotFoundException e) { // e는 단순히 예외를 담는 변수이다.

                   

                    // catch블록은 ( )내에 있는 예외가 발생하면 블록 내에 있는 대안 로직을 대신 실행시킨다.

                   

                    System.out.println("클래스가 존재하지 않습니다."); // 대안 로직

                   

                    // finally는 옵션이기에, 반드시 필요한 것은 아니다.

                   

             } // try - catch

            

       } // main

 

} // end class

 

11. 예외처리 코드 2 - try - catch - finally

 

package try_catch_finally;

 

public class TryCatchFinallyRuntimeExceptionExample { // try - catch

      

       public static void main(String [] args) {

            

             String data1 = null;

             String data2 = null;

            

             try { // try 블록 내에서 예외가 발생하게 되면 catch로 간다. 예외가 발생하지 않으면 catch는 패스한다.

                   

                    data1 = args[0];

                    data2 = args[1];

                   

                    int result = Integer.parseInt(args[1]); // 문자열을 숫자로 변환시켜 준다!! (***)

                   

                    System.out.println("result : " + result);

                   

             } catch(ArrayIndexOutOfBoundsException e) {

                   

                    System.out.println("실행매개 값의 수가 부족합니다.");

                    System.out.println("[실행방법]");

                    System.out.println("java TryCatchFinallyRuntimeExceptionExample num1 num2");

                   

                    return; // 이 문장을 만나는 즉시, 메소드의 실행을 종료시키고 (***)

                                 // 만일 뒤의 값(리터럴, 변수, 표현식 등)이 오면, 호출자에게 반환한다.

                   

             } // try-catch

            

            

       } // main

 

} // end class

728x90
댓글
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
최근에 올라온 글
Total
Today
Yesterday
공지사항