비트교육센터/자바

[비트교육센터] 자바 15일차 인터페이스,예외처리,객체

달의요정루나 2023. 6. 21. 19:58

1. 인터페이스

1) 인터페이스로 만든 자동차 배기음

[1] Engine.java

package com.julian5383.train10;

public interface Engine {

	public void drive();

}

[2] Car.java

package com.julian5383.train10;

public class Car implements Engine{

	@Override
	public void drive() {
		// TODO Auto-generated method stub
		
	}

}

[3] DieselEngine.java

package com.julian5383.train10;

public class DieselEngine implements Engine{
	
	@Override
	public void drive() {
		// TODO Auto-generated method stub
		System.out.println("드륵드륵~~~~~~~");
	}
}

[4] ElectroEngine.java

package com.julian5383.train10;

public class ElectroEngine implements Engine {
	@Override
	public void drive() {
		// TODO Auto-generated method stub
		System.out.println("우웅웅~~~~~~~");
	}
}

[5] GasolineEngine.java

package com.julian5383.train10;

public class GasolineEngine implements Engine{

	@Override
	public void drive() {
		// TODO Auto-generated method stub
		System.out.println("부르릉~~~~~~~~");
	}
}

[6] CarMain.java

package com.julian5383.train10;

public class CarMain {
	public static void main(String[] args) {

		Engine gaEngine = new GasolineEngine();
		Engine diEngine = new DieselEngine();
		Engine elEngine = new ElectroEngine();
		
		gaEngine.drive();
		diEngine.drive();
		elEngine.drive();
	}

}

- 인터페이스에 drive메소드를 선언하고 클래스들에 여러개의 클래스에 인터페이스를 구현해서 추상 메소드를 재정의 하였다.

 

--> 결과

부르릉~~~~~~~~
드륵드륵~~~~~~~
우웅웅~~~~~~~

2) 다중 인터페이스 구현

- 구현한 객체는 여러 개의 인터페이스를 implements할 수 있다.

[1] RemoteControl.java

package com.julian5383.train11;

public interface RemoteControl {
	public void turnOn();
	public void turnOff();
}

[2] Searchable.java

package com.julian5383.train11;

public interface Searchable {
	public void search(String url);

}

[3] SmartTelevision.java

package com.julian5383.train11;

public class SmartTelevision implements RemoteControl, Searchable{

	//search() 추상메소드 오버라이딩
	@Override
	public void search(String url) {
		// TODO Auto-generated method stub
		System.out.println(url+"을 검색합니다.");
	}

	//turnOn() 추상메소드 오버라이딩
	@Override
	public void turnOn() {
		// TODO Auto-generated method stub
		System.out.println("TV를 켭니다.");
	}

	//turnOff() 추상메소드 오버라이딩
	@Override
	public void turnOff() {
		// TODO Auto-generated method stub
		System.out.println("TV를 끕니다.");
	}

	
}

[4] RemoteMain.java

package com.julian5383.train11;

public class RemoteMain {
	public static void main(String[] args) {
		//RemoteControl 인터페이스 변수 선언 및 구현 객체 대입
		RemoteControl rc = new SmartTelevision();
		//RemoteControl 인터페이스에 선언된 추상 메소드만 호출 가능
		rc.turnOn();
		rc.turnOff();
		
		//Searchable 인터페이스 변수 선언 및 구현 객체 대입
		Searchable searchable = new SmartTelevision();
		//Searchable 인터페이스에 선언된 추상 메소드만 호출 가능
		searchable.search("http://www.naver.com");
	}
}

--> 결과

TV를 켭니다.
TV를 끕니다.
http://www.naver.com을 검색합니다.

3) 인터페이스 상속

- 인터페이스도 다른 인터페이스를 상속할 수 있다. 클래스와는 달리 다중 상속을 허용한다.

- extends 키워드 뒤에 상속할 인터페이스들을 나열하면 된다.

