search
HomeJavajavaTutorialJava Improvement (7) ----- Detailed explanation of internal classes

You can place the definition of a class inside the definition of another class. This is an inner class.

The internal class is a very useful but more difficult to understand the characteristics of use (I have not used the internal classes so far, I just know one or two for the internal class).

First meeting

Internal classes are very easy to understand from the outside. They are nothing more than defining a class inside a class.

public class OuterClass {  
    private String name ;  
    private int age;  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public int getAge() {  
        return age;  
    }  
  
    public void setAge(int age) {  
        this.age = age;  
    }  
      
    class InnerClass{  
        public InnerClass(){  
            name = "chenssy";  
            age = 23;  
        }  
    }  
}

Here InnerClass is the inner class. For beginners, inner classes are not used much. I, a novice, have never used them (it seems to be only used in swing registration events). But as our programming skills improve, we will realize its charm, and it can use it to design our program structure more elegantly. Before using inner classes, we need to understand why we should use inner classes and what benefits inner classes can bring us.


1. Why use inner classes

Why use inner classes? There is this sentence in "Think in Java": The most attractive reason for using inner classes is that each inner class can independently inherit an (interface) implementation, so no matter whether the outer class has inherited an (interface) ) implementation has no effect on inner classes.

In our programming, sometimes there are some problems that are difficult to solve using interfaces. At this time, we can use the ability provided by internal classes to inherit multiple concrete or abstract classes to solve these programs. Design issues. It can be said that interfaces only solve part of the problem, and inner classes make the solution of multiple inheritance more complete.

public interface Father {  
  
}  
  
public interface Mother {  
  
}  
  
public class Son implements Father, Mother {  
  
}  
  
public class Daughter implements Father{  
  
    class Mother_ implements Mother{  
          
    }  
}

In fact, we really can’t see the advantages of using internal classes for this example, but what if Father and Mother are not interfaces, but abstract classes or concrete classes? At this time we can only use inner classes to achieve multiple inheritance.

In fact, the biggest advantage of using inner classes is that it can solve the problem of multiple inheritance very well, but if we do not need to solve the problem of multiple inheritance, then we can naturally use other coding methods, but use inner classes It can also bring us the following features (excerpted from "Think in java"):

1. Internal classes can use multiple instances. Each instance has its own status information and is related to the information of other peripheral objects. Independent.

2. In a single peripheral class, multiple internal classes can implement the same interface in different ways, or inherit the same class.

3. The time when the inner class object is created does not depend on the creation of the outer class object.

4. The inner class does not have the confusing "is-a" relationship, it is an independent entity.

5. The inner class provides better encapsulation. Except for the peripheral class, other classes cannot access it.


## 2. Basics of Internal Classes

This section mainly introduces how inner classes use the properties and methods of external classes, as well as the use of .this and .new.

When we create an inner class, it has an invisible connection with the outer class. Relying on this connection, it can have unlimited access to the elements of the outer class.

public class OuterClass {  
    private String name ;  
    private int age;  
  
    /**省略getter和setter方法**/  
      
    public class InnerClass{  
        public InnerClass(){  
            name = "chenssy";  
            age = 23;  
        }  
          
        public void display(){  
            System.out.println("name:" + getName() +"   ;age:" + getAge());  
        }  
    }  
      
    public static void main(String[] args) {  
        OuterClass outerClass = new OuterClass();  
        OuterClass.InnerClass innerClass = outerClass.new InnerClass();  
        innerClass.display();  
    }  
}  
--------------  
Output:  
name:chenssy   ;age:23

In this application, we can see that the inner InnerClass can seamlessly access the properties of the outer class OuterClass, although it is privately modified. This is because when we create an inner class object of an outer class, the inner class object will definitely capture a reference to that outer class object. As long as we access members of the outer class, we will use this reference. Select members of the enclosing class.

In fact, in this application we also saw how to reference inner classes: To reference inner classes we need to specify the type of this object: OuterClasName.InnerClassName. At the same time, if we need to create an inner class object, we must use the outer class object to create the inner class through .new: OuterClass.InnerClass innerClass = outerClass.new InnerClass();.

At the same time, if we need to generate a reference to an external class object, we can use OuterClassName.this, so that a reference to the external class can be generated correctly. Of course, this is known at compile time and there is no runtime cost.

public class OuterClass {  
    public void display(){  
        System.out.println("OuterClass...");  
    }  
      
    public class InnerClass{  
        public OuterClass getOuterClass(){  
            return OuterClass.this;  
        }  
    }  
      
