클래스들이 구현해야하는 메서드들의 집합
클래스를 만들기위한 기본 뼈대.
추상 클래스 - 구현된 메소드와 필드를 가질수 있음, 단일 상속만 가능
인터페이스 - 메서드의 시그니쳐만 정의(이름, 변환형, 매개변수), 다중 상속 가능
인터페이스내의 메서드는 public과 abstract로 간주(생략가능)
인터페이스는 상수만 가질 수 있음(public, static, final로 자동으로 선언)
public interface TestInterface {
int a = 0; //자동으로 public static final
public abstract void testMethod();
void testMethod2(); //기본적으로 public abstract 간주
}
인터페이스가 public과 abstract 만 가능한 건 아님
default와 static은 가능
public interface TestInterface {
default void defaultTestMethod() {
System.out.println("Default Method is available in Interface");
}
static void staticTestMethod() {
System.out.println("Static Method is also available in Interface");
}
}
package lec1.test.review;
public class TestClass implements TestInterface {
@Override
public void defaultTestMethod() {
System.out.println("Default Method is available to override");
TestInterface.super.defaultTestMethod(); //super키워드를 통해 인터페이스 내의 default메소드 호출 가능
}
}
package lec1.test.review;
public class TestMain {
public static void main(String[] args) {
TestClass t = new TestClass();
t.defaultTestMethod(); //Override된 메소드 호출
TestInterface.staticTestMethod(); // Static이므로 인터페이스 이름을 통해 바로 접근 가능
}
}
클래스가 여러 인터페이스를 구현가능(like 다중상속)
class A implements intesrfaceA, interfaceB
interface C extends interfaceA, interfaceB
인터페이스가 인터페이스를 다중상속가능
단, 이를 구현하는 class는 모든 메서드를 구현해야한다.
class a extends b implements c
//c : void sleep();, method1();
//b : public void sleep();
클래스의 메서드가 인터페이스의 메서드보다 우선
c에 있는 sleep()을 b가 구현하고 a가 b를 상속받는다.
⇒ a는 method1()만 구현하면 된다. (부모클래스가 인터페이스를 이미 구현하고 상속한걸로 인식)
inner class는 outer 클래스의 멤버로 정의
inner class에서 outer변수는 사용이 가능하다
(변수명이 같다면 inner우선 ⇒ this.변수명이 자동으로 붙음)
outer변수를 사용하려면 outer클래스명.this.변수명 으로 사용
outer class에서 inner class의 변수에는 접근이 불가능(static 제외)
⇒ inner class의 객체를 생성후에 접근해야함
inner class의 인스턴스를 생성하려면 outer class의 인스턴스를 먼저 생성해야함
OuterClass out = new OuterClass();
OuterClass.InnerClass in = out.new InnerClass();
OuterClass.InnerClass in2 = new OuterClass().new InnerClass();
Outer class의 인스턴스와 독립적으로 존재
Outer class의 정적멤버에만 접근이 가능
Outer class의 인스턴스 없이 독립적으로 생성가능
static이 아닌 inner class는 메모리 누수를 일으킬 우려가 있음
일반 Inner Class는 Outer Class에 대한 참조를 유지하기 때문
Inner Class의 인스턴스가 생성되는 순간 Outer 클래스의 참조를 가진다.
⇒ Outer Class의 this 참조를 자동으로 포함하기 때문에 Outer class가 더이상 필요 없더라고 GC가 이를 해제하지 못함
⇒ Inner class의 객체가 Outer class의 객체보다 오래 유지되면 메모리 누수 발생 가능
public class OuterClass {
private int ramdomNumber = 45678;
public int getRamdomNumber() {
return ramdomNumber;
}
public class InnerClass {
public void trash() {
System.out.println(ramdomNumber + "is still available");
}
}
}
public class TestMain {
public static void main(String[] args) {
OuterClass outerInstance = new OuterClass();
OuterClass.InnerClass innerInstance = outerInstance.new InnerClass();
System.out.println(outerInstance.getRamdomNumber());
innerInstance.trash();
outerInstance = null;
//System.out.println(outerInstance.getRamdomNumber());
innerInstance.trash();
}
}
출력:
45678
45678is still available
45678is still available
Outer 인스턴스가 null 로 변하고 나서도 Inner 인스턴스는 값을 계속 참조하여 호출이 가능함 → 메모리누수!
💡
메모리 누수를 방지하기 위해 특별한 경우가 아니라면(외부클래스의 멤버 사용 등) static으로 생성 요망