1. 인터페이스(interface)
: 서로 관계가 없는 물체들이 상호작용을 하기 위해서 사용하는 장치나 시스템
자체적으로 타입의 역할은 할 수 있지만 구현은 없어서 이거 자체가 객체를 생성해놓지는 못함.
=> 반드시 구현해서 사용해야힘.
- 만들기
추상 메소드와 상수 정의
public interface TV{
public int MAX_VOLUME = 100;
public int MIN_VOLUME = 0;
public void turnOn();
public void turnOff();
public void changeVolume(int volume);
public void changeChannel(int channel);
}
인터페이스에서 변수를 선언하면 컴파일시 자동으로 아래와 같이 바뀐다.
public static final int MAX_VOLUME = 100;
public static final int MIN_VOLUME = 0;
인터페이스에서 정의된 메소드는 모두 추상 메소드이다.
위에서 선언된 모든 메소드는 컴파일 시에 다음과 같이 자동으로 변경된다.
public abstract void on();
public abstract void off();
public abstract void volume(int value);
public abstract void channel(int number);
- 사용하기
인터페이스는 사용할때 해당 인터페이스를 구현하는 클래스에서 implements 키워드를 이용한다.
public class LedTV implements TV{
public void on(){
System.out.println("켜다");
}
public void off(){
System.out.println("끄다");
}
public void volume(int value){
System.out.println(value + "로 볼륨조정하다.");
}
public void channel(int number){
System.out.println(number + "로 채널조정하다.");
}
}
인터페이스가 가지고 있는 메소드를 하나라도 구현하지 않는다면 해당 클래스는 추상클래스가 된다.
(추상클래스는 인스턴스를 만들 수 없음)
public class LedTVExam{
public static void main(String args[]){
TV tv = new LedTV();
tv.on();
tv.volume(50);
tv.channel(6);
tv.off();
}
}
참조변수의 타입으로 인터페이스를 사용할 수 있다.
이 경우 인터페이스가 가지고 있는 메소드만 사용할 수 있다.
만약 TV인터페이스를 구현하는 LcdTV를 만들었다면
위의 코드에서 new LedTV부분만 new LcdTV로 변경해도 똑같이 프로그램이 동작할 것다.
동일한 인터페이스를 구현한다는 것은 클래스 사용법이 같다는 것을 의미한다.
클래스는 이러한 인터페이스를 여러개 구현할 수 있다.
2. 인터페이스의 default method
JAVA 8이 등장하면서 interface에 대한 정의가 몇 가지 변경되었음.
기존에는 추상메소드만 가질 수 있었지만 JAVA 8부터는 defalt랑 static메소드 정의 가능해짐.
=> interface가 defalt로 선언되면 메소드를 구현할 수 있게 됨.
- default 메소드
인터페이스가 default키워드로 선언되면 메소드가 구현될 수 있다.
또한 이를 구현하는 클래스는 default메소드를 오버라이딩 할 수 있다.
public interface Calculator {
public int plus(int i, int j);
public int multiple(int i, int j);
default int exec(int i, int j){ //default로 선언함으로 메소드를 구현할 수 있다.
return i + j;
}
}
//Calculator인터페이스를 구현한 MyCalculator클래스
public class MyCalculator implements Calculator {
@Override
public int plus(int i, int j) {
return i + j;
}
@Override
public int multiple(int i, int j) {
return i * j;
}
}
public class MyCalculatorExam {
public static void main(String[] args){
Calculator cal = new MyCalculator();
int value = cal.exec(5, 10);
System.out.println(value);
}
}
인터페이스가 변경이 되면, 인터페이스를 구현하는 모든 클래스들이 해당 메소드를 구현해야 하는 문제가 있다.
이런 문제를 해결하기 위하여 인터페이스에 메소드를 구현해 놓을 수 있도록 하였다.
- static메소드
public interface Calculator {
public int plus(int i, int j);
public int multiple(int i, int j);
default int exec(int i, int j){
return i + j;
}
public static int exec2(int i, int j){ //static 메소드
return i * j;
}
}
//인터페이스에서 정의한 static메소드는 반드시 인터페이스명.메소드 형식으로 호출해야한다.
public class MyCalculatorExam {
public static void main(String[] args){
Calculator cal = new MyCalculator();
int value = cal.exec(5, 10);
System.out.println(value);
int value2 = Calculator.exec2(5, 10); //static메소드 호출
System.out.println(value2);
}
}
인터페이스에 static 메소드를 선언함으로써,
인터페이스를 이용하여 간단한 기능을 가지는 유틸리티성 인터페이스를 만들 수 있게 되었다.
3. 내부클래스
: 클래스 안에 선언된 클래스
어느 위치에 선언하느냐에 따라서 4가지 형태가 있을 수 있음
1) 중첩클래스 혹은 인스턴스 클래스
== 클래스 안에 인스턴스 변수, 즉 필드를 선언하는 위치에 선언되는 경우.
내부에 있는 Cal객체를 생성하기 위해서는,
밖에는 InnerExam1의 객체를 만든 후에 InnerExam1.Cal cal = t.new Cal();과 같은 방법으로 Cal객체를 생성한 후 사용한다.
public class InnerExam1{
class Cal{
int value = 0;
public void plus(){
value++;
}
}
public static void main(String args[]){
InnerExam1 t = new InnerExam1();
InnerExam1.Cal cal = t.new Cal();
cal.plus();
System.out.println(cal.value);
}
}
2) 정적 중첩 클래스 또는 static 클래스
== 내부 클래스가 static으로 정의된 경우
필드 선언할 때 스태틱한 필드로 선언한 것과 같다.
이 경우에는 InnerExam2객체를 생성할 필요없이 new InnerExam2.Cal() 로 객체를 생성할 수 있다.
public class InnerExam2{
static class Cal{
int value = 0;
public void plus(){
value++;
}
}
public static void main(String args[]){
InnerExam2.Cal cal = new InnerExam2.Cal();
cal.plus();
System.out.println(cal.value);
}
}
3) 지역 중첩 클래스 또는 지역 클래스
== 메소드 안에 클래스를 선언한 경우
메소드 안에서 해당 클래스를 이용할 수 있다.
public class InnerExam3{
public void exec(){
class Cal{
int value = 0;
public void plus(){
value++;
}
}
Cal cal = new Cal();
cal.plus();
System.out.println(cal.value);
}
public static void main(String args[]){
InnerExam3 t = new InnerExam3();
t.exec();
}
}
4) 익명클래스, 익명 중첩클래스
익명 중첩 클래스==익명 클래스==내부 클래스
//추상클래스 Action
public abstract class Action{
public abstract void exec();
}
//추상클래스 Action을 상속받은 클래스 MyAction
public class MyAction extends Action{
public void exec(){
System.out.println("exec");
}
}
//MyAction을 사용하는 클래스 ActionExam
public class ActionExam{
public static void main(String args[]){
Action action = new MyAction();
action.exec();
}
}
//MyAction을 사용하지 않고 Action을 상속받는 익명 클래스를 만들어서 사용하도록 수정하면
public class ActionExam{
public static void main(String args[]){
Action action = new Action(){
public void exec(){
System.out.println("exec");
}
};
action.exec();
}
}
생성자 다음에 중괄호 열고 닫고가 나오면,
해당 생성자 이름에 해당하는 클래스를 상속받는 이름없는 객체를 만든다는 것을 뜻한다.
괄호 안에는 메소드를 구현하거나 메소드를 추가할 수 있다.
이렇게 생성된 이름 없는 객체를 action이라는 참조변수가 참조하도록 하고, exec()메소드를 호출.
익명클래스를 만드는 이유는 Action을 상속받는 클래스를 만들 필요가 없을 경우이다.
Action을 상속받는 클래스가 해당 클래스에서만 사용되고 다른 클래스에서는 사용되지 않는 경우이다.
'Java > 기초 공부' 카테고리의 다른 글
| 자바 라이브러리 (0) | 2025.11.26 |
|---|---|
| int와 Integer (0) | 2025.11.26 |
| 상속(2) - 부모생성자, 오버라이딩, 클래스 형변환 (0) | 2025.11.20 |
| 상속(1) - 상속, 접근제한자, 추상클래스 (0) | 2025.11.20 |
| 클래스 다듬기 - 생성자, this, 오버로딩, 패키지 (0) | 2025.11.20 |