- 자식 인터페이스의 구현 클래스는 자식 인터페이스의 메소드뿐만 아니라 부모 인터페이스의 모든 추상메소드를 재정의 해야한다.

 

[1] InterfaceA.java

package com.julian5383.train12;

public interface InterfaceA {
	//추상 메소드
	public void methodA();

}

[2] InterfaceB.java

package com.julian5383.train12;

public interface InterfaceB {
	//추상 메소드
	public void methodB();

}

[3] InterfaceC.java

package com.julian5383.train12;

public interface InterfaceC extends InterfaceA, InterfaceB {
	//추상 메소드
	public void methodC();
}

[4] InterfaceImpl.java

package com.julian5383.train12;

public class InterfaceImpl implements InterfaceC{

	@Override
	public void methodA() {
		// TODO Auto-generated method stub
		System.out.println("methodA 실행");
	}

	@Override
	public void methodB() {
		// TODO Auto-generated method stub
		System.out.println("methodB 실행");
	}

	@Override
	public void methodC() {
		// TODO Auto-generated method stub
		System.out.println("methodC 실행");
	}

	
}

[5] InterfaceMain.java

package com.julian5383.train12;

public class InterfaceMain {
	public static void main(String[] args) {
		InterfaceImpl impl = new InterfaceImpl();
		
		InterfaceA ia = impl;//impl이 가지고 있는 레퍼런스 값을 ia에 넣어준것
		ia.methodA();
		//ia.methodB();
		System.out.println();
		
		InterfaceB ib = impl;
		//ib.methodA();
		ib.methodB();
		System.out.println();
		
		InterfaceC ic = impl;
		ic.methodA();
		ic.methodB();
		ic.methodC();
	}
}

--> 결과

methodA 실행

methodB 실행

methodA 실행
methodB 실행
methodC 실행

2. 예외 처리

1) 예외처리 예시

[1] ExceptionTest.java(NullPointerException)

package com.julian5383.train13;

public class ExceptionTest {
	public static void main(String[] args) {
		int[] arr = null;//NullPointerException
		
		System.out.println(arr[3]);
		//Syntax Error
		//Exception 예외사항
	}

}

NullPointerException: 실제 값이 아닌 null을 가지고 있는 객체/변수를 호출할 때 발생하는 예외이다.

--> 결과

Exception in thread "main" java.lang.NullPointerException: Cannot load from int array because "arr" is null
	at com.julian5383.train13.ExceptionTest.main(ExceptionTest.java:7)

 

[2] ExceptionTest.java(try, catch, finally)

package com.julian5383.train13;

public class ExceptionTest {
	public static void main(String[] args) {
		int[] arr= {1,2,3,4,5};
		try {
			System.out.println(arr[3]);
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("배열관련 오류");
		} finally {
			System.out.println("무조건 실행");
		}//finally: 보통 자원을 들고 있는데 오류가 나면 풀어줄려고 사용
	}

}

- try-catch-finally는 예외 처리 코드이다.

- try에서 예외발생 가능코드를 실행하고 정상실행이 되면 넘어가지만 예외가 발생시 catch가 실행된다.

- 단, 예외발생 여부와 상관없이 finally블록은 항상 실행된다. 심지어 try와 catch 블록에서 return문을 사용해도 finally블록은 항상 실행된다.

 

--> 결과

4
무조건 실행

[3] ExceptionTest.java(ArrayIndexOutofBoundsException)

package com.julian5383.train13;

public class ExceptionTest {
	public static void main(String[] args) {		
		String data1 = args[0];//ArrayIndexOutOfBoundsException
		String data2 = args[0];
		
		System.out.println(data1);
		System.out.println(data2);
		
		try {
			Class c = Class.forName("java.lang.String2");
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("오류");
			e.printStackTrace();
			//e.printstacktrace가 빨간 오류 찍음
			System.out.println(e.getMessage());
		}
	}

}

- ArrayIndexOutOfBoundsException: 정해진 배열의 크기보다 크거나 음수 index에 대한 요청이 있으면 나오는 오류이다.

 

--> 결과

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
	at com.julian5383.train13.ExceptionTest.main(ExceptionTest.java:22)

- Exception관련

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Exception.html

 

Exception (Java SE 17 & JDK 17)

All Implemented Interfaces: Serializable Direct Known Subclasses: AbsentInformationException, AgentInitializationException, AgentLoadException, AlreadyBoundException, AttachNotSupportedException, AWTException, BackingStoreException, BadAttributeValueExpExc

docs.oracle.com

 

[4] ThrowsTest.java

package com.julian5383.train13;

public class ThrowsTest {
	public static void main(String[] args) {
		try {
			test();
		} catch (Exception e) {//Exception은 예외에 관련된 최상위 부모 클래스
			// TODO Auto-generated catch block
			System.out.println("예외 처리");
		}//ClassNotFoundException이 있어 예외처리가 필수
	}
	
	public static void test() throws ClassNotFoundException{
		Class c = Class.forName("java.lang.String2");
	}
	//test()에서 예외처리를 미리 할수 있지만 main에 test()를 선언시 이곳에서 문제가 발생시 처리를 못한다.
	//throws의 의미와 관련, test에서 예외처리를 main으로 넘겨 처리시킨다.
}

- throws: 예외가 발생시 try-catch블록으로 예외를 처리하지만 메소드를 호출한 곳으로 예외를 넘길 수 있다.

--> 결과

예외 처리

2) 예외처리 예시(계좌 기록)

[1] BalanceInsufficientException.java

package com.julian5383.train13;

public class BalanceInsufficientException extends RuntimeException{
	//예외는 RunTimeException로 선언
	public BalanceInsufficientException() {}//기본 생성자
	public BalanceInsufficientException(String message) {
		super(message);
	}
	//인자 없는 생성자도 있다. 이는 throw에서 메시지를 따로 작성하지 않을때 만든다.
}

[2] Account.java

package com.julian5383.train13;

public class Account {
	private long balance;
	
	public long getbalance() {
		return balance;
	}
	
	public void deposit(int money) {
		balance+=money;
	}

	public void withdraw(int money) throws BalanceInsufficientException{//호출한 곳으로 예외 넘김
		if(balance < money) {
			throw new BalanceInsufficientException("잔고부족");//예외 발생
			//throw new BalanceInsufficientException();
		}
		balance -= money;
	}
}

[3] AccountMain.java

package com.julian5383.train13;

public class AccountMain {
	public static void main(String[] args) {
		Account acc = new Account();
		
		acc.deposit(10000);
		System.out.println(acc.getbalance());
		
		try {
			acc.withdraw(50000);
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println(e.getMessage());
			System.out.println();
			e.printStackTrace();
		}//예외처리코드와 함께 withdraw() 메소드 호출
	}

}

- Account에서 출금을 계산할때 에러가 나타나면 BalanceInsufficientException 클래스로 넘기도록 만들었다.

--> 결과

10000
잔고부족

com.julian5383.train13.BalanceInsufficientException: 잔고부족
	at com.julian5383.train13.Account.withdraw(Account.java:16)
	at com.julian5383.train13.AccountMain.main(AccountMain.java:11)

- 런타임Exception관련

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/RuntimeException.html

 

RuntimeException (Java SE 17 & JDK 17)

All Implemented Interfaces: Serializable Direct Known Subclasses: AnnotationTypeMismatchException, ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, CatalogException, Clas

docs.oracle.com

3. 객체지향 프로그래밍

1) 객체 타입 확인

[1] ObjectTest.java

package com.julian5383.train14;

public class ObjectTest {
	public static void main(String[] args) {
		int[] a = {1,2,3};
		int[] b = {1,2,3};
		
		System.out.println(a);
		System.out.println(b);
		System.out.println(a.equals(b));
		
		System.out.println();
		
		String s1 = new String("Hello");
		String s2 = new String("Hello");
		
		System.out.println(s1);
		System.out.println(s2);
		System.out.println(s1 == s2);
		System.out.println(s1.equals(s2));
	}

}