    public static void main(String[] args) {  
        OuterClass outerClass = new OuterClass();  
        OuterClass.InnerClass innerClass = outerClass.new InnerClass();  
        innerClass.getOuterClass().display();  
    }  
}  
-------------  
Output:  
OuterClass...

 到这里了我们需要明确一点,内部类是个编译时的概念,一旦编译成功后,它就与外围类属于两个完全不同的类(当然他们之间还是有联系的)。对于一个名为OuterClass的外围类和一个名为InnerClass的内部类,在编译成功后,会出现这样两个class文件:OuterClass.class和OuterClass$InnerClass.class。

       在Java中内部类主要分为成员内部类、局部内部类、匿名内部类、静态内部类。


       三、成员内部类

       成员内部类也是最普通的内部类,它是外围类的一个成员,所以他是可以无限制的访问外围类的所有 成员属性和方法,尽管是private的,但是外围类要访问内部类的成员属性和方法则需要通过内部类实例来访问。

       在成员内部类中要注意两点,第一:成员内部类中不能存在任何static的变量和方法;第二:成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类。

public class OuterClass {  
    private String str;  
      
    public void outerDisplay(){  
        System.out.println("outerClass...");  
    }  
      
    public class InnerClass{  
        public void innerDisplay(){  
            //使用外围内的属性  
            str = "chenssy...";  
            System.out.println(str);  
            //使用外围内的方法  
            outerDisplay();  
        }  
    }  
      
    /*推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时 */  
    public InnerClass getInnerClass(){  
        return new InnerClass();  
    }  
      
    public static void main(String[] args) {  
        OuterClass outer = new OuterClass();  
        OuterClass.InnerClass inner = outer.getInnerClass();  
        inner.innerDisplay();  
    }  
}  
--------------------  
chenssy...  
outerClass...

推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时 。


       四、局部内部类

       有这样一种内部类,它是嵌套在方法和作用于内的,对于这个类的使用主要是应用与解决比较复杂的问题,想创建一个类来辅助我们的解决方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类,局部内部类和成员内部类一样被编译,只是它的作用域发生了改变,它只能在该方法和属性中被使用,出了该方法和属性就会失效。

       对于局部内部类实在是想不出什么好例子,所以就引用《Think in java》中的经典例子了。

       定义在方法里:

public class Parcel5 {  
    public Destionation destionation(String str){  
        class PDestionation implements Destionation{  
            private String label;  
            private PDestionation(String whereTo){  
                label = whereTo;  
            }  
            public String readLabel(){  
                return label;  
            }  
        }  
        return new PDestionation(str);  
    }  
      
    public static void main(String[] args) {  
        Parcel5 parcel5 = new Parcel5();  
        Destionation d = parcel5.destionation("chenssy");  
    }  
}

       定义在作用域内:

public class Parcel6 {  
    private void internalTracking(boolean b){  
        if(b){  
            class TrackingSlip{  
                private String id;  
                TrackingSlip(String s) {  
                    id = s;  
                }  
                String getSlip(){  
                    return id;  
                }  
            }  
            TrackingSlip ts = new TrackingSlip("chenssy");  
            String string = ts.getSlip();  
        }  
    }  
      
    public void track(){  
        internalTracking(true);  
    }  
      
    public static void main(String[] args) {  
        Parcel6 parcel6 = new Parcel6();  
        parcel6.track();  
    }  
}

 五、匿名内部类

       在做Swing编程中,我们经常使用这种方式来绑定事件

button2.addActionListener(    
                new ActionListener(){    
                    public void actionPerformed(ActionEvent e) {    
                        System.out.println("你按了按钮二");    
                    }    
                });

        我们咋一看可能觉得非常奇怪,因为这个内部类是没有名字的,在看如下这个例子:

public class OuterClass {  
    public InnerClass getInnerClass(final int num,String str2){  
        return new InnerClass(){  
            int number = num + 3;  
            public int getNumber(){  
                return number;  
            }  
        };        /* 注意:分号不能省 */  
    }  
      
    public static void main(String[] args) {  
        OuterClass out = new OuterClass();  
        InnerClass inner = out.getInnerClass(2, "chenssy");  
        System.out.println(inner.getNumber());  
    }  
}  
  
interface InnerClass {  
    int getNumber();  
}  
  
----------------  
Output:  
5

这里我们就需要看清几个地方

      1、 匿名内部类是没有访问修饰符的。

      2、 new 匿名内部类,这个类首先是要存在的。如果我们将那个InnerClass接口注释掉,就会出现编译出错。

      3、 注意getInnerClass()方法的形参,第一个形参是用final修饰的,而第二个却没有。同时我们也发现第二个形参在匿名内部类中没有使用过,所以当所在方法的形参需要被匿名内部类使用,那么这个形参就必须为final。

      4、 匿名内部类是没有构造方法的。因为它连名字都没有何来构造方法。

PS:由于篇幅有限,对匿名内部类就介绍到这里,有关更多关于匿名内部类的知识,我就会在下篇博客(java提高篇-----详解匿名内部类)做详细的介绍,包括为何形参要定义成final,怎么对匿名内部类进行初始化等等,敬请期待……


       六、静态内部类

       在java提高篇-----关键字static中提到Static可以修饰成员变量、方法、代码块,其他它还可以修饰内部类,使用static修饰的内部类我们称之为静态内部类,不过我们更喜欢称之为嵌套内部类。静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。没有这个引用就意味着:

      1、 它的创建是不需要依赖于外围类的。

      2、 它不能使用任何外围类的非static成员变量和方法。

