Nested classes in JAVA pitfalls

1. Introduction to Nested Classes

1.1 Overview

Java nested classes refer to a way of defining another class within one class, which can improve the readability, maintainability and encapsulation of the code. Java nested classes are divided into two types: static nested classes and non-static nested classes.

Static nested classes: Static nested classes, that is, there is a static modifier in front of the class.
Non-static nested classes: Non-static nested classes, also known as inner classes, Inner classes

  • Ordinary inner class (also translated as: member inner class)
  • Local classes
  • Anonymous classes

1.2 Classification of nested classes

static nested class

 Ordinary inner class

local inner class

anonymous inner class

1.3 Reasons for use

  • Different access rights requirements, more fine-grained access control
  • Be concise and avoid too many class definitions
  • The language design is too complex and difficult to learn and use

2. Anonymous inner classes and local inner classes

2.1 Anonymous inner classes

An anonymous inner class is an inner class without a name. It is usually used to implement an interface or inherit an abstract class and is only used once. The essence of an anonymous inner class is an anonymous subclass object with a specific implementation of a parent class or parent interface. Anonymous inner classes can make your code more concise, and you can instantiate a class at the same time it is defined.

- An internal class without a class name must inherit a parent class/implement a parent interface
- After instantiation, it is quickly transformed into a parent class/parent interface
- This type of object can only create a new object, and then operate with the object name
1. Inner classes can be used in ordinary statements and member variable assignments.

interface MyInterface {
  void display();
}

class OuterClass {
  public void test() {
    // 使用匿名内部类实现接口
    MyInterface obj = new MyInterface() {
      @Override
      public void display() {
        System.out.println("我是匿名内部类");
      }
    };
    // 调用接口方法
    obj.display();
  }
}
package org.example;

public class Outer1 {
    private String name = "abc";
    //匿名内部类
    public void fl()
    {
        String name = "def"; // 加上 final 修饰符
        Runnable r = new Runnable() {
            //匿名内部类不能定义静态变量,除非是常量
            public final static int a = 1; // 加上 final 修饰符并赋值

            public void run(){
                System.out.println("hello " + Outer1.this.name); // 加上 Outer1.this.
            };
        };
        //静态方法不能在匿名内部类定义
//        public void static f2{
//
//        }
        new Thread(r).start();
        System.out.println(r.getClass().getName());

        Runnable r2 = new Runnable() { // 加上 new Runnable()
            String name = "def";
            public void run(){
                System.out.println("hello " + name);
            };
        };
        new Thread(r2).start();
        System.out.println(r2.getClass().getName());
    }

    public static void main(String[] args) {
        Outer1 obj = new Outer1(); // 创建外部类对象
        obj.fl(); // 调用外部类方法
        // 调用r2对象

    }
}

 2.2 Local inner classes

package org.example;

public class Outer2 {
    private String name = "abc";
    // 局部内部类
    public void fl() {
         String  name = "def";
        class Inner2 {
            final static int a = 1;
            String name = "ghi";
            public void f2() {
                System.out.println(name); // 输出 ghi
                System.out.println(Outer2.this.name);
            }
        }
        Inner2 obj1 = new Inner2();
        obj1.f2();
        System.out.println(obj1.getClass().getName()); // 输出 Outer2$1Inner2
    }
    public  static void f2() {
        String name = "def";
        class Inner2 {

            public void f2() {
                System.out.println(name); // 输出 ghi
                //System.out.println(Outer2.this.name);
            }
        }
        Inner2 obj1 = new Inner2();
        obj1.f2();
        System.out.println(obj1.getClass().getName()); // 输出 Outer2$1Inner2
    }
    public static void main(String[] args) {
        Outer2 obj = new Outer2(); // 创建外部类对象
        obj.fl(); // 调用外部类方法
        f2(); // 调用外部类静态方法
    }
}

2.3 Similarities and differences

The similarities between anonymous inner classes and local inner classes are:

  • Anonymous inner classes and local inner classes are inner classes defined in a method. They can only be used in that method and cannot be accessed elsewhere.
  • Both anonymous inner classes and local inner classes can access members of the outer class, but if you want to access local variables in a method, the local variables must be modified with final.

The main differences between anonymous inner classes and local inner classes are:

  • Anonymous inner classes have no names, while local inner classes have names.
  • Anonymous inner classes can only create objects once, while local inner classes can create multiple objects in a method.
  • Anonymous inner classes are usually used to implement interfaces or inherit abstract classes and are used only once. Local inner classes can inherit or implement any class or interface.
  • The syntax format of anonymous inner classes is: new class name or interface name () { overriding method; }. The syntax format of a local inner class is: class class name { member; }

3. Ordinary inner classes and static nested classes

3.1 Ordinary inner classes

class OuterClass {
    private int data = 10;
    public void test() {
        System.out.println("我是外部类成员方法");
    }
    class InnerClass {
        // 访问外部类的私有数据成员
        void getData() {
            System.out.println("data is " + data);
        }
        // 访问外部类的成员方法
        void getTest() {
            OuterClass.this.test();
        }
    }
}

public class Test {
    public static void main(String[] args) {
        // 创建外部类对象
        OuterClass myOuter = new OuterClass();
        // 创建内部类对象
        OuterClass.InnerClass myInner = myOuter.new InnerClass();
        // 调用内部类方法
        myInner.getData();
        myInner.getTest();
    }
}

3.2 Static nested classes

Static nested classes have the following characteristics:

  • A static nested class is a static member of an outer class. It can directly access itself using the outer class name. Static nested class name
  • A static nested class cannot access non-static members of the outer class, it can only use them through object references.
  • Static nested classes can use private, public, protected, or package-private access modifiers.
  • A static nested class is a top-level class in behavior, and is placed in an external class just to facilitate packaging.
class OuterClass {
    private static int data = 10;
    public static void test() {
        System.out.println("我是外部类静态方法");
    }
    static class StaticNestedClass {
        // 访问外部类的静态数据成员
        void getData() {
            System.out.println("data is " + data);
        }
        // 访问外部类的静态方法
        void getTest() {
            OuterClass.test();
        }
    }
}

public class Test {
    public static void main(String[] args) {
        // 创建静态嵌套类对象
        OuterClass.StaticNestedClass myNested = new OuterClass.StaticNestedClass();
        // 调用静态嵌套类方法
        myNested.getData();
        myNested.getTest();
    }
}

 

4. Comparison of nested classes 

4.1 Comparison

4.2 External access rules

4.3 Variable masking 

Guess you like

Origin blog.csdn.net/qq_62377885/article/details/132945138