Java--Inner Class Study Notes

This article introduces what is an inner class, the inner class in Java: instance inner class, static inner class, local inner class, grammar and precautions of anonymous inner class, as well as the application scenario of each inner class, and a brief introduction to anonymous inner class The class is more concise and more special syntax -> lambda expression

1. What is an inner class?

When there is a part inside a thing that needs a complete structure to describe, and the complete internal structure only provides services for external things, then it is best to use the inner class for the complete internal structure

For example: a car, the car as a whole is a complete structure, but it can be subdivided into multiple internal structures such as the engine in the car, which can be regarded as an independent internal structure, and the internal structure of the engine is Cars provide energy for…
insert image description here

Therefore, Java, an object-oriented programming language, is used to describe the containment relationship between classes and classes, taking the form of inner classes:

A class A can be defined inside another class B or a method. With this definition relationship, the
former A is called an inner class, and the latter B is called an outer class.
Internal classes can be regarded as members of external classes, which can be modified by access modifiers and static, so internal classes are also a manifestation of encapsulation...

The syntax is as follows:

public class OutClass {
class InnerClass{
}
} // OutClass是外部类
// InnerClass是内部类

First define an external class, and then define a class inside the class. OutClass is the external class, and InnerClass is the internal class

public class A{
}

class B{
}

Generally, only one class is written in a java source file. If there is another class, it is generally
class A above the internal class. Class B is defined in the same java source file, but it is not an internal class.

Notice:

  1. Defined outside the curly braces of the class class name {}, even in a file, cannot be called an internal class
  2. The inner class and the outer class share the same java source file, but after compilation, the inner class will form a separate bytecode file

2. Classification of inner classes

The inner class is defined in a class, but due to different positions in the class, or different modifiers, different usages can be divided into various forms: instance inner class static inner class local inner class anonymous inner class

1. Instance inner class

The inner class of the instance is an instance member of the outer class, defined in a class, outside the method, not modified by static

Example:

class OuterClass1{
    
    
    public int num1=1;
    static int num2=2;
    public class InnerClass{
    
      //  内部类 是外部类的一个成员 作为类的一部分 可以和另一个类的内部类同名 是属于不同类里的 内部类是一个成员可以用public等修饰符
        
        public int num1=1; // 内部类 和外部类虽是包含关系 但是 是两个不同的类,分别都可以有同名的成员 

        static final int num3=3;   //语法规定 非静态/实例 内部类 里面不能写 静态成员变量和成员方法 但是静态成员变量可以加final变为静态常量
        //static int num; 报错
//        static void func1(){  语法报错
//
//        }

        //静态内部类里可以有静态属性和方法 非静态内部类 不能有静态属性或方法 但可以有静态常量(因为静态常量在编译时就产生,可做内部类里常量使用) 非静态内部类使用就得实例化
        //在加载外部类时不会加载实例内部类故无法加载实例内部类里的静态成员  所以非静态内部类里不能有静态成员 否则没有实例化没有加载 通过类名无法访问
       
        //加载外部类会加载静态内部类 静态内部类里可以有静态成员 可以通过类名访问
        int num4 =4;
        final int num5=5;
        //可以有非静态成员变量和成员方法 或 静态 非静态的final常量

        public void func(){
    
     //非静态内部类里的非静态方法

            InnerClass innerClass=new InnerClass();  //在外部类里或者非静态内部类里 可以不用外部类类名.内部类类名 而是直接使用内部类名 来创建非静态内部类引用变量
            //创建内部类对象时 在外部类的实例部分中(实例代码块和成员方法等)只要能用this表示当前对象引用时 可以直接使用new 内部类() 来实例 因为隐式包含了当前外部类对象

            System.out.println("非静态内部类里的静态常量:"+num3);  //静态常量 直接用名也可以访问

            System.out.println("非静态内部类里的非静态变量:"+num4);
            System.out.println("非静态内部类里的非静态常量:"+this.num5);
            System.out.println("非静态内部类里调用外部类的非静态变量:"+OuterClass1.this.num1);//非静态内部类里调用外部类的非静态变量用外部类对象this
            //因为非静态内部类对象出现一定要有外部类对象和内部类对象
            // 此时在内部类方法里有两个this 单独this表示当前内部类对象的this 表示当前对象的引用 也有外部类名.this 表示外部类对象的引用
            System.out.println("非静态内部类里调用外部类的静态变量:"+OuterClass1.num2);
            
        }

    }
//静态内部类和非静态内部类 一般静态内部类比较常用 非静态比较麻烦 用内部类就是多了层关系 表示内部类是为外部类服务的
}

Note:
Although the inner class and the outer class have a containment relationship, they are two different classes. They can have methods or members with the same name inside. When calling a static member with the same name as the outer class in the instance inner class, in order to avoid conflicts , you need to add the external class name. member, and if you are calling an instance member of the external class, you need to add the external class name. this. The external class member (that is, there are two this references in the instance internal class object, one internal The class object itself, one corresponding to the external class object), and the members of the inner class of the instance cannot be directly called in the outer class or the outer class object, unless the inner class member is instanced
in the outer class to call

insert image description here
Java syntax does not support static member variables and member methods defined in the instance internal class, because the instance internal class will not be loaded when the external class is loaded, so the static part will not be loaded, and the static part cannot be called when the internal class reference is obtained member, but can be modified by static and final at the same time, indicating that it is a static constant (the constant will be loaded at compile time),

Instance inner class object creation

//实例内部类的调用
        OuterClass1 outerClass1=new OuterClass1();
        OuterClass1.InnerClass innerClass1 =outerClass1.new InnerClass();
        // 给非静态内部类创建对象 需要先实例化外部类对象然后 外部类名.内部类名 引用变量= 外部类实例化的对象.new 内部类();可见创建非静态内部类比静态麻烦,创建时多了外部类对象调用
        innerClass1.func();

insert image description here

Because the inner class of the instance is a member of the outer class object, to get the reference of the inner class of the instance, you need to pass the name of the outer class. The inner class name corresponds to creating an inner class reference variable, but to create the inner class object of the instance, you need to create an outer class first class object, and then pass the external class object.new instance internal class name();
that is, to get the instance internal class object, the external class object must first be obtained

Static member variables and member methods cannot be defined in the inner class of the instance. The members of the
inner class of the instance and the outer class can have the same name. The inner class object of the instance has the current object this reference and the outer class object this reference. To
create an instance inner class object, the outer class must first be created. object

2. Static inner class

The static inner class is defined in the outer class, outside the method, the class modified by the static keyword, that is, a static member of the outer class

Example:

class OuterClass{
    
       //外部类 里面有完整结构 里面有内部类 内部类只是外部类的一个成员 内部类里可以有自己的结构 可以同名 与外部类不冲突!!!
    public int num1=1;
    static int num2=2;

    static class InnerClass{
    
         // OuterClass里的一个静态类 这个类属于外部类的一部分 但是这个类里可以有自己完整的结构
        int num1=1;
        static int num2=2;
        int num3=3;
        static int num4=4;
        // 一个类内部是一个完整结构 不管其和其他类是否是包含关系 还是继承关系 只要是不同的两个类 两个类就可以有同名的变量
        void func(){
    
    
        InnerClass innerClass=new InnerClass(); // 在外部类里 可以不用外部类名 直接使用内部类名 创建内部类对象
            System.out.println("static("+num2+","+num4+")");
            // 当前最近一层类是 InnerClass 其变量是属于此类的 不属于再外层的OuterClass (跟多层包类似) 类里的变量最接近的哪层类就是哪层类自身的
            System.out.println("内部类非静态变量:"+num1);   //在非静态方法中 可以直接调用当前对象的静态或非静态
            System.out.println("内部类静态变量:"+this.num2);//静态内部类 成员方法里可以this表示静态内部类对象引用
           OuterClass outerClass=new OuterClass();
            System.out.println("外部类对象内的非静态变量:"+outerClass.num1);
            System.out.println("外部类的静态变量:"+OuterClass.num2);
            //System.out.println("外部类对象内的非静态变量:"+OuterClass.this.num1);  错误
            // 静态内部类里不存在两个this 因为外部类不用实例化就可以实例化静态内部类 在内部类方法里访问外部类的非静态必须先实例化外部类访问
        }