public class OuterClass {  
    private String sex;  
    public static String name = "chenssy";  
      
    /** 
     *静态内部类 
     */  
    static class InnerClass1{  
        /* 在静态内部类中可以存在静态成员 */  
        public static String _name1 = "chenssy_static";  
          
        public void display(){  
            /*  
             * 静态内部类只能访问外围类的静态成员变量和方法 
             * 不能访问外围类的非静态成员变量和方法 
             */  
            System.out.println("OutClass name :" + name);  
        }  
    }  
      
    /** 
     * 非静态内部类 
     */  
    class InnerClass2{  
        /* 非静态内部类中不能存在静态成员 */  
        public String _name2 = "chenssy_inner";  
        /* 非静态内部类中可以调用外围类的任何成员,不管是静态的还是非静态的 */  
        public void display(){  
            System.out.println("OuterClass name:" + name);  
        }  
    }  
      
    /** 
     * @desc 外围类方法 
     * @author chenssy 
     * @data 2013-10-25 
     * @return void 
     */  
    public void display(){  
        /* 外围类访问静态内部类:内部类. */  
        System.out.println(InnerClass1._name1);  
        /* 静态内部类 可以直接创建实例不需要依赖于外围类 */  
        new InnerClass1().display();  
          
        /* 非静态内部的创建需要依赖于外围类 */  
        OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2();  
        /* 方位非静态内部类的成员需要使用非静态内部类的实例 */  
        System.out.println(inner2._name2);  
        inner2.display();  
    }  
      
    public static void main(String[] args) {  
        OuterClass outer = new OuterClass();  
        outer.display();  
    }  
}  
----------------  
Output:  
chenssy_static  
OutClass name :chenssy  
chenssy_inner  
OuterClass name:chenssy

上面这个例子充分展现了静态内部类和非静态内部类的区别。

The introduction to internal classes is basically over here! In fact, my knowledge of internal classes is only superficial. I am almost a novice with limited knowledge! I will use these few days to study internal classes!

The above is the java improvement chapter (seven) -----detailed explanation of the content of internal classes. For more related content, please pay attention to the PHP Chinese website (www.php .cn)!


Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Top 4 JavaScript Frameworks in 2025: React, Angular, Vue, SvelteTop 4 JavaScript Frameworks in 2025: React, Angular, Vue, SvelteMar 07, 2025 pm 06:09 PM

This article analyzes the top four JavaScript frameworks (React, Angular, Vue, Svelte) in 2025, comparing their performance, scalability, and future prospects. While all remain dominant due to strong communities and ecosystems, their relative popul

Spring Boot SnakeYAML 2.0 CVE-2022-1471 Issue FixedSpring Boot SnakeYAML 2.0 CVE-2022-1471 Issue FixedMar 07, 2025 pm 05:52 PM

This article addresses the CVE-2022-1471 vulnerability in SnakeYAML, a critical flaw allowing remote code execution. It details how upgrading Spring Boot applications to SnakeYAML 1.33 or later mitigates this risk, emphasizing that dependency updat

Node.js 20: Key Performance Boosts and New FeaturesNode.js 20: Key Performance Boosts and New FeaturesMar 07, 2025 pm 06:12 PM

Node.js 20 significantly enhances performance via V8 engine improvements, notably faster garbage collection and I/O. New features include better WebAssembly support and refined debugging tools, boosting developer productivity and application speed.

How do I implement multi-level caching in Java applications using libraries like Caffeine or Guava Cache?How do I implement multi-level caching in Java applications using libraries like Caffeine or Guava Cache?Mar 17, 2025 pm 05:44 PM

The article discusses implementing multi-level caching in Java using Caffeine and Guava Cache to enhance application performance. It covers setup, integration, and performance benefits, along with configuration and eviction policy management best pra

How does Java's classloading mechanism work, including different classloaders and their delegation models?How does Java's classloading mechanism work, including different classloaders and their delegation models?Mar 17, 2025 pm 05:35 PM

Java's classloading involves loading, linking, and initializing classes using a hierarchical system with Bootstrap, Extension, and Application classloaders. The parent delegation model ensures core classes are loaded first, affecting custom class loa

How to Share Data Between Steps in CucumberHow to Share Data Between Steps in CucumberMar 07, 2025 pm 05:55 PM

This article explores methods for sharing data between Cucumber steps, comparing scenario context, global variables, argument passing, and data structures. It emphasizes best practices for maintainability, including concise context use, descriptive

How can I implement functional programming techniques in Java?How can I implement functional programming techniques in Java?Mar 11, 2025 pm 05:51 PM

This article explores integrating functional programming into Java using lambda expressions, Streams API, method references, and Optional. It highlights benefits like improved code readability and maintainability through conciseness and immutability

Iceberg: The Future of Data Lake TablesIceberg: The Future of Data Lake TablesMar 07, 2025 pm 06:31 PM

Iceberg, an open table format for large analytical datasets, improves data lake performance and scalability. It addresses limitations of Parquet/ORC through internal metadata management, enabling efficient schema evolution, time travel, concurrent w

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
3 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools