Maison  >  Article  >  Java  >  Analyse d'exemples de classes internes Java

Analyse d'exemples de classes internes Java

WBOY
WBOYavant
2023-04-23 14:43:14526parcourir

    1. Concept et classification des classes internes

    Lorsqu'une classe est définie à l'intérieur d'une autre classe ou à l'intérieur d'une interface ou à l'intérieur d'un corps de méthode, cette classe est appelée une classe interne. On pourrait aussi bien appeler la classe où se trouve la classe interne. la classe interne est située. Pour les classes périphériques, en plus des classes internes définies dans les classes, interfaces et méthodes, il existe également une classe interne spéciale, qui doit utiliser le mot-clé new pour créer un objet d'une classe anonyme, et cette classe anonyme La classe est en fait une classe interne. Plus précisément, il s'agit d'une classe interne anonyme qui est souvent utilisée pour construire des objets en passant des arguments de constructeur, comme la création d'objets PriorityQueue.

    Lorsqu'une classe est définie dans une autre classe ou dans une interface et qu'il n'y a pas de modification statique, la classe interne est appelée classe interne d'instance. Lorsqu'une modification statique est utilisée, la classe interne est appelée classe interne statique (classe imbriquée). ), définissez une classe à l'intérieur du bloc de code, en particulier à l'intérieur du corps de la méthode. Cette classe interne est appelée classe interne locale ou classe interne locale, et l'autre est la classe interne anonyme mentionnée ci-dessus.

    2. Classe interne d'instance

    2.1 Création d'une classe interne d'instance

    La définition de la classe interne d'instance est très simple, il suffit de la définir directement à l'intérieur de la classe externe. La question est de savoir comment créer un objet de classe interne. Tout d'abord, vous devez comprendre que les variables et méthodes membres de la classe interne et de la classe externe sont sur un pied d'égalité. Elles appartiennent toutes à l'objet de classe externe (sans statique). modification), donc si vous voulez l'objet de classe interne, vous devez d'abord avoir un objet de classe périphérique, la première façon de créer un objet de classe interne est d'utiliser une méthode pour renvoyer un objet de classe interne, et le type de cet objet de classe interne est OutClassName.InnerClassName, c'est-à-dire nom de classe externe.nom de classe interne.

    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 Utilisez .this et .new

    Bien sûr, il existe d'autres façons de créer une classe interne, qui consiste à utiliser l'objet de la classe externe.new pour créer un objet de classe interne. La syntaxe est :

    .

    Objet de classe externe.new Méthode de construction de classe interne ;

    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

    Les caractéristiques des classes internes ne sont pas seulement cela, les classes internes peuvent également être liées aux classes externes. Premièrement, la création d'objets de classe interne d'instance dépend de la référence des classes externes. objets de classe et statut des variables membres des classes internes d'instance et des classes externes Idem, si vous souhaitez accéder aux variables membres et aux méthodes de la classe externe (en particulier les variables du même nom) via l'objet de classe interne. Dans la classe interne, vous pouvez utiliser le nom de la classe externe.this pour obtenir l'objet de classe externe, puis utiliser l'objet de classe externe obtenu pour utiliser les variables et les méthodes de la classe externe.

    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

    En fait, il y a deux this dans l'objet de classe interne. L'utilisation directe du membre this obtient les membres de l'objet de classe interne lui-même, tandis que l'utilisation du nom de classe externe comme ci-dessus obtient les membres de l'objet de classe externe. class, c'est-à-dire Dans la classe interne, cela pointe vers la référence de l'objet de classe interne lui-même, et le nom de la classe externe. Cela pointe vers la référence de l'objet de classe externe.

    Lorsque les noms de variables de classe interne et de classe externe sont identiques, ces deux-là sont d'une grande utilité.

    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

    Si le même nom n'apparaît pas, obtenez simplement le membre directement. Vous n'avez pas besoin de l'utiliser comme mentionné ci-dessus. Si le même nom apparaît, le membre directement accessible est par défaut l'objet de classe interne.

    2.3 La classe interne implémente l'impression itérative

    La classe interne peut avoir des droits d'accès à tous les éléments de la classe externe, nous pouvons donc essayer d'utiliser la classe interne pour parcourir et afficher les éléments de la classe externe, bien que le statut de membre de la classe interne et la classe externe sont égales, mais une classe interne est aussi une classe après tout, et elle peut également hériter de classes et implémenter des interfaces comme des classes périphériques.

    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 Héritage des classes internes

    L'héritage des classes internes est un peu gênant, car le constructeur de la classe interne doit s'appuyer sur la référence de la classe externe, donc une syntaxe spéciale est nécessaire pour illustrer l'association entre la classe interne et la classe externe :

    Référence de classe périphérique.super();

    Voir le morceau de code suivant pour une utilisation spécifique :

    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);
            
        }
    }

    Lorsque la classe interne est héritée, elle doit être transmise au constructeur du parent classe via la référence de la classe externe et appelez super().

    Si la classe interne hérite de la classe externe, héritez-en simplement directement, pas besoin de vous embêter.

    Lorsque le programme génère le fichier bytecode d'un fichier java, il est nommé classe externe publique $ classe interne.

    Les classes internes peuvent être imbriquées à l'infini, mais généralement personne ne le fait.

    3. Classe interne statique

    La classe interne statique est également appelée classe imbriquée. Il s'agit d'ajouter un mot-clé statique avant la définition de la classe interne d'instance, comme suit :

    public class Outer {
        
        static class Inner{
            
        }
    }

    La différence avec la classe interne d'instance est cette classe interne statique. class Il appartient à la classe plutôt qu'à l'objet, donc la création de la classe interne statique ne dépend pas de l'objet de classe externe. C'est l'une des plus grandes différences par rapport à la classe interne d'instance.

    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. Classes internes anonymes

    Nous avons déjà vu l'utilisation de classes internes anonymes, c'est-à-dire que lors de la création d'un objet PriorityQueue, un petit tas est créé par défaut et un comparateur doit être transmis pour créer un grand. tas.

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

    Comme la méthode ci-dessus, utilisez le nouveau mot-clé pour créer un objet d'une classe anonyme en tant que paramètre réel. La classe anonyme à l'intérieur est une classe interne anonyme pendant le processus de création. Ici, c'est la classe Comparator.

    Si vous utilisez un type personnalisé pour passer dans la file d'attente prioritaire, vous devez implémenter un comparateur. La manière la plus courante d'implémenter un comparateur consiste à utiliser des classes internes anonymes et des expressions 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{
                //
            }
        }
    }

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Déclaration:
    Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer