웹사이트 검색

자바 내부 클래스


Java 내부 클래스는 다른 클래스의 본문 내부에 정의됩니다. Java 내부 클래스는 개인, 공용, 보호 또는 기본 액세스로 선언될 수 있지만 외부 클래스는 공용 또는 기본 액세스만 가질 수 있습니다. Java Nested 클래스는 두 가지 유형으로 나뉩니다.

두 가지 특수한 종류의 Java 내부 클래스가 있습니다.

  1. local inner class

    If a class is defined in a method body, it’s known as local inner class. Since the local inner class is not associated with Object, we can’t use private, public or protected access modifiers with it. The only allowed modifiers are abstract or final. A local inner class can access all the members of the enclosing class and local final variables in the scope it’s defined. Additionally, it can also access a non-final local variable of the method in which it is defined, but it cannot modify them. So if you try to print non-final local variable’s value it will be allowed but if you try to change its value from inside method local inner class, you will get compile time Error. Local inner class can be defined as:

    package com.journaldev.innerclasses;
    
    public class MainClass {
    
    	private String s_main_class;
    
    	public void print() {
    		String s_print_method = "";
    		// local inner class inside the method
    		class Logger {
    			// able to access enclosing class variables
    			String name = s_main_class; 
    			// able to access non-final method variables
    			String name1 = s_print_method; 
    
    			public void foo() {
    				String name1 = s_print_method;
    				// Below code will throw compile time error:
    				// Local variable s_print_method defined in an enclosing scope must be final or effectively final 
    				// s_print_method= ":";
    			}
    		}
    		// instantiate local inner class in the method to use
    		Logger logger = new Logger();
    
    	}
    }
    

    We can define a local inner class inside any block too, such as static block, if-else block etc. However, in this case, the scope of the class will be very limited.

    public class MainClass {
    
    	static {
    		class Foo {
    			
    		}
    		Foo f = new Foo();
    	}
    	
    	public void bar() {
    		if(1 < 2) {
    			class Test {
    				
    			}
    			Test t1 = new Test();
    		}
    		// Below will throw error because of the scope of the class
    		//Test t = new Test();
    		//Foo f = new Foo();
    	}
    }
    
  2. anonymous inner class

    A local inner class without name is known as anonymous inner class. An anonymous class is defined and instantiated in a single statement. Anonymous inner class always extend a class or implement an interface. Since an anonymous class has no name, it is not possible to define a constructor for an anonymous class. Anonymous inner classes are accessible only at the point where it is defined. It’s a bit hard to define how to create an anonymous inner class, we will see it’s real-time usage in the test program below.

다음은 Java 내부 클래스, 정적 중첩 클래스, 로컬 내부 클래스 및 익명 내부 클래스를 정의하는 방법을 보여주는 Java 클래스입니다. OuterClass.java

package com.journaldev.nested;

import java.io.File;
import java.io.FilenameFilter;

public class OuterClass {
    
    private static String name = "OuterClass";
    private int i;
    protected int j;
    int k;
    public int l;

    //OuterClass constructor
    public OuterClass(int i, int j, int k, int l) {
        this.i = i;
        this.j = j;
        this.k = k;
        this.l = l;
    }

    public int getI() {
        return this.i;
    }

    //static nested class, can access OuterClass static variables/methods
    static class StaticNestedClass {
        private int a;
        protected int b;
        int c;
        public int d;

        public int getA() {
            return this.a;
        }

        public String getName() {
            return name;
        }
    }

    //inner class, non-static and can access all the variables/methods of the outer class
    class InnerClass {
        private int w;
        protected int x;
        int y;
        public int z;

        public int getW() {
            return this.w;
        }

        public void setValues() {
            this.w = i;
            this.x = j;
            this.y = k;
            this.z = l;
        }

        @Override
        public String toString() {
            return "w=" + w + ":x=" + x + ":y=" + y + ":z=" + z;
        }

        public String getName() {
            return name;
        }
    }

    //local inner class
    public void print(String initial) {
        //local inner class inside the method
        class Logger {
            String name;

            public Logger(String name) {
                this.name = name;
            }

            public void log(String str) {
                System.out.println(this.name + ": " + str);
            }
        }

        Logger logger = new Logger(initial);
        logger.log(name);
        logger.log("" + this.i);
        logger.log("" + this.j);
        logger.log("" + this.k);
        logger.log("" + this.l);
    }

    //anonymous inner class
    public String[] getFilesInDir(String dir, final String ext) {
        File file = new File(dir);
        //anonymous inner class implementing FilenameFilter interface
        String[] filesList = file.list(new FilenameFilter() {

            @Override
            public boolean accept(File dir, String name) {
                return name.endsWith(ext);
            }

        });
        return filesList;
    }
}

다음은 Java에서 내부 클래스를 인스턴스화하고 사용하는 방법을 보여주는 테스트 프로그램입니다. InnerClassTest.java

package com.journaldev.nested;

import java.util.Arrays;
//nested classes can be used in import for easy instantiation
import com.journaldev.nested.OuterClass.InnerClass;
import com.journaldev.nested.OuterClass.StaticNestedClass;

public class InnerClassTest {

    public static void main(String[] args) {
        OuterClass outer = new OuterClass(1,2,3,4);
        
        //static nested classes example
        StaticNestedClass staticNestedClass = new StaticNestedClass();
        StaticNestedClass staticNestedClass1 = new StaticNestedClass();
        
        System.out.println(staticNestedClass.getName());
        staticNestedClass.d=10;
        System.out.println(staticNestedClass.d);
        System.out.println(staticNestedClass1.d);
        
        //inner class example
        InnerClass innerClass = outer.new InnerClass();
        System.out.println(innerClass.getName());
        System.out.println(innerClass);
        innerClass.setValues();
        System.out.println(innerClass);
        
        //calling method using local inner class
        outer.print("Outer");
        
        //calling method using anonymous inner class
        System.out.println(Arrays.toString(outer.getFilesInDir("src/com/journaldev/nested", ".java")));
        
        System.out.println(Arrays.toString(outer.getFilesInDir("bin/com/journaldev/nested", ".class")));
    }

}

다음은 위의 Java 내부 클래스 예제 프로그램의 출력입니다.

OuterClass
10
0
OuterClass
w=0:x=0:y=0:z=0
w=1:x=2:y=3:z=4
Outer: OuterClass
Outer: 1
Outer: 2
Outer: 3
Outer: 4
[NestedClassTest.java, OuterClass.java]
[NestedClassTest.class, OuterClass$1.class, OuterClass$1Logger.class, OuterClass$InnerClass.class, OuterClass$StaticNestedClass.class, OuterClass.class]

OuterClass가 컴파일되면 내부 클래스, 로컬 내부 클래스 및 정적 중첩 클래스에 대해 별도의 클래스 파일이 생성됩니다.

Java 내부 클래스의 이점

  1. 클래스가 하나의 클래스에만 유용하다면 클래스를 중첩하여 함께 유지하는 것이 좋습니다. 수업 패키징에 도움이 됩니다.
  2. Java 내부 클래스는 캡슐화를 구현합니다. 내부 클래스는 외부 클래스 개인 멤버에 액세스할 수 있으며 동시에 외부 세계에서 내부 클래스를 숨길 수 있습니다.
  3. 최상위 클래스 내에 작은 클래스를 유지하면 코드가 사용되는 위치에 더 가깝게 배치되고 코드를 더 읽기 쉽고 유지 관리할 수 있습니다.

이것이 자바 내부 클래스의 전부입니다.