Java 내부클래스

김정훈·2024년 4월 22일

Java

목록 보기
22/48

내부클래스

클래스 안에 클래스가 정의된 형식

1. 인스턴스 내부 클래스

  • 멤버 변수, 멤버 메서드와 비슷한 성격
  • 외부 클래스의 객체 생성 이후 접근 가능한 클래스

외부 내부 변수 접근

  • 내부클래스에서는 외부클래스를 직접적으로 접근가능하다.
  • 내부에 외부의 클래스에 존재하는 인스턴스변수와 변수명이 같은 경우 내부클래스의 인스턴스변수를 호출.
  • 반대로 Outer.this는 외부클래스의 인터턴스변수를 호출해준다.
public class Outer {
	int num1 = 10;
    class Inner{
    	int num2 = 20;
        public void mothod(){
        	System.our.println(Outer.this.num1); //외부 클래스의 num1로 출력한다.
            System.out.println("인스턴스 내부 클래스에서 호출");
            System.our.println(num1 + num2);//내부클래스에서는 외부클래스를 직접적으로 접근가능하다. 또한 내부에 외부의 클래스에 존재하는 인스턴스변수와 변수명이 같은 경우 내부클래스의 인스턴스변수를 호출.
        }
    }
}
------------------------------------------
public class Ex01 {
    public static void main(String[] args) {
        Outer outer = new Outer(); //외부 클래스 객체생성
        Outer.Inner inner = outer.new Inner();
        inner.mothod();
    }
}

2. 정적 내부 클래스

  • 정적 변수, 정적 메서드와 비슷한 성격
  • 객체생성과 상관 X, 접근 가능(외부 클래스명으로 접근 가능)
public class Outer {
    int num1 = 10;
    static num2 = 20;
    static class Inner {
        public void method(){
            System.out.println("정적 내부 클래스에서 호출");
            //System.out.println(num1); //Outer클래스의 객체가 되든 관련 x 접근x
             System.out.println(num2); //num2가 static 정적 변수이기 떄문에 접근가능
        }
    }
}
--------------------------------------------
public class Ex01 {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer.Inner();
        //외부클래스의 객체생성 상관없이 접근이 가능
        inner.method();
    }
}

3. 지역내부 클래스

  • 메서드 안에 정의된 클래스
  • 메서드 안에서 내부클래스의 객체를 생성하고 메서드를 호출해야한다.
public class Outer {
    public void method(){
        class Inner{
            public void method(){
                System.out.println("지역 내부 클래스에서 호출");
            }
        }
        Inner inner = new Inner();
        inner.method();
    }
}
-----------------------------
public class Ex01 {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.method();
    }
}

4. 지역내부 인터페이스, 추상클래스

지역내부에서는 인터페이스, 추상클래스를 객체로 생성할수있다.

방법
1. 지역 내부, 클래스의 멤버변수에서 객체 생성
2. 미구현된 메서드의 재정의

인터페이스
public interface Calculator {
    int add(int num1, int nu2);
}

클래스
public class Outer {
    public void method(){
        Calculator cal = new Calculator(){ //1. 지역 내부, 클래스의 멤버변수에서 객체 생성
            public int add(int num1, int num2) { //2. 미구현된 메서드의 재정의
                return num1 + num2;
            }
        };

        int result = cal.add(10,20);
        System.out.println(result);
    }
}

메인함수
public class Ex01 {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.method(); //실행되면 객체가 생성된다.
    }
}

1) 지역내부의 인터페이스, 추상클래스 객체 외부접근

1) 지역변수의 자료형을 인터페이스,추상클래스 자료형으로
2) 리턴값으로 인터페이스,추상클래스의 객체를 리턴한다.

  • 자료형이 Caluculator인 이유는 outer.mothod Calculator참조자료형인 지역변수 cal을 반환하기떄문이다.
  • cal 지역변수에는 객체의 주소값을 가지고있다.
  • 힙에 존재하는 Outer클래스 객체가 참조가 되어 있지않으면 가비지 콜랙터가 제거
  • 값을 할당해서 참조를 시키면 제거가 되지않음.
