두 객체를 연결
하는 역할을 한다.interface
키워드 사용default
, public
을 붙일 수 있다.package ch08.sec02;
public interface RemoteControl {
public void turnOn();
}
implements
키워드를 사용해 인터페이스를 구현한다.package ch08.sec02;
public class Television implements RemoteControl{
@Override
public void turnOn() {
System.out.println("Tv를 켜다.");
}
}
null을 대입
할 수 있다.구현 객체를 대입
해야 한다.package ch08.sec02;
public class RemoteControlEx {
public static void main(String[] args) {
RemoteControl remoteControl = null;
remoteControl = new Television();
remoteControl.turnOn(); // Tv를 켜다.
}
}
public static final
특성을 갖는다.대문자
로 작성하되, 단어 간 연결은 언더바(_)
로 작성하는 것이 관례이다.package ch08.sec02;
public interface RemoteControl {
// 상수 필드
int MAX_VOLUME = 10;
int MIN_VOLUME = 0;
// 추상 메서드
public void turnOn();
}
package ch08.sec02;
public class RemoteControlEx {
public static void main(String[] args) {
System.out.println(RemoteControl.MAX_VOLUME); // 10
System.out.println(RemoteControl.MIN_VOLUME); // 0
}
}
모든 추상 메서드를 재정의
해야 한다.완전한 실행 코드를 가진 메서드
로 default 키워드가 리턴 타입 앞에 붙는다.package ch08.sec02;
public interface RemoteControl {
int MAX_VOLUME = 10;
int MIN_VOLUME = 0;
void turnOn();
void setVolume(int volume);
default void setMute(boolean mute) {
if (mute) {
System.out.println("무음 처리");
setVolume(MIN_VOLUME);
} else {
System.out.println("무음 해제");
}
}
static void changeBattery() {
// setMute(); // 컴파일 에러 : Non-static method 'setMute(boolean)' cannot be referenced from a static context
System.out.println("리모콘 건전지를 교환합니다.");
}
}
package ch08.sec02;
public class Television implements RemoteControl{
private int volume;
private int memoryVolume;
@Override
public void turnOn() {
System.out.println("Tv를 켜다.");
}
@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;
}
System.out.println("현재 볼륨: " + volume);
}
@Override
public void setMute(boolean mute) {
if (mute) {
this.memoryVolume = this.volume;
System.out.println("무음 처리합니다.");
setVolume(RemoteControl.MIN_VOLUME);
} else {
System.out.println("무음 해제합니다.");
setVolume(this.memoryVolume);
}
}
}
package ch08.sec02;
public class Audio implements RemoteControl{
private int volume;
@Override
public void turnOn() {
System.out.println("오디오를 켜다.");
}
@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;
}
System.out.println("현재 볼륨: " + volume);
}
}
package ch08.sec02;
public class RemoteControlEx {
public static void main(String[] args) {
RemoteControl rc;
rc = new Audio();
rc.setMute(true); // 무음 처리 현재 볼륨: 0
rc.setMute(false); // 무음 해제
rc = new Television();
rc.setVolume(7); // 현재 볼륨: 7
rc.setMute(true); // 무음 처리합니다. 현재 볼륨: 0
rc.setMute(false); // 무음 해제합니다. 현재 볼륨: 7
RemoteControl.changeBattery(); // 리모콘 건전지를 교환합니다.
}
}
구분 | 설명 |
---|---|
private 메서드 | 구현 객체가 필요한 메서드 |
privae 정적 메서드 | 구현 객체가 필요 없는 메서드 |
package ch08.sec07;
public interface Service {
default void defaultMethod() {
System.out.println("default void defaultMethod() --- ");
privateMethod();
privateStaticMethod();
System.out.println("--- default void defaultMethod()");
}
private void privateMethod() {
System.out.println("private void privateMethod() Call!!");
}
static void staticMethod() {
System.out.println("static void staticMethod() ---");
privateStaticMethod();
// privateMethod(); // 컴파일 에러 :Non-static method 'privateMethod()' cannot be referenced from a static context
System.out.println("--- static void staticMethod()");
}
private static void privateStaticMethod() {
System.out.println("private static void privateStaticMethod() Call!");
}
}
package ch08.sec07;
public class ServiceImpl implements Service{
}
package ch08.sec07;
public class ServiceEx {
public static void main(String[] args) {
Service service = new ServiceImpl();
service.defaultMethod();
/*
default void defaultMethod() ---
private void privateMethod() Call!!
private static void privateStaticMethod() Call!
--- default void defaultMethod()
*/
Service.staticMethod();
/*
static void staticMethod() ---
private static void privateStaticMethod() Call!
--- static void staticMethod()
*/
}
}
implements
키워드를 사용해 여러 개의 인터페이스를 구현할 수 있다.package ch08.sec08;
public interface RemoteControl {
void turnOn();
void turnOff();
}
package ch08.sec08;
public interface Searchable {
void search(String url);
}
package ch08.sec08;
public class SmartTelevision implements RemoteControl, Searchable{
@Override
public void turnOn() {
System.out.println("Tv를 켜다");
}
@Override
public void turnOff() {
System.out.println("Tv를 끄다");
}
@Override
public void search(String url) {
System.out.println(url + "을 검색하다");
}
}
package ch08.sec08;
public class MultiInterfaceImplEx {
public static void main(String[] args) {
RemoteControl rc = new SmartTelevision();
rc.turnOn(); // Tv를 켜다
rc.turnOff(); // Tv를 끄다
Searchable searchable = new SmartTelevision();
searchable.search("https://velog.io/"); // https://velog.io/을 검색하다
}
}
클래스와 달리 다중 상속을 허용한다.
package ch08.sec09;
public interface InterfaceC extends InterfaceA, InterfaceB{
void methodC();
}
package ch08.sec09;
public class InterfaceCImpl implements InterfaceC{
@Override
public void methodA() {
System.out.println("InterfaceCImpl - methodA() Call!");
}
@Override
public void methodB() {
System.out.println("InterfaceCImpl - methodB() Call!");
}
@Override
public void methodC() {
System.out.println("InterfaceCImpl - methodC() Call!");
}
}
package ch08.sec09;
public class ExtendsEx {
public static void main(String[] args) {
InterfaceCImpl impl = new InterfaceCImpl();
InterfaceA ia = impl;
ia.methodA(); // InterfaceCImpl - methodA() Call!
InterfaceB ib = impl;
ib.methodB(); // InterfaceCImpl - methodB() Call!
InterfaceC ic = impl;
ic.methodC(); // InterfaceCImpl - methodC() Call!
}
}
// A.java
public interface A {
}
// B.java
public class B implements A{
}
// C.java
public class C extends B{
}
public class PromotionEx {
public static void main(String[] args) {
B b = new B();
C c = new C();
A a;
a = b;
a = c;
}
}
package sec10.exam02;
public class CatingEx {
public static void main(String[] args) {
Vehicle vehicle = new Bus();
vehicle.run(); // 버스가 달린다.
// vehicle.checkFar(); // 컴파일 에러 : cannot find symbol
// 강제 타입 변환
Bus bus = (Bus) vehicle;
bus.run(); // 버스가 달린다.
bus.checkFare(); // 승차 요금을 확인한다.
}
}
(자동 타입 변환)
// Tire.java
public interface Tire {
void roll();
}
// HankookTire.java
public class HankookTire implements Tire{
@Override
public void roll() {
System.out.println("한국 타이어가 굴러갑니다.");
}
}
// KumhoTire.java
public class KumhoTire implements Tire {
@Override
public void roll() {
System.out.println("금호 타이어가 굴러갑니다.");
}
}
// Car.java
public class Car {
// 필드
Tire tire = new HankookTire();
void run() {
tire.roll();
}
}
public class CarEx {
public static void main(String[] args) {
Car car = new Car();
car.run(); // 한국 타이어가 굴러갑니다.
car.tire = new KumhoTire();
car.run(); // 금호 타이어가 굴러갑니다.
}
}
(자동 타입 변환)
// Vehicle.java
public interface Vehicle {
void run();
}
// Bus.java
public class Bus implements Vehicle{
@Override
public void run() {
System.out.println("버스가 달린다.");
}
public void checkFare() {
System.out.println("승차요금을 확인한다.");
}
}
// Taxi.java
public class Taxi implements Vehicle{
@Override
public void run() {
System.out.println("택시가 달린다.");
}
}
// Driver.java
public class Driver {
void drive(Vehicle vehicle) {
vehicle.run();
}
}
public class DriverEx {
public static void main(String[] args) {
Driver driver = new Driver();
driver.drive(new Bus()); // 버스가 달린다.
driver.drive(new Taxi()); // 택시가 달린다.
}
}
instanceof
연산자로 객체 타입을 확인한다.public class DriverEx {
public static void main(String[] args) {
Driver driver = new Driver();
ride(new Bus()); // 승차요금을 확인한다.
}
public static void ride(Vehicle vehicle) {
if (vehicle instanceof Bus) {
Bus bus = (Bus) vehicle;
bus.checkFare();
}
/* Java 12부터 사용 가능
if (vehicle instanceof Bus bus) {
bus.checkFare();
}
*/
}
}
// InterfaceA.java
public sealed interface InterfaceA permits InterfaceB {
void methodA();
}
// InterfaceB.java
public non-sealed interface InterfaceB extends InterfaceA {
void methodB();
}
// InterfaceC.java
public interface InterfaceC extends InterfaceB {
void methodC();
}
// ImplClass.java
public class ImplClass implements InterfaceC {
@Override
public void methodA() {
System.out.println("methodA() Call!!");
}
@Override
public void methodB() {
System.out.println("methodB() Call!!");
}
@Override
public void methodC() {
System.out.println("methodC() Call!!");
}
}
public class SealedExample {
public static void main(String[] args) {
ImplClass implClass = new ImplClass();
InterfaceA interfaceA = implClass;
interfaceA.methodA(); // methodA() Call!!
InterfaceB interfaceB = implClass;
interfaceB.methodA(); // methodA() Call!!
interfaceB.methodB(); // methodB() Call!!
InterfaceC interfaceC = implClass;
interfaceC.methodA(); // methodA() Call!!
interfaceC.methodB(); // methodB() Call!!
interfaceC.methodC(); // methodC() Call!!
}
}