- 인덱스 없이 배열이름만 입력시 각 배열의 주소값이 출력된다.

- 이것 equals에 대입하면 주소값이 다르기 때문에 false가 뜬다.

 

- ==주소값을 통해서 비교를 해서 문자열 비교 관련해서 True를 출력하려면 equals를 입력한다.

 

--> 결과

[I@5ca881b5
[I@24d46ca6
false

Hello
Hello
false
true

 

2) 객체 타입 확인

[1] Member.java

package com.julian5383.train14;

public class Member {
	private String id;

	public Member(String id) {
		this.id = id;
	}
	
	public String getId() {
		return id;
	}

	@Override
	public boolean equals(Object obj) {//object에서 상속받음.
		// TODO Auto-generated method stub
		if(obj instanceof Member) {//객체 타입 확인 연산자
			Member member=(Member)obj;
			if(id.equals(member.id)) {
				return true;
			}
		}
		return false;
	}

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return super.toString()+"-"+id;
	}
	
	

}

- instanceof: 상속에서 객체타입확인(해당 코드문에서는 obj에 대입된 객체가 Member일 경우 실행한다.)

- obj에 대입된 객체가 Member일 경우에만 Member로 강제 타입 변환시킴.

[2] MemberMain.java

package com.julian5383.train14;

public class MemberMain {
	public static void main(String[] args) {
		Member m1 = new Member("홍길동");
		Member m2 = new Member("김선달");
		Member m3 = new Member("홍길동");
		
		System.out.println(m1.equals(m2));
		System.out.println(m2.equals(m3));
		System.out.println(m1.equals(m3));
		
		System.out.println(m1);//객체를 찍으면 객체id가 출력
		System.out.println(m2);
		System.out.println(m3);
		
		System.out.println(m1.getId());
	}

}

--> 결과

false
false
true
com.julian5383.train14.Member@24d46ca6-홍길동
com.julian5383.train14.Member@4517d9a3-김선달
com.julian5383.train14.Member@372f7a8d-홍길동
홍길동

--> 객체관련 정보 주소

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html

 

Object (Java SE 17 & JDK 17)

java.lang.Object public class Object Class Object is the root of the class hierarchy. Every class has Object as a superclass. All objects, including arrays, implement the methods of this class. Since: 1.0 See Also: Constructor Summary Constructors Method S

docs.oracle.com

3) Split, SpringBuffer

[1] SplitTest.java

package com.julian5383.train14;

public class SplitTest {
	public static void main(String[] args) {
		String s = "Hi, my name is Tom.";
		String[] tokens = s.split(" ");
		//String[] tokens = "Hi, my name is Tom.".split(" ");
		for (String token: tokens) {
			System.out.println(token);
		}
		
		System.out.println("--------------------------------");
		
		StringBuilder sb = new StringBuilder();
		
		sb.append("Java ");
		sb.append("Class ");
		sb.append("Open!");
		System.out.println(sb.length());
		System.out.println(sb.toString());
		//StringBuffer는 StringBuilder와 사용법 동일, thread safe 버전
		//StringBuilder를 선언하면 맞은 문자열 변경작업시 효율적으로 작업할 수 있다.
	}

}

- split을 통해서 문자열을 나눌수 있다.

- split()안에 공백을 입력하면(split(" "))공백을 기준으로 나누고, 문자를 선언하면(split("A")) 문자 A에 따라 분류한다.

 

- StringBuffer: 문자열을 추가하거나 변경할 때 쓰는 자료형이다.

- StringBuilder: 문자열을 만드는 객체이다.

--> 결과

Hi,
my
name
is
Tom.
--------------------------------
16
Java Class Open!

4) WrapperTest

[1] WrapperTest.java

package com.julian5383.train14;

public class WrapperTest {

