[Big Data] Study Notes 1 Java SE Chapter 7 Object-Oriented Basics (Part 2) 7.3 Internal Classes

[Big Data] Study Notes

insert image description here

1 Java SE

Chapter 7 Object-Oriented Fundamentals (Part 2)

7.3 Inner classes
7.3.1 Overview
  1. What are inner classes?

When a class A is defined inside another class B, the class A inside is called an inner class , and B is called an outer class .

  1. Why declare an inner class?

In general, follow the general principles of object-oriented development with high cohesion and low coupling. Ease of code maintenance and expansion.

Specifically, when there is another part of a thing that needs a complete structure to describe, and this complete internal structure only provides services for external things and is not used separately elsewhere, then the entire internal complete structure is the best Better use inner classes. And because the inner class is inside the outer class, it can directly access the private members of the outer class.

  1. What are the forms of inner classes?

According to the location of the inner class declaration (like the classification of variables), we can be divided into:

(1) Member inner class:

  • static member inner class
  • non-static member inner class

(2) Local inner class

  • named local inner class
  • anonymous inner class
7.3.2 Inner classes with members

If the non-static members of the outer class are not used in the member inner class, the inner class is usually declared as a static inner class, otherwise it is declared as a non-static inner class.

Grammar format:

【修饰符】 class 外部类{
    
    
    【其他修饰符】 【staticclass 内部类{
    
    
    }
}

[1] Static inner class

A member inner class with static modification is called a static inner class. Its features:

  • Like any other class, it's just another complete class structure defined in an outer class
    • You can inherit your own parent class you want to inherit, and implement the parent interfaces you want to implement, regardless of the parent class and parent interface of the external class
    • Structures such as attributes, methods, and constructors can be declared in static inner classes, including static members
    • Can be modified with abstract, so it can also be inherited by other classes
    • Final modification can be used to indicate that it cannot be inherited
    • After compilation, it has its own independent bytecode file, but the external class name and the $ symbol are preceded by the internal class name.
  • Unlike external classes, it allows four permission modifiers: public, protected, default, private
    • External classes only allow public or default
  • Only static members of outer classes can be used in static inner classes
    • Non-static members of an outer class cannot be used in a static inner class
    • If there is a variable in the inner class with the same name as the static member variable of the outer class, you can use "outer class name." to distinguish
  • Objects of static inner classes can be created outside the outer class without passing objects of the outer class (this should generally be avoided)

In fact, strictly speaking (in "The Java Language Specification" edited by James Gosling et al.), static inner classes are not inner classes, but the concept of nested classes similar to C++. External classes are just a namespace of static inner classes. The qualified name form of . Therefore, the inner class in the interface is usually not called an inner class, because the inner members in the interface are implicitly static (that is, public static). For example: Map.Entry.

[2] Non-static member inner class

A member inner class without static modification is called a non-static inner class. Features of non-static inner classes:

  • Like any other class, it's just another complete class structure defined in an outer class
    • You can inherit your own parent class you want to inherit, and implement the parent interfaces you want to implement, regardless of the parent class and parent interface of the external class
    • Structures such as attributes, methods, and constructors can be declared in non-static inner classes, but static members are not allowed to be declared , but static members of the parent class can be inherited , and static constants can be declared .
    • Can be modified with abstract, so it can also be inherited by other classes
    • Final modification can be used to indicate that it cannot be inherited
    • After compilation, it has its own independent bytecode file, but the external class name and the $ symbol are preceded by the internal class name.
  • Unlike external classes, it allows four permission modifiers: public, protected, default, private
    • External classes only allow public or default
  • You can also use all members of the outer class in the non-static inner class , even if it is private
  • Non-static inner classes cannot be used in static members of outer classes
    • Just like non-static member variables and non-static methods of this class cannot be accessed in static methods
  • Outside the outer class, objects of the outer class must be used to create objects of non-static inner classes (usually this should be avoided)
    • If you want to use an object of a non-static inner class outside the outer class, it is usually more appropriate to provide a method in the outer class to return the object of the non-static inner class
    • Therefore, there are two this objects in the method of the non-static inner class, one is the this object of the outer class, and the other is the this object of the inner class
package com.dingjiaxiong.inner.member;