        @Override
        public String toString() {
    
       //内部类本身也是一个类 继承 object 可以重写其方法
            return "InnerClass{" +
                    "num1=" + num1 +
                    ", num3=" + num3 +
                    '}';
        }

    }
    void func(){
    
     //外部类 内部类 都有自己的结构 可以有同名方法和同名属性
        System.out.println("外部类非静态变量:"+num1);   //在非静态方法中 可以直接调用当前对象的静态或非静态
        System.out.println("外部类静态变量:"+num2);
        InnerClass innerClass=new InnerClass();  // 在当前外部类里 可以直接用静态类名访问 静态类 实例化类对象
        System.out.println("内部类对象内的非静态变量:"+innerClass.num3);  // 有了内部类对象才可以调用内部类非静态成员变量
        System.out.println("内部类的静态变量:"+InnerClass.num4); //此时在外部类里面 使用内部类静态成员变量 只需要静态类名 调用即可
    }
}

Note:
The static inner class is a static member of the outer class, but it is generally used by the class used in the outer class to describe an inner structure. The outer class and the static inner class can have member variables with the same name. Member methods, in In the static inner class, the instance members of the outer class object can no longer be accessed, but the static members of the outer class can be accessed: the name of the outer class. The static member of the outer class (because the instance of the static inner class does not need to instantiate the outer class object first, it must Access to non-static members of the outer class requires an instance of the outer class object)

Static inner classes can have static members, non-static members, and constants, because static inner classes will also be loaded when the outer class is loaded, and the static members of the static inner class will be loaded, and it can also be directly passed in the outer class Get the name of the static inner class. Access to static members
cannot access its instance members when the static inner class object is not created

Creation of static inner class objects

OuterClass.InnerClass innerClass=new OuterClass.InnerClass();  // 静态内部类是外部类一部分 需要拿到外部类类名.静态类名才能得到这个类 实例化内部类对象需要 new 外部类名.内部类名()
        System.out.println(innerClass);
        innerClass.func();
        OuterClass outerClass=new OuterClass(); //实例化一个外部类 对象 里面有一个静态成员是一个类
        outerClass.func();

To obtain a static inner class, you need to use the external class name. Static internal class name to create a static internal class reference. To obtain a static internal class
object, you need new external class name. Static internal class name (); Get a static internal class object
to create a static internal class Class objects do not need to create external class objects first, just get the class name
insert image description here

3. Local inner class

A local inner class is a class defined in a code block, and its scope is also in the local area of ​​its code, so it is called a local inner class

Example:

class OuterClass2{
    
       // 局部内部类 在一个类里 有代码块(静态或非静态) 构造方法 成员方法 这些内部都可以定义一个类 这些类都被成为局部内部类

    //局部内部类只在 对应的 代码块 方法体内有效 能够被访问使用, 所以不同的区域内 是不同的类 可以同名 出了指定局部就不能再使用
    //不能被public  不能static 只能实例化后使用且只能在当前包内  几乎不使用
    int num1=1;
    class InnerClass{
    
       // 一个外部类里 不能同时存在相同名字的两个内部类 不论静态非静态 但是有内部类 可以存在同名的局部内部类

    }
//    static class InnerClass{ // 存在实例内部类 不能再有同名的静态内部类
//
//    }