클래스
public class Outer {
	public Calculator method(){
    	private Calculator cal = new Calculator() 			{
        @Override
        	public int add(int num1, int num2) {
            	return num1 + num2;
        }
    };
    return cal;
}
----------------------------------------------
public class Ex01 {
    public static void main(String[] args) {
        Outer outer = new Outer();
        Calculator cal = outer.method();
        //자료형이 Caluculator인 이유는 outer.mothod가 Calculator참조자료형인 지역변수 cal을 반환하기떄문이다.
        //cal 지역변수에는 객체의 주소값을 가지고있다.
        //힙에 존재하는 Outer클래스 객체가 참조가 되어 있지않으면 가비지 콜랙터가 제거
		// 값을 할당해서 참조를 시키면 제거가 되지않음.
        int result = cal.add(10,20);
        System.out.println(result);
    }
}

2) 지역내부 인터페이스 객체 매개변수의 상수화

  • 매개변수인 num3에 30을 넣음
  • 매개변수인 num3은 지역변수이다.
  • 메서드가 return될경우 값이 초기화되는게 정상이다.
    (outer.method가 실행되면서 이미 num는 초기화되어야한다.)
  • 그러나 cal.add(10,20)을 실행했을때 num3는 값이 없어야하지만, 아직 존재중이다.
  • 그이유는 num3이 상수화 되었기 때문이다
  • 이유 : 데이터가 유실되지않기위해서(final int num3)
public class Outer {
    public Calculator Method(int num3){
    // 반환값을 Calculator 참조자료형으로 변환
        Calculator cal = new Calculator() {
        //지역변수(스택) = 객체 생성(힙에저장)
            public int add(int num1, int num2){
                return num1 + num2 + num3;
            }
        };
        return cal;  
        //Calculator 참조자료형인 cal지역변수는 생성된객체의 주소를 갖고있기 때문에 객체의 주소를 반환시킴, 객체의 주소값을 외부에 리턴함으로써 외부에서도 사용가능하게한다.
    }
}
----------------------------------------------
메인함수
public class Ex01 {
    public static void main(String[] args) {
        Outer outer = new Outer();
        Calculator cal = outer.method(30);
        //매개변수인 num3에 30을 넣음
        //매개변수인 num3은 지역변수이다.
        //메서드가 return될경우 값이 초기화되는게 정상이다.
        //(outer.method가 실행되면서 이미 num는 초기화되어야한다.)
        
        //그렇지만 cal.add(10,20)을 실행했을때 num3는 존재하고있다.
        // 그이유는 num3이 상수화(되었기 때문이다. 이유(제거되지않기 위해서) (final)
        int result = cal.add(10,20);
        System.out.println(result);
    }
}

3) 익명 지역내부클래스

Calculator cal = new Calculator()은 참조변수 cal을 생성했기때문에 4byte씩 메모리를 사용한다. 그렇기 때문에 익명함수로 객체의 주소를 참조변수를 통해 반환하지않고 바로 반환한다.

public class Outer {
	public Calculator method(int num3){
		return new Calculator(){
    		public Calculator method1(int num3){
                return num1+num2+num3;
            }
        };
    }
}

----------------------------------
public class Ex01 {
    public static void main(String[] args) {
        Outer outer = new Outer();
        Calculator cal = outer.method1(30);
        int result1  = cal.add(10,20);
        System.out.println(result1);

    }
}                      

4) 메서드 동적오버라이딩

함수내부에서 객체를 생성하면서 오버라이딩이 가능

A클래스에서 "메서드"를 출력하는 메서드를 정의했지만, 메인함수에서 A클래스를 객체로 생성하면서 오버라이딩을 했다. 이로 인해 "메서드"가아닌 "오버라이딩"이 출력된다.

public class A {
    public void method(){
        System.out.println("메서드");
    }
}
------------------------------------
public class Ex04 {
    public static void main(String[] args) {
        A a = new A(){ //객체를 생성하면서 오버라이딩
            public void method(){
                System.out.println("오버라이딩");
            }
        };
        a.method();
    }
}
profile
안녕하세요!

0개의 댓글