	public static void main(String[] args) {
		// byte Byte, char Char, short Short, int Integer, long Long, float Float, double Double
		// Wrapper Class
		
		Integer a = 10;
		//Auto Boxing: 자동으로 넣어줌, 해당 값을 담는 객체를 만들어서 그 레퍼런스 값을 a에 담음
		Integer b = 20;
		
		System.out.println(a+b);
		
		String s="100";
		int c=200;
		
		int d=c+Integer.parseInt(s);//문자열 값을 숫자로 바꾸어줌
		System.out.println(d);
		System.out.println(a.toString());
		System.out.println(a.equals(b));
	}

}

- Wrapper: 포장객체로 값을 포장한다는 의미이다.

 

- 박싱: 기본 카입의 값을 포장 객체로 만드는 과정

int i = 10;
Integer num = new Integer(i);

- 언박싱: 포각 객체에서 기본 타입의 값을 얻어내는 과정

Integer num = new Integer(10);
int i = num.intValue();

- Integer 클래스 parseInt 메소드: 문자열에서 정수형으로 바꾸는 방법이다.

--> 결과

30
300
10
false

4. 실전문제

1) 토양샘플데이터 구하기

[1] SoilSearch.java

- 지질학자는 토양샘플 분석을 도와주는 프로그램을 원함
- 이 프로그램은 샘플내 성분 종류와 각 성분의 함량을 실행인자로 받음
- 첫번째 인자는 토양내 성분 이름이며 "," 로 구분되어 있음
- 두번째 인자는 각 성분의 함량 정보이며 2차원 정보로 구성됨.
- 각 열은 "<>" 로 구분되어 있으며, 각 행은 "," 로 구분되어 있음
carbon-dioxide,magnesium,sodium,potassium,chloride,water
8.3,4.5,6.7,2.3,12.5,4.5<>3.9,1.8,34.7,23.5,1.2,14.3<>6.7,7.4,1.5,18.4,7.2,23.7<>23.4,5.6,2.9,18.5,39.5,18.2<>15.4,5.3,27.4,9.8,3.8,27.4
package com.julian5383.train15;

public class SoilSearch {
	public static void main(String[] args) {
		String[] elements = getElements(args[0]);//인자의 첫줄에서 값을 받는다.
		printElement(elements);
		
		double[][] samples = getSamples(args[1]);//인자의 두번째줄에서 값을 받는다.
		
		printSamples(samples);
	}
	
	public static String[] getElements(String inputElementString) {
		return inputElementString.split(",");//첫줄값을 ,단위로 분리한다.
	}
	
	public static double[][] getSamples(String inputElementString) {
		String row[]=inputElementString.split("<>");//두번줄의 값을 <>을 기준으로 행을 분리한다.
		String col[]=row[0].split(",");// 행을 기준으로 열을 ,을 기준으로 분리한다.
		
		double samples[][] = new double[row.length][col.length];
		//samples 2차원 배열을 선언한다.
        
		for (int i = 0; i < samples.length; i++) {
			String[] temp = row[i].split(",");
			for (int j = 0; j < samples[i].length; j++) {
				samples[i][j]=Double.parseDouble(temp[j]);
			}
		}
        // samples 2차원 배열에 row배열과 col배열의 데이터들을 집어넣는다.
        // 단, 문자열들을 double형으로 입력한다.
		return samples;
	}
	
	public static void printElement(String[] array) {
		for(String element : array) {
			System.out.println(element);
		}
	}
    //물질들의 이름들 출력한다.
	
	public static void printSamples(double[][] samples) {
		for(double[] row:samples) {//samples을 double[]배열형태로 
			for(double element:row) {
				System.out.printf("%2.1f ",element);
			}
			System.out.println();
		}
	}
    //샘플 데이터들을 출력한다.
}

--> 결과

carbon-dioxide
magnesium
sodium
potassium
chloride
water
8.3 4.5 6.7 2.3 12.5 4.5 
3.9 1.8 34.7 23.5 1.2 14.3 
6.7 7.4 1.5 18.4 7.2 23.7 
23.4 5.6 2.9 18.5 39.5 18.2 
15.4 5.3 27.4 9.8 3.8 27.4