    {
    
    //实例代码块
         class InnerClass{
    
    
            int num1=1;
        }
    }
    static {
    
    //静态代码块
        class InnerClass{
    
      
            int num2=2;
        }
    }
    void func(){
    
    //成员方法
        class InnerClass{
    
    
            int num3=3;
        }
    }
    static void func1(){
    
    
        class InnerClass{
    
    
            int num4=4;
        }
    }
    OuterClass2(){
    
     // 构造方法
        class InnerClass{
    
    
            int num5=5;
        }
    }
    //不同局部区域的局部内部类 可以同名
}

Note:
Local internal classes can be defined in code blocks and can only be used in defined code blocks, and they cannot be modified by access modifiers. Generally, they are rarely
used. Local internal classes in different code blocks can have the same name. But the static inner class instance inner class in the same outer class cannot have the same name

  1. Local inner classes can only be used within the body of the method they are defined in
  2. Cannot be modified by public, static and other modifiers
  3. The compiler also has its own independent bytecode file, naming format: external class name $ number internal class name.class
  4. hardly ever use

4. Anonymous inner class

An anonymous inner class is a class without a name defined in a class. Because it has no name, this class can only be used once and must be used in conjunction with inheriting other classes or implementing other interfaces...

Example:

interface IA{
    
    
    void func();
}
class AA implements IA{
    
      //此处和下面创建匿名内部类过程是等价的

    @Override
    public void func() {
    
    
        System.out.println("创建一个普通类 实现IA接口重写func方法 实例化此普通类调用此func方法");
    }
}

public class Note{
    
    
    //匿名内部类

        new OuterClass(){
    
    
           void func1(){
    
    
               System.out.println("创建一个匿名内部类继承 OuterClass 重写一个func1方法 并且实例化匿名内部类对象 调用func1方法");
           }
            }.func1();

        OuterClass outerClass2= new OuterClass(){
    
    
            void func(){
    
    
                System.out.println(" 创建一个匿名内部类 继承OuterClass 类  重写func方法 并且实例化一个对象给OuterClass类引用接受 再调用此子类对象重写的func");
            }

        };
       outerClass2.func();
       
        IA ia=new AA(); //向上转型
        ia.func(); //动态绑定

        new IA(){
    
    

            @Override
            public void func() {
    
    
                System.out.println("创建一个匿名内部类拓展IA接口,重写IA内抽象方法 并实例化此内部类对象调用 func");
            }
        }.func();
    }

    //创建匿名内部类 一定是要继承某个类或者某个接口 new 类名/接口名 (){};   {}内写继承或拓展后需要重写或者自己的结构最后以分号结尾 在创建完后会实例化对象 如果要想执行对象内容在分号前通过.执行
    //匿名内部类只在当前创建实例化后只执行一次 匿名只使用一次
    //多用于拓展接口
}

insert image description here
The writing method of creating an anonymous inner class is different from other inner classes:
the creation of an anonymous inner class needs to implement or inherit a certain class first, and after confirming that a certain interface is to be implemented, it can be implemented by new interface name (){};
This interface, written in {}, is the member of the anonymous inner class. It can have its own members, but it is mainly used to rewrite the methods in the interface. Most of the usage scenarios are to directly call the rewritten methods...

When we have an interface or a class that has one or more methods that need to be rewritten, we can customize a class that can override the methods of the class and interface after inheriting or implementing the interface, and then The instance calls these overridden methods

For example: to achieve the comparison of objects, you can create a comparator object to implement the compare interface and rewrite its comparison rules, and then this class can be used as a comparator object (with comparison characteristics)

And a class defined in this way is generally used in a special scenario, such as the comparator object defined for comparing the size of the object. This object is generally used only once, and if you explicitly define a class to get a comparator object then The class has a name and a separate .class source file, but generally the class used as a comparator is only used in a specific scene to get a comparator object