/**
 * @Projectname: BigDataStudy
 * @Classname: TestMemberInnerClass
 * @Author: Ding Jiaxiong
 * @Date:2023/4/27 13:29
 */

public class TestMemberInnerClass {
    
    
    public static void main(String[] args) {
    
    
        Outer.outMethod();
        System.out.println("-----------------------");
        Outer out = new Outer();
        out.outFun();

        System.out.println("####################################");
        Outer.Inner.inMethod();
        System.out.println("------------------------");
        Outer.Inner inner = new Outer.Inner();
        inner.inFun();

        System.out.println("####################################");
        Outer outer = new Outer();
//        Outer.Nei nei = outer.new Nei();
        Outer.Nei nei = out.getNei();
        nei.inFun();
    }
}

class Outer {
    
    
    private static String a = "外部类的静态a";
    private static String b = "外部类的静态b";
    private String c = "外部类对象的非静态c";
    private String d = "外部类对象的非静态d";

    static class Inner {
    
    
        private static String a = "静态内部类的静态a";
        private String c = "静态内部类对象的非静态c";

        public static void inMethod() {
    
    
            System.out.println("Inner.inMethod");
            System.out.println("Outer.a = " + Outer.a);
            System.out.println("Inner.a = " + a);
            System.out.println("b = " + b);
//            System.out.println("c = " + c);//不能访问外部类和自己的非静态成员
//            System.out.println("d = " + d);//不能访问外部类的非静态成员
        }

        public void inFun() {
    
    
            System.out.println("Inner.inFun");
            System.out.println("Outer.a = " + Outer.a);
            System.out.println("Inner.a = " + a);
            System.out.println("b = " + b);
            System.out.println("c = " + c);
//            System.out.println("d = " + d);//不能访问外部类的非静态成员
        }
    }

    class Nei {
    
    
        private String a = "非静态内部类对象的非静态a";
        private String c = "非静态内部类对象的非静态c";

        public void inFun() {
    
    
            System.out.println("Nei.inFun");
            System.out.println("Outer.a = " + Outer.a);
            System.out.println("a = " + a);
            System.out.println("b = " + b);
            System.out.println("Outer.c = " + Outer.this.c);
            System.out.println("c = " + c);
            System.out.println("d = " + d);
        }
    }

    public static void outMethod() {
    
    
        System.out.println("Outer.outMethod");
        System.out.println("a = " + a);
        System.out.println("Inner.a = " + Inner.a);
        System.out.println("b = " + b);
//        System.out.println("c = " + c);
//        System.out.println("d = " + d);
        Inner in = new Inner();
        System.out.println("in.c = " + in.c);
    }

    public void outFun() {
    
    
        System.out.println("Outer.outFun");
        System.out.println("a = " + a);
        System.out.println("Inner.a = " + Inner.a);
        System.out.println("b = " + b);
        System.out.println("c = " + c);
        System.out.println("d = " + d);
        Inner in = new Inner();
        System.out.println("in.c = " + in.c);
    }

    public Nei getNei() {
    
    
        return new Nei();
    }
}

insert image description here

7.3.3 Local inner classes

[1] Local inner class

Grammar format:

【修饰符】 class 外部类{
    
    
    【修饰符】 返回值类型  方法名(【形参列表】){
    
    final/abstractclass 内部类{
    
    
    	}
    }    
}

Features of local inner classes:

  • Like the outer class, it is just another complete class structure defined in a method of the outer class
    • You can inherit your own parent class you want to inherit, and implement the parent interfaces you want to implement, regardless of the parent class and parent interface of the external class
    • Structures such as attributes, methods, and constructors can be declared in local inner classes, but static members are not included, unless they are inherited from a parent class or static constants
    • Can be modified with abstract, so it can also be inherited by other inner classes behind it in the same method
    • Final modification can be used to indicate that it cannot be inherited
    • After compilation, it has its own independent bytecode file, but the external class name, $ symbol, and number are prefixed with the internal class name.
      • There are numbers here because in the same outer class, there are local inner classes with the same name in different methods
  • Unlike member inner classes, it cannot be preceded by permission modifiers, etc.
  • Local inner classes have scope like local variables
  • Whether the local inner class can access the static or non-static members of the outer class depends on the method
  • In the local inner class, the local constant of the method can also be used, that is, the local variable declared with final
    • After JDK1.8, if a local variable is used in a local inner class, it will automatically add final
    • Why do you need to add final to the local variables that use the outer class method in the local inner class? Consider life cycle issues.

