-
인터페이스, 내부클래스, 예외JAVA 2021. 7. 23. 09:33
interface 두번째
인터페이스끼리 상속하는 이유?
설계도인 인터페이스들을 메서드의 기능을 다 다르게하여 부품화시키고
상속받는 인터페이스는 건드리지 않고 기능을 추가 삭제 가능하다.
default 메서드:
예를 들어 기존에 인터페이스를 구현한 클래스 말고 새로 그 기능을
구현할 새로운 클래스가 생겼는데 그 클래스를 위해 추가로 메서드를 생성시 기존의 클래스에
영향이 가지 않도록 default 메서드를 생성해 이 인터페이스를 사용한다면 기본으로 사용
할 수 있는 메서드를 제공한다.(default 메서드는 인터페이스에서 구현해야한다!!)
디폴트메서드는 오버라이딩도 가능하기 때문에 사용할 클래스에서 고쳐쓰는게 가능하다.
상속받은 default 메서드를 자식인터페이스에서 다시 추상메서드로 바꾸는 오버라이딩도 가능하다.
nested 중첩(내부클래스)
내부클래스도 바이트 코드 따로 생성(사실 잘 사용안 함)
1. 멤버 클래스
- 인스턴스 클래스: 외부클래스 생성자 생성시 사용가능, 당연히 static 사용가능.
외부클래스의 멤버변수,메서드와 같은 영역이니까 내부클래스에서 외부멤버 사용가능하다.
- 정적(static) 클래스: 외부클래스 생성안해도 따로 사용가능. 클래스가 static 메서드도 static을 가질 수 있다.
외부클래스의 멤버영역은 사용 불가하고, static멤버면 사용가능하다.(같은 static멤버만 가능)
2. 로컬 클래스
- 메서드내에서 적용하는 클래스, 외부클래스의 메서드 안에서만 사용가능하다.
메서드 안에서만 생성자 생성, 필드사용, 메서드사용 가능하다.(접근이 제한되어 있다)
exception
오류
1.에러: 문법오류, 바이트코드로 run되지 못함, 정상상태로 못 돌아감
2.예외(exception): 문법오류는 아니지만 사용자가 코드오류시 런타임 중 발생
발생되면 프로그램 종료
예외처리시 다시 정상으로 돌아감
java목록에 : Java: Exception 문서 확인!!
interface 1
casting(강제형변환)
인터페이스 형에서 구현한클래스형으로
인터페이스
1234public interface Vehicle {void run();}cs 구현클래스
123456789101112public class Bus implements Vehicle{@Overridepublic void run() {System.out.println("버스를 운전합니다.");}public void checkFare() {System.out.println("버스요금을 확인합니다!");}}cs 1234567891011121314151617public class DriverMain {public static void main(String[] args) {Vehicle run = new Bus();run.run();// run.checkFare(); Vehicle 인터페이스 타입에는 없는 메서드Bus bus;bus = (Bus)run; //강제형변환bus.run();bus.checkFare();//Bus 형에는 checkFare() 메서드가 존재한다.}}cs
interface 2
instanceof
인터페이스
123456789101112public class Bus implements Vehicle{@Overridepublic void run() {System.out.println("버스를 운전합니다.");}public void checkFare() {System.out.println("버스요금을 확인합니다!");}}cs 12345678public class Taxi implements Vehicle{@Overridepublic void run() {System.out.println("택시를 운전합니다.");}}cs 12345678910111213public class Driver {public void drive(Vehicle vehicle) {if(vehicle instanceof Bus) {//Bus 의 객체일 경우 checkFare() 메서드를 실행Bus bus = (Bus)vehicle;bus.checkFare();}//Bus 객체와 다른 객체들 공통적으로 run()메서드를 실행vehicle.run();}}cs 12345678910public class DriverMain {public static void main(String[] args) {Driver driver = new Driver();driver.drive(new Taxi());driver.drive(new Bus());}}cs 1번 : 택시를 운전합니다. 2번 : 버스를 운전합니다.
interface 3
인터페이스 상속
여러 인터페이스를 상속(extends!!) 받은 인터페이스 하나를
클래스가 구현한다(implements!!)
상속받은 인터페이스는 당연히 본인도 인터페이스니까 상속받은
추상메서드 구현 따로 안함.
123public interface InterfaceA {void methodA();}cs 123public interface InterfaceB {void methodB();}cs 123public interface InterfaceC extends InterfaceA,InterfaceB{void methodC();}cs 1234567891011121314151617public class ImplementC implements InterfaceC{@Overridepublic void methodA() {System.out.println("InterfaceA.methodA() 호출");}@Overridepublic void methodB() {System.out.println("InterfaceA.methodB() 호출");}@Overridepublic void methodC() {System.out.println("InterfaceA.methodC() 호출");}}cs 1234567891011121314151617181920212223242526public static void main(String[] args) {ImplementC impl = new ImplementC();impl.methodA();impl.methodB();impl.methodC();System.out.println();InterfaceA ia =impl;ia.methodA();// ia.methodB(); (x)// ia.methodC(); (x)System.out.println();InterfaceB ib =impl;// ib.methodA(); (x)ib.methodB();// ib.methodC(); (x)System.out.println();InterfaceC ic =impl;ic.methodA();ic.methodB();ic.methodC();}}cs
interface 4
default 메서드
인터페이스
1234567891011public interface MyInterface {void method1();default void method2() {System.out.println("1년후에 새로운 업무가 추가!!!");}default void method3() {System.out.println("MyInterface.method3() 실행!!");}}cs 1234567public class MyClassA implements MyInterface{@Overridepublic void method1() {System.out.println("MyClassA.method1() 실행");}}cs 123456789101112public class MyClassB implements MyInterface{@Overridepublic void method1() {System.out.println("MyClassB.method1() 실행");}@Overridepublic void method2() {System.out.println("MyClassB.method2() 실행");}}cs default method의 필요성
인터페이스에서 디폴트메서드를 허용한 이유는 기존의 인터페이스를 확장해서
새로운 기능을 추가할 수 있도록 하기 위해서이다.
기존 인터페이스의 이름과 추상메서드의 변경없이 디폴트메서드만 추가할 수 있기 때문에
이전에 개발된 구현클래스들을 그대로 사용할 수 있으면서 새롭게 개발된 클래스에서는
디폴트 메서드를 활용할 수 있도록 한다.
12345678910111213141516public class DefaultMethodMain {public static void main(String[] args) {MyInterface mia = new MyClassA();mia.method1();mia.method2();mia.method3();System.out.println();MyInterface mib = new MyClassB();mib.method1();mib.method2();mib.method3();}}cs
내부클래스
내부클래스의 위치
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980public class A {//A생성자public A() {System.out.println("A객체 생성");}//1. 인스턴스 멤버 클래스//A의 멤버, A가 생성되야 사용가능public class B{//B필드int field1;//B생성자public B() {System.out.println("B객체 생성");}//B메서드void method1() {System.out.println("B.method1() 실행");}//static void method2(){} (X)}//2. 정적 멤버 클래스//정적 멤버, A 생성안되도 사용가능public static class C{//C필드int field1;//C생성자public C() {System.out.println("C객체 생성");}//C메서드void method1() {System.out.println("C.method1() 실행 !!");}static void method2() {System.out.println("C.method1() 실행 !!");}}//3. 로컬 클래스//A의 메소드의 클래스, A생성후 메서드를 쓸 때 사용.//로컬클래스는 접근제한자를 사용할 수 없다.void method() {class D{//D필드int field1;//D생성자public D() {System.out.println("D객체 생성");}//D메서드void method1() {System.out.println("D.method1() 실행!!");}//static void method2(){} (X)}//메소드는 단순히 호출만 가능, 메서드 안에서 생성, 호출해야 함D d = new D();d.field1 = 10;d.method1();}}cs 내부클래스의 접근범위
: 로컬 클래스는 외부클래스멤버들에 아예 접근 불가
1234567891011121314151617181920212223242526272829303132333435public class A {int field1;void method1() {}static int field2;static void method2() {}//인스턴스클래스//인스턴스, static인 필드와 메서드에 모두 접근 가능class B{void method() {field1 = 10;method1();//외부클래스의 static 멤버는 어차피 데이터영역에 올라가 있으므로 사용 가능field2 = 200;method2();}}//정적멤버클래스//외부클래스의 필드,메서드도 정적필드,메서드만 접근 가능static class C{void method() {//field1 = 10; (X)//method1(); (X)field2 = 200;method2();}}}cs 내부인터페이스
외부클래스에서 하는 역할
12345678910111213141516171819public class Button {//내부 인터페이스interface OnClickListner{void method();}//필드OnClickListner listner;//메서드void touch() {listner.method();}void setOnClickListner(OnClickListner listner) {this.listner = listner;}}cs 1234567public class CallListner implements Button.OnClickListner{@Overridepublic void method() {System.out.println("전화를 겁니다.");}}cs 1234567public class MessageListner implements Button.OnClickListner{@Overridepublic void method() {System.out.println("메시지를 보냅니다.");}}cs 12345678910111213public class ButtonMain {public static void main(String[] args) {Button button = new Button();button.setOnClickListner(new CallListner());button.touch();button.setOnClickListner(new MessageListner());button.touch();}}cs
예외1
123456789101112public class ArrayIndexOutOfBoundsMain {public static void main(String[]args) {// 현재 메인보드의 args 배열에 값이 없으므로 ArrayIndexOutOfBoundsException이 걸림String data1 = args[0];// 현재값이 null이므로 NullPointerException이 걸림String data = null;System.out.println(data.toString());}}cs 123456789101112131415public class NumberFormatExceptionMain {public static void main(String[] args) {String data1 = "100";String data2 = "100a";int val1 = Integer.parseInt(data1);System.out.println(val1);//NumberFormatException 발생int val2 = Integer.parseInt(data2);System.out.println(val2);}}cs 12345678910111213141516171819202122public class ClassCastingExceptionMain {public static void main(String[] args) {Dog dog = new Dog();Cat cat = new Cat();changeDog(dog);//ClassCastException 발생, 같은 부모를 가져도 자식객체들 끼리는 당연히 형변환 못함.changeDog(cat);}private static void changeDog(Animal animal) {Dog dog =(Dog)animal;System.out.println(dog.toString());}}class Animal{}class Dog extends Animal{}class Cat extends Animal{}cs
예외2
throws
123456789101112public class TryCatchMain {//예외를 호출한 곳에서 Main으로 던져서 해결public static void main(String[] args) ClassNotFoundException {//Dog dog = new Dog(); 이런 형식과 동일//Class형 안에 forName("패키지.클래스")으로 접근한 객체 생성//Class 객체 생성자가 private 이기 때문에 이렇게 접근해야 생성됨Class cls = Class.forName("java.lang.String");System.out.println(cls.toString());}}cs try-catch
123456789101112131415161718192021public class TryCatchMain {//예외를 호출한 곳에서 Main으로 던져서 해결public static void main(String[] args){//Dog dog = new Dog(); 이런 형식과 동일//Class형 안에 forName("패키지.클래스")으로 접근한 객체 생성//Class 객체 생성자가 private 이기 때문에 이렇게 접근해야 생성됨try {Class cls = Class.forName("java.lang.Stringxxx");System.out.println(cls.toString());} catch (ClassNotFoundException e) { //위의 발생한 에러를 매개변수자리에 넣음System.out.println("클래스를 찾지 못했습니다.");e.printStackTrace();//어디서 에러걸렸는지 추적 및 알려줌System.out.println(e.getMessage());//매개변수로 온 Class의 정보가 나옴}}}cs
예외3
throws
계속 떠넘기기
예외떠넘기기(throws)
메서드 내부에서 예외가 발생할 경우 코딩을 할 때 try~catch 블럭으로 예외처리를 하는 것이 기본이지만
경우에 따라서는 메서드를 호출한 곳으로 예외를 떠 넘길 수가 있다.
이 때 사용하는 키워드가 throws 이다.
throws키워드는 메서드 선언부 끝에 작성되어 메서드에서 처리하지 않은 예외를 호출한 곳으로 떠넘기는 역할을 한다. throws 키워드에는 떠넘길 예외클래스를 쉼표로 구분해서 나열해주면 된다.
throws 키워드가 붙어 있는 메서드는 반드시 try 블럭내에서 호출되어야 한다.
그리고 catch블럭에서 떠넘긴 예외를 처리해야 한다.
하지만 보통 안쓰이고 아래와 같이 쓰이는 경우 대부분이다.
123456789101112//계속 떠넘겨서 Main까지 넘겨버리기public static void main(String[] args) throws ClassNotFoundException {findClass();}private static void findClass() throws ClassNotFoundException {Class cls = Class.forName("java.lang.Stringxxx");}}cs
예외4
try-catch-finally문
12345678910111213141516171819202122232425262728293031323334public class TryCatchFinallyMain {public static void main(String[] args) {String data1 = null;String data2 = null;try {data1 = args[0];data2 = args[1];} catch (ArrayIndexOutOfBoundsException e) {System.out.println("실행시 매개변수가 부족합니다!");e.getMessage();return;}System.out.println(data1 + "," + data2);try {String str1 = "aaa";String str2 = "bbb";int val1 = Integer.parseInt(str1);int val2 = Integer.parseInt(str2);int result = val1 + val2;System.out.println(result);} catch (NumberFormatException e) {System.out.println("숫자로 변환이 불가능 합니다.");} finally {System.out.println("무조건 한번은 실행됩니다!!");}}}cs
예외5
다중예외 catch 문
12345678910111213141516171819202122232425262728293031323334353637public class MultiException {public static void main(String[] args) {try {String data1 = args[0];String data2 = args[1];String str1 = "aaa";String str2 = "bbb";int val1 = Integer.parseInt(str1);int val2 = Integer.parseInt(str2);int result = val1 + val2;System.out.println(result);// } catch (ArrayIndexOutOfBoundsException e) {// System.out.println("실행매개 변수가 부족합니다!");//// } catch (NumberFormatException e) {// System.out.println("숫자로 변환이 불가능합니다!");//// } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {// System.out.println("배열 또는 숫자변환시에 예외가 발생했습니다.");} catch (Exception e) {System.out.println("예외가 발생했습니다.");e.getMessage();e.printStackTrace();//이렇게 추적을 통해 어떤 예외인지 알 수 있어서 위처럼 말고 그냥 Exception 클래스로 다 잡는게 편하다.} finally {System.out.println("무조건 한번은 실행됩니다!");}}}cs 'JAVA' 카테고리의 다른 글
정규표현식,Arrays,java.lang 패키지 (0) 2021.07.23 java.lang.Object 클래스 (0) 2021.07.23 상속, instanceof, 추상, interface (0) 2021.07.22 set,get,상속,overriding & overloading (0) 2021.07.22 메서드,싱글톤,static,상수 (0) 2021.07.22