At this time, anonymous inner classes can be used. An anonymous inner class implements an interface or class and then rewrites the method of the interface or class inside it. After the definition is completed, an object of this type will be returned at the same time, that is, it will be instantiated at the same time as the definition. Object, and this class has no name and is only used once. After instantiation, it can also be accepted by references created by its implemented interfaces or inherited classes (upward transformation)

It can be seen that an anonymous inner class is a class used to rewrite a method in a class or interface in certain specific scenarios. Its anonymous nature makes this class only used once when it is defined

Anonymous inner classes are more convenient and concise than ordinary classes to implement this function, but they need to explicitly rewrite the method name when using it, and follow the rewriting rules to rewrite the method

And later there is a more concise usage similar to anonymous inner classes -> lambda expression

A brief introduction to lambda expressions:

insert image description here
In the above code, you can see that when the anonymous inner class is used to implement the IA interface and rewrite its method for use, the compiler prompts that this writing method can be replaced by a lambda expression,
as follows:

new IA(){
    
    

            @Override
            public void func() {
    
    
                System.out.println("创建一个匿名内部类拓展IA接口,重写IA内抽象方法 并实例化此内部类对象调用 func");
            }
        }.func();
               
         IA ia1=()->{
    
      // 重写的方法无返回值 重写的方法内容为 输出字符串...
             System.out.println("使用lambda表达式 代替匿名内部类 重写IA抽象方法 并实例化后给IA接口引用 接受后并调用");
         };
         ia1.func();
         //匿名内部类和lambda表达式 在此处效果是等价的 

insert image description here
It can be seen that the lambda expression is more concise than the anonymous expression, but the readability is not good, and it needs to be used in special scenarios (must be used to implement the functional interface (interface with only one abstract method) that is used to rewrite This abstract method) so when you are very familiar with the method to be rewritten, using lambda expressions can complete this function faster than anonymous expressions...

3. Application scenarios of each internal class

Both the static inner class and the instance inner class are outer classes defined outside the method in the outer class
They can all be used as a member of an external class (static or non-static)
and can be modified by access modifiers, that is, encapsulation can be achieved. When we need a class to be used only in another class or in the object of a class instance, and If you cannot access this class in other classes, you can modify it as private to reflect its encapsulation

Static inner classes and instance inner classes are used in java when a class needs to describe an additional complete structure:
for example, when writing a linked list or a binary tree hash table, an additional node structure is required inside, and this node structure only serves For the external linked list class, a node class can be encapsulated in the linked list at this time, and the internal class can be used to perfectly reflect this design requirement

Of course, instead of using internal classes, a node class can also be defined outside the linked list class, and a linked list can also be described by using a combination relationship, but this way of writing does not express the inclusion relationship between the linked list and nodes well and is not easy to encapsulate. can access the node class

Therefore, the use of static or instance inner classes can express the inclusion relationship more clearly

The static inner class is generally more commonly used than the instance inner class, because its syntax is more concise than the instance inner class and does not need to have an outer class object first, but the instance inner class can directly access the members of the outer class object, depending on the specific scenario.

Both local inner classes and anonymous inner classes are classes defined in the local code block area
Local inner classes are rarely used, but the feature of anonymous inner classes is widely used in java. There are many interfaces provided in java that need to be implemented to rewrite their methods, and anonymous inner classes are used to create a faster and more convenient A class implements an interface and overrides its methods

Four. Summary

This article introduces what is an inner class (used to describe the internal structure of the object), the inner class in java (instance inner class, static inner class, local inner class, anonymous inner class) instance inner class and static inner class are better described The internal structure of a class and its containment relationship also have encapsulation characteristics. Local internal classes are not commonly used. Anonymous internal classes can quickly construct a class that rewrites the methods of its implemented interfaces or inherited classes, and anonymous classes can only be used once , used to quickly get rewritten methods for use... and a brief introduction to the more specific usage of anonymous inner classes in simpler scenarios -> lambda expressions

insert image description here

Guess you like

Origin blog.csdn.net/lch1552493370/article/details/130780566