Java (인터페이스와 내부클래스, 예외 처리, java.lang 패키지 클래스 활용)

주8·2023년 1월 16일
0

WIL

목록 보기
5/19
post-thumbnail

기간
2023/1/9 ~ 2023/1/13

수업
실시간 ZOOM 수업


Day 11(인터페이스와 내부클래스)

인터페이스와 내부클래스

인터페이스

하나의 클래스는 여러 개의 인터페이스를 implements할 수 있다.
인터페이스는 인터페이스끼리 다중상속할 수 있다. (implements가 아니라 extends)
→ 인터페이스는 추상메서드의 집합

구현체인 클래스를 인터페이스 타입으로 선언할 수 있다.
→ 해당 인터페이스 기능으로 그룹화 가능

interface Flyable{
	void fly();
}

class Bird implements Flyable{
	@Override
	public void fly(){
		System.out.println("새가 난다");
	}
}
class Airplane implements Flyable{
	@Override
	public void fly(){
		System.out.println("비행기가 난다");
	}

	public static void main(String[] args){
		Flyable[] flyable = {new Bird(), new Airplane()};
		flyable[0].fly(); //새가 난다
		flyable[1].fly(); //비행기가 난다
	}
}

Flyable엔 fly 메서드만 있으니까 관련있는 기능끼리 묶어서 관리할 수 있다.


인터페이스의 장점

  1. 개발 시간을 단축할 수 있다.
    1. A의 개발이 끝나길 기다릴 필요 없이 인터페이스로 추상메서드를 호출하여 코드 작성 가능
  2. 변경에 유리한 유연한 설계가 가능하다.
  3. 표준화가 가능하다.
    1. 규칙을 정해서 개발을 할 수 있다.
    2. JDBC인터페이스로 설계하면 DB를 변경해야 할 때 어플리케이션을 많이 변경하지 않아도 됨
  4. 서로 관계없는 클래스의 관계를 맺어줄 수 있다.

인터페이스를 사용하면 클래스간의 관계를 느슨하개 유지할 수 있고, 클래스간의 관계가 느슨하면 다른 클래스로 교체할 때 수정할 코드가 줄어든다(의존 역전 원칙: DIP).

//클래스간의 직접관계
class A{
	public void methodA(B b){ //B를 변경할 경우 바꿔야 함
		b.methodB();
	}
}

class B{
	public void methodB(){
		System.out.println("methodB()");
	}
}

class InterfaceTest{
	public static void main(String[] args){
		A a = new A();
		a.methodA(new B());
	}
}

👇

//간점관계
class A{
	public void methodA(I i){
		i.methodB();
	}
}

interface I{
	void methodB();
}

class B implements I{
	public void methodB(){
		System.out.println("methodB()");
	}
}
//B를 C로 변경해도 A는 바꿀 게 없음
class C implements I{
	public void methodB(){
		System.out.println("methodB() in C");
	}
}

default 메서드가 기본 메서드와 충돌할 때의 해결책

  1. 여러 인터페이스와 디폴트 메서드 간의 충돌
    1. 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩해야 한다.
  2. 디폴트 메서드와 조상 클래스의 메서드 간의 충돌
    1. 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다.

인터페이스와 추상클래스의 차이

  1. 인터페이스는 인터페이스끼리만 상속(다중상속도 가능)할 수 있다. (implements 아니고 extends)
    1. defualt, static 메서드 만들 수 있어서 implements 할 수 있을 줄 알았는데 아니었음
  2. 추상클래스는 인터페이스를 implements할 수도 있고, 다른 클래스를 상속받을 수도 있다.
    1. 추상클래스는 추상메서드가 1개 이상인 클래스니까.
    2. 그래서 다른 인터페이스를 구현하고 그 구현한 메서드를 다시 상속할 수도 있음
    3. 추상클래스가 인터페이스를 구현하고, 그 추상클래스를 상속받으면 추상클래스의 인터페이스타입으로도 인스턴스를 생성할 수 있다.

Java8부터 인터페이스에 default, static 메서드 만들어서 구현된 메서드 쓸 수 있다는 걸 배우니까 생각난 게
내가 저번 부트캠프에서 프로젝트할 때 (자바 뭣도 모르고 바로 스프링 들어갔을 때 ㅎㅎ) 해쉬태그 검색기능을 알고리즘으로 구현해놓고 메서드를 공용으로 쓰려고 하다가 클래스 따로 만들긴 싫고(인스턴스 만들기 싫었음... 굳이 메서드 하나 쓰자고 DI 주입을 해? 싶어서 ㅋㅋ) 인터페이스 만들어서 거기에 알고리즘 메서드 넣고 implements 해놓고 깃헙에 pr하니까 같은 팀원이 보고
인터페이스에 구현된 메서드를 넣으면 안 된다고 함...
그래서 엥? 되던데요? 하니까 원래 인터페이스는 implements 해서 구현해야 하는 거라고 그렇게 쓰면 안 된다고 해서 결국 클래스 따로 만들어서 객체 DI 주입해서 썼던 기억이 ㅋㅋ...
그때야 실습으로 바로 스프링부트 들어가서 프로젝트 달리던 때라 자바 기본 지식이 없어서 그렇다면 그런갑다 하고 말았는데... (물론 속으로 되는데 왜 안 쓰지 이상하네 생각하긴 했음ㅋㅋㅋ)
아니 애초에 static 메서드를 만드는 게 나았을까?


Day 12(예외 처리)

예외(Exception) 처리

스프링에서 global exception handler 만들어서 exception throw한 걸 log에 e.getMessage해서 썼던 기억...
그 땐 사용자 정의 예외처리가 있는 줄 모르고 인텔리제이에서 exception치면 가장 위에 표기되는 ㅋㅋㅋ 걸로 모든걸 통일했었는데... 그러다가 모든 게 404로 구분이 안 되니까 최종 프로젝트에선 예외를 3개정도 나눠서 404, 500 등으로 보냈었다.

아 이래서 배워야 해;;


Day 13(java.lang 패키지 클래스 활용)

java.lang 패키지 클래스 활용

알고리즘 하면서 참 string 많이도 자르고 붙이고...
근데 int <-> Integer가 오토박싱/언박싱이 되는데
왜 배열에서는 int[]로 변환할 때 mapToInt(Integer::intValue)를 붙여야 하는 걸까? 그냥 toArray()가 Object[]타입으로 출력되니까 toArray에 대한 변환인가? 그렇다기엔 Integer를 intValue로 바꾸는 건데... Object가 아니라...

Integer[] a = {10};
int[] aa = a.stream().mapToInt(Integer::intValue).toArray();

-> 배열은 기본형(Primitive type)이 아니므로... 박싱/언박싱은 기본형과 그 래퍼클래스 간의 변환을 말한다.
(바본가 정말;; 그냥 타입만 보고 Integer <-> int인데 배열에선 왜 안 되지 이러고 있었네;;;)

profile
웹퍼블리셔의 백엔드 개발자 도전기

0개의 댓글