>  기사  >  Java  >  Java 내부 클래스 예제 분석

Java 내부 클래스 예제 분석

WBOY
WBOY앞으로
2023-04-23 14:43:14571검색

    1. 내부 클래스의 개념 및 분류

    클래스가 다른 클래스 내부 또는 인터페이스 내부 또는 메소드 본문 내부에서 정의되면 이 클래스를 내부 클래스라고 부를 수도 있습니다. 내부 클래스가 위치합니다. 주변 클래스의 경우 클래스, 인터페이스 및 메소드에 정의된 내부 클래스 외에도 new 키워드를 사용하여 익명 클래스의 객체를 생성하는 특수 내부 클래스도 있습니다. 클래스는 실제로 내부 클래스입니다. 특히 PriorityQueue 객체 생성과 같이 생성자 인수를 전달하여 객체를 생성하는 데 자주 사용되는 익명 내부 클래스입니다.

    클래스가 다른 클래스 내부 또는 인터페이스 내부에 정의되어 있고 정적 수정이 없는 경우 내부 클래스를 인스턴스 내부 클래스라고 합니다. 정적 수정이 사용된 경우 내부 클래스를 정적 ​​내부 클래스(중첩 클래스)라고 합니다. ) , 코드 블록 내부, 특히 메소드 본문 내부에 클래스를 정의합니다. 이 내부 클래스를 로컬 내부 클래스 또는 로컬 내부 클래스라고 하며, 다른 하나는 위에서 언급한 익명 내부 클래스입니다.

    2. 인스턴스 내부 클래스

    2.1 인스턴스 내부 클래스 생성

    인스턴스 내부 클래스의 정의는 매우 간단합니다. 외부 클래스 내부에서 직접 정의하면 됩니다. 문제는 내부 클래스 객체를 생성하는 방법입니다. 먼저 내부 클래스와 외부 클래스의 멤버 변수와 메서드는 모두 외부 클래스 객체에 속한다는 점을 이해해야 합니다. 수정), 따라서 내부 클래스 객체를 원한다면 먼저 Peripheral 클래스 객체가 있어야 하며, 내부 클래스 객체를 생성하는 첫 번째 방법은 메서드를 사용하여 내부 클래스 객체를 반환하는 것이며, 이 내부 클래스 객체의 유형은 다음과 같습니다. OutClassName.InnerClassName, 즉 외부 클래스 이름. 내부 클래스 이름입니다.

    public class Outer {
    
        class Inner1 {
            private String str;
            public Inner1(String s) {
                this.str = s;
            }
            public String readStr() {
                return this.str;
            }
        }
    
        class Inner2 {
            private int val;
            public Inner2(int i) {
                this.val = i;
            }
            public int readVal() {
                return this.val;
            }
        }
        //创建内部类
        public Inner1 creatInner1(String s) {
            return new Inner1(s);
        }
        public Inner2 creatInner2(int i) {
            return new Inner2(i);
        }
    
        public static void main(String[] args) {
            Outer outer = new Outer();
            Outer.Inner1 inner1 =  outer.creatInner1("Inner1");
            Outer.Inner2 inner2 = outer.creatInner2(2);
    
            System.out.println(inner1.readStr());
            System.out.println(inner2.readVal());
        }
    }
    //output:
    Inner1
    2
    
    Process finished with exit code 0

    2.2 .this 및 .new

    사용 물론 내부 클래스를 만드는 다른 방법도 있습니다. 즉, 외부 class.new의 개체를 사용하여 내부 클래스 개체를 만드는 것입니다. 구문은 다음과 같습니다.

    외부 클래스 object.new 내부 클래스 생성 방법

    public class Outer {
    
        class Inner1 {
            private String str;
            public Inner1(String s) {
                this.str = s;
            }
            public String readStr() {
                return this.str;
            }
        }
    
        class Inner2 {
            private int val;
            public Inner2(int i) {
                this.val = i;
            }
            public int readVal() {
                return this.val;
            }
        }
    
    
        public static void main(String[] args) {
            Outer outer = new Outer();
            Outer.Inner1 inner1 =  outer.new Inner1("Inner1");
            Outer.Inner2 inner2 = outer.new Inner2(2);
    
            System.out.println(inner1.readStr());
            System.out.println(inner2.readVal());
        }
    }
    //output:
    Inner1
    2
    
    Process finished with exit code 0

    내부 클래스의 특징은 그것뿐만 아니라, 내부 클래스도 외부 클래스와 연결될 수 있습니다. 첫째, 인스턴스 내부 클래스 객체 생성은 외부 클래스의 참조에 따라 달라집니다. 클래스 객체, 인스턴스 내부 클래스와 외부 클래스의 멤버 변수 상태 동일, 내부 클래스 객체를 통해 외부 클래스의 멤버 변수 및 메소드(특히 같은 이름을 가진 변수)에 접근하려는 경우. 내부 클래스에서는 외부 클래스 이름을 사용하여 외부 클래스 개체를 얻은 다음, 얻은 외부 클래스 개체를 사용하여 외부 클래스의 변수 및 메서드를 사용할 수 있습니다.
    public class Outer {
        private String outStr;
        public Outer(String str) {
            this.outStr = str;
        }
    
        public void printOuter() {
            System.out.println(this.outStr);
        }
    
        class Inner {
            private String str;
            public Inner(String s) {
                this.str = s;
            }
            public String readStr() {
                return this.str;
            }
            //使用.this获取父类对象引用
            public Outer outer() {
                return Outer.this;
            }
        }
    
    
    
        public static void main(String[] args) {
            Outer outer = new Outer("outerString");
            Outer.Inner inner = outer.new Inner("innerString");
    
            Outer out = inner.outer();
            out.printOuter();
        }
    }
    //output:
    outerString
    
    Process finished with exit code 0

    사실 내부 클래스 객체에는 this가 두 개 있습니다. this를 직접 사용하면 member는 내부 클래스 객체 자체의 멤버를 가져오고, 외부 클래스 이름을 사용하면 this 멤버는 외부 클래스의 멤버를 가져옵니다. 즉, 내부 클래스에서 이것은 내부 클래스 객체 자체의 참조를 가리키고, 외부 클래스 이름은 외부 클래스 객체의 참조를 가리킵니다.

    내부 클래스와 외부 클래스 변수 이름이 동일한 경우 이 두 가지가 매우 유용합니다.

    public class Outer {
        public int a = 12;
        public int b = 16;
        public int c = 20;
    
        class Inner{
            public int a = 8;
            public int c = 48;
            public int d = 2;
    
            public void printVal() {
                System.out.println("外围类变量a=" + Outer.this.a);
                System.out.println("外围类变量b=" + Outer.this.b);
                System.out.println("外围类变量c=" + Outer.this.c);
                System.out.println("内部类变量a=" + this.a);
                System.out.println("内部类变量c=" + this.c);
                System.out.println("内部类变量d=" + this.d);
            }
        }
    
        public Inner creatInner() {
            return new Inner();
        }
    
        public static void main(String[] args) {
            Outer outer = new Outer();
    
            Outer.Inner inner = outer.creatInner();
            inner.printVal();
        }
    }
    //output:
    外围类变量a=12
    外围类变量b=16
    外围类变量c=20
    内部类变量a=8
    内部类变量c=48
    内部类变量d=2
    
    Process finished with exit code 0

    같은 이름이 나오지 않으면 그냥 멤버를 직접 얻으면 됩니다. 위에서 언급한 것처럼 굳이 사용할 필요는 없습니다. 같은 이름이 나온다면 직접 접근한 멤버는 기본적으로 내부 클래스 객체가 됩니다.

    2.3 내부 클래스는 반복 인쇄를 구현합니다.

    내부 클래스는 외부 클래스의 모든 요소에 대한 액세스 권한을 가질 수 있으므로 내부 클래스를 사용하여 외부 클래스의 요소를 탐색하고 출력할 수 있습니다. 내부 클래스와 외부 클래스는 동일하지만 내부 클래스도 결국 클래스이며 클래스를 상속하고 주변 클래스와 같은 인터페이스를 구현할 수도 있습니다.

    import java.util.Arrays;
    
    interface Selector{
        //判断是否迭代完全部元素
        public boolean end();
        //获取当前元素
        public Object current();
        //迭代下一个元素
        public void next();
    }
    
    public class SequeArray {
        private Object[] items;
        private int usedSize;
    
        public SequeArray(int capacity) {
            items = new Object[capacity];
        }
        public void add(Object val) {
            if (usedSize == items.length) items = Arrays.copyOf(items, 2 * usedSize);
    
            items[usedSize++] = val;
        }
    
        private class SequeSelector implements Selector{
            private int index;
    
            public boolean end() {
                return index == usedSize;
            }
            public Object current() {
                return items[index];
            }
            public void next() {
                if (index < usedSize) index++;
            }
        }
        public SequeSelector sequeSelector() {
            return new SequeSelector();
        }
    
        public static void main(String[] args) {
            SequeArray array = new SequeArray(10);
    
            for (int i = 0; i < 10; i++) {
                array.add(i+1);
            }
            //发生了向上转型
            Selector selector = array.sequeSelector();
    
            while (!selector.end()) {
                System.out.print(selector.current() + "   ");
                selector.next();
            }
        }
    }
    //output:
    1   2   3   4   5   6   7   8   9   10   
    Process finished with exit code 0

    2.4 내부 클래스 상속

    내부 클래스 상속은 약간 번거롭습니다. 내부 클래스의 생성자는 외부 클래스의 참조에 의존해야 하기 때문에 내부 클래스 간의 연관을 설명하려면 특별한 구문이 필요합니다. 및 외부 클래스:

    주변 클래스 reference.super();

    특정 사용법은 다음 코드를 참조하세요.
    public class Outer {
        class Inner{
            
        }
    }
    class Person extends Outer.Inner {
        private String str;
        private int id;
        public Person(Outer out, String str, int id) {
            out.super();
            this.str = str;
            this.id = id;
        }
        public void readVal() {
            System.out.println(this.str + this.id);
            
        }
    }

    내부 클래스가 상속되면 상위 클래스의 생성자로 전달되어야 합니다. 외부 클래스의 참조를 통해 클래스를 생성하고 컴파일을 통해 super()를 호출합니다.

    내부 클래스가 외부 클래스를 상속받는 경우 직접 상속하면 됩니다. 귀찮게 할 필요가 없습니다.

    프로그램이 Java 파일의 바이트코드 파일을 생성하면 이름이 public external class $ Internal class로 지정됩니다.

    내부 클래스는 무한히 중첩될 수 있지만 일반적으로 누구도 그렇게 하지 않습니다.

    3. 정적 내부 클래스

    정적 내부 클래스는 중첩 클래스라고도 합니다. 인스턴스 내부 클래스 정의 앞에 다음과 같이 static 키워드를 추가하는 것입니다.

    public class Outer {
        
        static class Inner{
            
        }
    }

    인스턴스 내부 클래스와의 차이점은 정적 내부 클래스입니다. class 객체가 아닌 클래스에 속하므로 정적 내부 클래스 생성이 외부 클래스 객체에 의존하지 않는다는 점이 인스턴스 내부 클래스와의 가장 큰 차이점 중 하나입니다.

    public class Outer {
        static class Inner{
            private String str;
            public Inner(String s) {
                str = s;
            }
        }
    
        public static void main(String[] args) {
            Outer.Inner inner = new Outer.Inner("我是静态内部类!");
            System.out.println(inner.str);
        }
    }
    //output:
    我是静态内部类!
    
    Process finished with exit code 0

    4. 익명 내부 클래스

    우리는 이미 익명 내부 클래스의 사용법을 살펴보았습니다. 즉, PriorityQueue 객체를 생성할 때 기본적으로 작은 힙이 생성되고 큰 힙을 생성하려면 비교기를 전달해야 합니다. 더미.

            PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return o1 - o2;
                }
            });

    위의 방법과 마찬가지로 new 키워드를 사용하여 익명 클래스의 객체를 실제 매개변수로 생성합니다. 내부의 익명 클래스는 익명 내부 클래스입니다. 생성 과정에서 Comparator 익명 클래스 객체는 필수 매개변수 유형을 상속받습니다. 여기는 Comparator 클래스입니다.

    사용자 정의 유형을 사용하여 우선 순위 대기열에 전달하는 경우 비교기를 구현하는 가장 일반적인 방법은 익명 내부 클래스와 Lambda 표현식입니다.

    假设我有一个Person类数组,需要对他们的name排序,如果不使用内部类,就需要在Person类中实现比较器。

    import java.util.Arrays;
    import java.util.Comparator;
    
    class Preson {
        public String name;
        public Integer id;
        public Preson(String name, Integer id) {
            this.name = name;
            this.id = id;
        }
    
        @Override
        public String toString() {
            return "Preson{" +
                    "name=&#39;" + name + &#39;\&#39;&#39; +
                    ", id=" + id +
                    &#39;}&#39;;
        }
    }
    class PersonComparator implements Comparator<Preson> {
        @Override
        public int compare(Preson o1, Preson o2) {
            return o1.name.compareTo(o2.name);
        }
    }
    public class Main {
        public static void main(String[] args) {
            Preson preson1 = new Preson("aboluo", 24);
            Preson preson2 = new Preson("zhousi", 25);
            Preson preson3 = new Preson("syyfjy", 2);
            Preson[] presons = {preson1, preson2, preson3};
            Arrays.parallelSort(presons, new PersonComparator());
            System.out.println(Arrays.toString(presons));
        }
    }
    //output:
    [Preson{name=&#39;aboluo&#39;, id=24}, Preson{name=&#39;syyfjy&#39;, id=2}, Preson{name=&#39;zhousi&#39;, id=25}]
    
    Process finished with exit code 0

    使用内部类上述代码就变为:

    import java.util.Arrays;
    import java.util.Comparator;
    
    class Preson {
        public String name;
        public Integer id;
        public Preson(String name, Integer id) {
            this.name = name;
            this.id = id;
        }
    
    
        @Override
        public String toString() {
            return "Preson{" +
                    "name=&#39;" + name + &#39;\&#39;&#39; +
                    ", id=" + id +
                    &#39;}&#39;;
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Preson preson1 = new Preson("aboluo", 24);
            Preson preson2 = new Preson("zhousi", 25);
            Preson preson3 = new Preson("syyfjy", 2);
            Preson[] presons = {preson1, preson2, preson3};
            Arrays.parallelSort(presons, new Comparator<Preson>() {
                @Override
                public int compare(Preson o1, Preson o2) {
                    return o1.name.compareTo(o2.name);
                }
            });
            System.out.println(Arrays.toString(presons));
        }
    }
    //output:
    [Preson{name=&#39;aboluo&#39;, id=24}, Preson{name=&#39;syyfjy&#39;, id=2}, Preson{name=&#39;zhousi&#39;, id=25}]
    
    Process finished with exit code 0

    还有一个本地内部类,就是类定义在方法中,就不多说了,基本上不用,用法如下:

    public class Outer {
        public void func() {
            class Inner{
                //
            }
        }
    }

    위 내용은 Java 내부 클래스 예제 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    성명:
    이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제