중첩클래스(Nested Class) : 클래스(OuterClass) 내부에 다른 클래스(InnerClass)를 선언
외부클래스에서는 내부클래스로 객체를 생성하여 접근제한자에 상관없이 내부클래스의 필드 또는 메소드 참조 가능
내부클래스에서는 외부클래스의 필드 또는 메소드를 접근제한자에 상관없이 참조 가능
외부클래스에서 내부클래스의 필드 또는 메소드에 대한 직접적인 참조 불가능
내부클래스에서는 외부클래스의 필드 또는 메소드를 접근제한자에 상관없이 참조 가능
일반 중첩 클래스 : 컴파일 결과를 [외부클래스$내부클래스.class] 파일로 제공
private int outerNum; //필드 선언
public OuterOne() { } //기본생성자
public OuterOne(int outerNum) { //생성자 초기화
super();
this.outerNum = outerNum;
}
public int getOuterNum() { //getter, setter 메소드 선언
return outerNum;
}
public void setOuterNum(int outerNum) {
this.outerNum = outerNum;
}
public void displayOuter() {//메소드 선언
System.out.println("outerNum = "+outerNum);
//외부클래스에서 내부클래스의 필드 또는 메소드에 대한 직접적인 참조 불가능
//System.out.println("innerNum = "+innerNum);
//외부클래스에서는 내부클래스로 객체를 생성하여 접근제한자에 상관없이
//내부클래스의 필드 또는 메소드 참조 가능
InnerOne innerOne=new InnerOne(200);
System.out.println("innerNum = "+innerOne.innerNum);
}
public class InnerOne {
private int innerNum;//내부클래스 필드 선언
public InnerOne() { }//기본생성자
public InnerOne(int innerNum) { //생성자 초기화
super();
this.innerNum = innerNum;
}
public int getInnerNum() { //getter, setter 메소드 선언
return innerNum;
}
public void setInnerNum(int innerNum) {
this.innerNum = innerNum;
}
public void displayInner() {//메소드 선언
System.out.println("innerNum = "+innerNum); }}}
//내부클래스에서는 외부클래스의 필드 또는 메소드를 접근제한자에 상관없이 참조 가능
//System.out.println("outerNum = "+outerNum);
//displayOuter();
import nested.OuterOne.InnerOne;//import 자동생성
public class OuterOneApp {
public static void main(String[] args) {
OuterOne outerOne=new OuterOne(100);//OuterOne객체생성
outerOne.displayOuter();//outerNum = 100, innerNum = 200
//일반 중첩 클래스로 직접 객체 생성 불가능
//InnerOne innerOne=new InnerOne();
//외부클래스의 객체를 이용하여 일반 중첩 클래스의 객체 생성 가능
InnerOne innerOne=outerOne.new InnerOne(300);//InnerOne객체생성
innerOne.displayInner(); }}//innerNum = 300
정적 중첩 클래스 : static 제한자를 사용하여 클래스 선언
내부클래스의 정적필드는 객체 생성 없이 클래스로 접근하여 참조 가능
public class OuterTwo {
private int outerNum; //필드 선언
public OuterTwo() { } //기본생성자
public OuterTwo(int outerNum) { //생성자 초기화
super();
this.outerNum = outerNum;
}
public int getOuterNum() { //getter, setter 메소드 선언
return outerNum;
}
public void setOuterNum(int outerNum) {
this.outerNum = outerNum;
}
public void displayOuter() {//메소드 선언
System.out.println("outerNum = "+outerNum);
//외부클래스에서는 내부클래스로 객체를 생성하여 접근제한자에 상관없이
//내부클래스의 필드 또는 메소드 참조 가능
//InnerTwo innerTwo=new InnerTwo();
//System.out.println("innerNum = "+innerTwo.innerNum);
//내부클래스의 정적필드는 객체 생성 없이 클래스로 접근하여 참조 가능
//System.out.println("staticNum = "+InnerTwo.staticNum);
}
public static class InnerTwo {
private int innerNum;//필드선언
private static int staticNum=300;//정적필드선언
public InnerTwo () { } //기본생성자
public InnerTwo(int innerNum) { //생성자초기화
super();
this.innerNum = innerNum;
}
public int getInnerNum() { //getter, setter 메소드 선언
return innerNum;
}
public void setInnerNum(int innerNum) {
this.innerNum = innerNum;
}
public static int getStaticNum() {
return staticNum;
}
public static void setStaticNum(int staticNum) {
InnerTwo.staticNum = staticNum;
}
public void displayInner() {//메소드 선언
System.out.println("innerNum = "+innerNum);
System.out.println("staticNum = "+staticNum);
//내부클래스에서는 외부클래스의 필드 또는 메소드 참조 불가능
// → 외부클래스의 정적필드나 정적메소드는 참조 가능
//System.out.println("outerNum = "+outerNum); }}}
import nested.OuterTwo.InnerTwo;
public class OuterTwoApp {
public static void main(String[] args) {
OuterTwo outerTwo=new OuterTwo(100);//OuterTwo 객체 생성
outerTwo.displayOuter();//메소드 호출 - outerNum = 100
//정적 중첩 클래스는 직접 객체 생성 가능
InnerTwo innerTwo=new InnerTwo(200);
innerTwo.displayInner(); }}//innerNum = 200, staticNum = 300
public class OuterThree {
private int outerNum;//필드 선언
public OuterThree() { } //기본 생성자
public OuterThree(int outerNum) {//생성자 초기화
super();
this.outerNum = outerNum;
}
public int getOuterNum() { //getter, setter 메소드 선언
return outerNum;
}
public void setOuterNum(int outerNum) {
this.outerNum = outerNum;
}
public void displayOuter() {//displayOuter 메소드 선언
System.out.println("outerNum = "+outerNum);
//외부클래스에서 로컬클래스를 사용하여 객체 생성 불가능
//InnerThree innerThree=new InnerThree();
}
public void local() { //local 메소드 선언
class InnerThree { //로컬클래스(메소드 내부에 선언된 클래스)
int innerNum;
void displayInner() {
System.out.println("innerNum = "+innerNum);
}
}
InnerThree innerThree=new InnerThree();
innerThree.innerNum=200;
//System.out.println("innerThree.innerNum = "+innerThree.innerNum);
innerThree.displayInner(); }}
public class OuterThreeApp {
public static void main(String[] args) {
OuterThree outerThree=new OuterThree(100);
outerThree.displayOuter();//100
outerThree.local(); }}//200
public interface Anonymous {
void display(); }
public class AnonymousApp {
public static void main(String[] args) {
//인터페이스를 이용하여 참조변수 생성은 가능하지만 객체 생성 불가능
//자식클래스로 객체를 생성하여 인터페이스 참조변수에 객체 저장 가능
//Anonymous anonymous=new Anonymous();
//익명의 내부클래스를 선언하고 자식클래스로 익명객체를 생성하여
//인터페이스 참조변수에 저장
Anonymous anonymous=new Anonymous() {
@Override
public void display() {
System.out.println("익명의 내부클래스의 오버라이드 메소드 호출"); }};
anonymous.display(); }}