JAVA

열 여섯번째, 내부 클래스

seung_ho_choi.s 2023. 6. 6. 23:25
728x90

개요: 6개월 동안 미룬 드디어 내부클래스를 쓸 차례이다.

 

 

내부 클래스

전체적인 요약은 다음과 같다. 

 

인스턴스 내부 클래스

class OutClass {

    int num = 10;

    class InClass {

    }
}

public class InnerTest {
    public static void main(String[] args) {

    }
}

저 InClass가 기본적인 내부클래스이다. 

이때 여기서

class OutClass {

    private int num = 10;
    private static int sNum=20;
    private InClass inClass;

    public OutClass(){
        inClass=new InClass();
        System.out.println(inClass.inNum);
        inClass.inTest();
    }
    class InClass {
        int inNum=20;
        // static int a=10;
        void inTest(){
            System.out.println(num);
            System.out.println(sNum);
        }

    }
}

public class InnerTest {
    public static void main(String[] args) {
        OutClass outClass= new OutClass();

      
    }
}

다음과 같이 내부 클래스안에서는 static 사용 불가하지만 밖에 클래스 static선언된것은  쓸 수 있다.  

내부 클래스 생성자를 선언할려면 외부 생성자가 먼저 선언 되야지 가능하다. 

호출할려면 private으로 될때는 다음과 같다. 

 

class OutClass {
    private int num = 10;
    private static int sNum=20;
   InClass inClass;
    public OutClass(){
        inClass=new InClass();
        System.out.println(inClass.inNum);
        inClass.inTest();
    }
    class InClass {
        int inNum=20;
        // static int a=10;
        void inTest(){
            System.out.println(num);
            System.out.println(sNum);
        }
    }
}
public class InnerTest {
    public static void main(String[] args) {
        OutClass outClass= new OutClass();
        outClass.inClass.inTest();
    }
}

private inclass를 해제 하면 다음과 같이 main 함수에서 불러올 수 있다. 

public class InnerTest {
    public static void main(String[] args) {
        OutClass outClass= new OutClass();
        OutClass.InClass inClass=outClass.new InClass();

    }
}

main 함수에서 내부클래스를 선언하고 싶으면 다음과 같다. 

 

정적내부클래스

lass OutClass {
    int num=3;
    static int sNUm=4;
    static class InStaticClass{
        int iNum=100;
        static int sInNum=200;

        void inTest(){
            num+=9; // 오류
            sNUm+=9; // 스태틱 필드
            sInNum+=9; // 스태틱 클래스 필드
        }
        static void sTest(){
            iNum+=4; //오류 
            sInNum+=4; //스태틱 클래스 필드
        }
    }
}

정적 내부 클래스는 외부클래스의 생성과 상관없이 쓸 수 있다. 하지만 외부 클래스의 필드는 사용할 수 없다.

이유는 다 알거라고 믿는다!! 

또한 정적 내부 클래스 안에 생성된 정적 메소드 또한 static 으로 붙여진 필드이외에 일반적인 필드는 

사용불가능하다. 

 

public class InnerTest {
    public static void main(String[] args) {
        OutClass outClass= new OutClass();
        OutClass.InStaticClass inStaticClass = new OutClass.InStaticClass();
        inStaticClass.inTest();
        OutClass.InStaticClass.sTest();
    }
}

불러오는 방법은 다음과 같다. 

static 클래스안에 일반 메서드는 3번째줄! 

static 클래스안에 static 메서드는 4번째줄이다!! 

 

지역내부클래스

class Outer {
    int outNum = 100;
    static int sNum = 200;



    public Runnable getRunnable() { // 쓰레드 생성할때 사용하는거
        int localNum = 100;
        class MyRunnable implements Runnable {

            @Override
            public void run() {
                localNum+=9; //오류
                System.out.println(outNum);
                System.out.println(sNum);
                System.out.println(localNum);
            }
        }

        return new MyRunnable();
    }
}

public class LocalInnerTest {
    public static void main(String[] args) {
        Outer outer =new Outer();
        outer.getRunnable().run();
    }
}

runnable 은 쓰레드를 생성할때 쓰인다고 한다. 일반적인 이름으로 지은 메서드는 다음과 같이 진행이 안된다.

추가로 localNum+=9오류가 왜 뜨냐면 메서드는 호출되고 사라지기 지고 애초에  localNum+=9 는 지역 내부

클래스 안에 있기 때문에 따로 생성되서 그런거라고 한다.  

즉 지역변수만 그런거고 사용할 수 있지만 변화 시킬수 없다. 인스턴스 변수는 가능! 

 

public Runnable getRunnable() { // 쓰레드 생성할때 사용하는거

    return new Runnable() {
        int localNum = 5;

        @Override
        public void run() {
            System.out.println(outNum);
            System.out.println(sNum);
            System.out.println(localNum);
        }
    };
}

다음과 같이 바꿀 수 있다 왜냐하면 클래스가 쓸데가 없기 때문에!

 

 

익명내부클래스

class Outer {
    int outNum = 100;
    static int sNum = 200;

    Runnable runnable =new Runnable() {
        @Override
        public void run() {
            System.out.println("runnable");
        }
    };
    
}

public class LocalInnerTest {
    public static void main(String[] args) {
        Outer outer =new Outer();
        outer.runnable.run();
    }
}

 

하나의 추상클래스나 인터페이스를 구현할 수 있다. 흠 이건 좀 어렵다... 

추가하겠다.

- 이친구는 이름이 없는 객체로 명시적으로 클래스를 선언하지 않기 때문에 쉽게 객체를 생성할 수 있다. 

- 익명 객체는 필드값, 로컬 변수값, 매개 변수값으로 주로 사용한다. 

- 클래스를 상속하거나 인터페이스를 구현해야만 사용할 수 있다. 

 

Tire 클래스

public class Tire {
    public void roll(){
        System.out.println("일반 타이어가 잘 굴러갑니다.");
    }
}

Car 클래스

public class Car {
    Tire tire1 =new Tire();
    Tire tire2=new Tire(){
        @Override
        public void roll(){
            System.out.println("객체1 굴러간다.");
        }
    };

    public void run1(){
        tire1.roll();
        tire2.roll();
    }

    public void run2(){
        Tire tire3=new Tire(){
            @Override
            public void roll() {
                System.out.println("객체2 굴러간다.");
            }
        };
        tire3.roll();
       }

    public void run3(Tire tire){
        tire.roll();
    }

}

 

 실행 클래스

public class CarExample {
    public static void main(String[] args) {
        Car car=new Car();
        car.run1();
        car.run2();
        car.run3(new Tire(){
            @Override
            public void roll(){
                System.out.println("객체3 이굴러간다.");
            }
        });
    }
}
728x90