Sample code:

package com.dingjiaxiong.inner.local;

/**
 * @Projectname: BigDataStudy
 * @Classname: TestLocalInner
 * @Author: Ding Jiaxiong
 * @Date:2023/4/27 13:31
 */

public class TestLocalInner {
    
    
    public static void main(String[] args) {
    
    
        Runner runner = Outer.getRunner();
        runner.run();

        System.out.println("-------------------");
        Outer.outMethod();

        System.out.println("-------------------");
        Outer out = new Outer();
        out.outTest();
    }
}

class Outer {
    
    
    private static String a = "外部类的静态a";
    private String b = "外部类对象的非静态b";

    public static void outMethod() {
    
    
        System.out.println("Outer.outMethod");
        final String c = "局部变量c";
        class Inner {
    
    
            public void inMethod() {
    
    
                System.out.println("Inner.inMethod");
                System.out.println("out.a = " + a);
//				System.out.println("out.b = " + b);//错误的,因为outMethod是静态的
                System.out.println("out.local.c = " + c);
            }
        }

        Inner in = new Inner();
        in.inMethod();
    }

    public void outTest() {
    
    
        class Inner {
    
    
            public void inMethod() {
    
    
                System.out.println("out.a = " + a);
                System.out.println("out.b = " + b);//可以,因为outTest是非静态的
            }
        }

        Inner in = new Inner();
        in.inMethod();
    }

    public static Runner getRunner() {
    
    
        class LocalRunner implements Runner {
    
    
            @Override
            public void run() {
    
    
                System.out.println("LocalRunner.run");
            }
        }
        return new LocalRunner();
    }

}

interface Runner {
    
    
    void run();
}

insert image description here

[2] Anonymous inner class

When we are in the development process, we need to use an object of a subclass of an abstract class or an object of an implementation class of an interface, and only create one object, and the logic code is not complicated. So how did we do it?

(1) Write a class, inherit this parent class or implement this interface

(2) Override the method of the parent class or parent interface

(3) Create an object of this subclass or implementation class

Here, because considering that this subclass or implementation class is one-off, it seems superfluous for us to "take painstaking efforts" to name it. Then we can use the anonymous inner class to achieve it, avoiding the problem of naming the class.

new 父类(【实参列表】){
    
    
    重写方法...
}
//()中是否需要【实参列表】,看你想要让这个匿名内部类调用父类的哪个构造器,如果调用父类的无参构造,那么()中就不用写参数,如果调用父类的有参构造,那么()中需要传入实参
new 父接口(){
    
    
    重写方法...
}
//()中没有参数,因为此时匿名内部类的父类是Object类,它只有一个无参构造

An anonymous inner class is a class without a name, so a unique object is created when the class is declared.

Notice:

An anonymous inner class is a special kind of local inner class, but it has no name. All restrictions of local inner classes apply to anonymous inner classes. For example:

  • Whether the non-static member variable of the outer class can be used in the anonymous inner class depends on whether the method is static
  • If you need to access the local variable of the current method in the anonymous inner class, the local variable needs to be finalized

Think: What can this object do?

(1) Use the object of the anonymous inner class to directly call the method

interface A{
    
    
	void a();
}
public class Test{
    
    
    public static void main(String[] args){
    
    
    	new A(){
    
    
			@Override
			public void a() {
    
    
				System.out.println("aaaa");
			}
    	}.a();
    }
}

(2) Refer to the object of the anonymous inner class through the variable polymorphism of the parent class or parent interface

interface A{
    
    
	void a();
}
public class Test{
    
    
    public static void main(String[] args){
    
    
    	A obj = new A(){
    
    
			@Override
			public void a() {
    
    
				System.out.println("aaaa");
			}
    	};
    	obj.a();
    }
}

(3) Objects of anonymous inner classes as actual parameters

interface A{
    
    
	void method();
}
public class Test{
    
    
    public static void test(A a){
    
    
    	a.method();
    }
    
    public static void main(String[] args){
    
    
    	test(new A(){
    
    

			@Override
			public void method() {
    
    
				System.out.println("aaaa");
			}
    	});
    }   
}

Guess you like

Origin blog.csdn.net/weixin_44226181/article/details/130470067