📜  Java中的内部类

📅  最后修改于: 2022-05-13 01:55:04.884000             🧑  作者: Mango

Java中的内部类

在Java中,内部类是指在主要引入的类或接口内部声明的类,概括起来,与Java相同的逻辑相关类是纯面向对象的,因此更接近现实世界。现在,您一定想知道为什么要介绍它们?

与内部类相关的某些优点如下:

  • 使代码干净易读。
  • 可以访问外部类的私有方法,从而带来新的维度并使其更接近现实世界。
  • 优化代码模块。

内部类的类型

Java中基本上有四种类型的内部类。

  1. 嵌套内部类
  2. 方法局部内部类
  3. 静态嵌套类
  4. 匿名内部类

让我们依次深入讨论上述每种类型以及一个干净的Java程序,这在每一步都非常关键,因为随着我们的坚持,它变得非常棘手。

类型 1:嵌套内部类

它可以访问外部类的任何私有实例变量。像任何其他实例变量一样,我们可以拥有访问修饰符 private、protected、public 和 default 修饰符。像类一样,接口也可以嵌套并且可以具有访问说明符。

示例 1A

Java
// Java Program to Demonstrate Nested class 
 
// Class 1
// Helper classes
class Outer {
 
    // Class 2
    // Simple nested inner class
    class Inner {
 
        // show() method of inner class
        public void show()
        {
 
            // Print statement
            System.out.println("In a nested class method");
        }
    }
}
 
// Class 2
// Main class
class Main {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Note how inner class object is created inside
        // main()
        Outer.Inner in = new Outer().new Inner();
 
        // Calling show() method over above object created
        in.show();
    }
}


Java
// Java Program to Demonstrate Nested class 
// Where Error is thrown
 
// Class 1
// Outer class
class Outer {
 
    // Method defined inside outer class
    void outerMethod()
    {
 
        // Print statement
        System.out.println("inside outerMethod");
    }
 
    // Class 2
    // Inner class
    class Inner {
 
        // Main driver method
        public static void main(String[] args)
        {
 
            // Display message for better readability
            System.out.println("inside inner class Method");
        }
    }
}


Java
// Java Program to Illustrate Inner class can be
// declared within a method of outer class
 
// Class 1
// Outer class
class Outer {
 
    // Method inside outer class
    void outerMethod()
    {
 
        // Print statement
        System.out.println("inside outerMethod");
 
        // Class 2
        // Inner class
        // It is local to outerMethod()
        class Inner {
 
            // Method defined inside inner class
            void innerMethod()
            {
 
                // Print statement whenever inner class is
                // called
                System.out.println("inside innerMethod");
            }
        }
 
        // Creating object of inner class
        Inner y = new Inner();
 
        // Calling over method defined inside it
        y.innerMethod();
    }
}
 
// Class 3
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating object of outer class inside main()
        // method
        Outer x = new Outer();
 
        // Calling over the same method
        // as we did for inner class above
        x.outerMethod();
    }
}


Java
class Outer {
   void outerMethod() {
      int x = 98;
      System.out.println("inside outerMethod");
      class Inner {
         void innerMethod() {
            System.out.println("x= "+x);
         }
      }
      Inner y = new Inner();
      y.innerMethod();
   }
}
class MethodLocalVariableDemo {
   public static void main(String[] args) {
      Outer x=new Outer();
      x.outerMethod();
   }
}


Java
class Outer {
   void outerMethod() {
      final int x=98;
      System.out.println("inside outerMethod");
      class Inner {
         void innerMethod() {
            System.out.println("x = "+x);
         }
      }
      Inner y = new Inner();
      y.innerMethod();
   }
}
class MethodLocalVariableDemo {
    public static void main(String[] args){
      Outer x = new Outer();
      x.outerMethod();
    }
}


Java
// Java Program to Illustrate Static Nested Classes
 
// Importing required classes
import java.util.*;
 
// Class 1
// Outer class
class Outer {
 
    // Method
    private static void outerMethod()
    {
 
        // Print statement
        System.out.println("inside outerMethod");
    }
 
    // Class 2
    // Static inner class
    static class Inner {
 
        public static void display()
        {
 
            // Print statement
            System.out.println("inside inner class Method");
 
            // Calling method inside main() method
            outerMethod();
        }
    }
}
 
// Class 3
// Main class
class GFG {
 
    // Main driver method
    public static void main(String args[])
    {
 
        Outer.Inner obj = new Outer.Inner();
 
        // Calling method via above instance created
        obj.display();
    }
}


Java
// Java Program to Illustrate Anonymous Inner classes
// Declaration Without any Name 
// As a subclass of the specified type
 
// Importing required classes
import java.util.*;
 
// Class 1
// Helper class
class Demo {
 
    // Method of helper class
    void show()
    {
        // Print statement
        System.out.println(
            "i am in show method of super class");
    }
}
 
// Class 2
// Main class
class Flavor1Demo {
 
    //  An anonymous class with Demo as base class
    static Demo d = new Demo() {
        // Method 1
        // show() method
        void show()
        {
            // Calling method show() via super keyword
            // which refers to parent class
            super.show();
 
            // Print statement
            System.out.println("i am in Flavor1Demo class");
        }
    };
 
    // Method 2
    // Main driver method
    public static void main(String[] args)
    {
        // Calling show() method inside main() method
        d.show();
    }
}


Java
// Java Program to Illustrate Anonymous Inner Classes
// Declaration Without Any Name
// As an implementer of Specified interface
 
// Interface
interface Hello {
 
    // Method defined inside interface
    void show();
}
 
// Main class
class GFG {
 
    // Class implementing interface
    static Hello h = new Hello() {
       
        // Method 1
        // show() method inside main class
        public void show()
        {
            // Print statement
            System.out.println("i am in anonymous class");
        }
    };
 
    // Method 2
    // Main driver method
    public static void main(String[] args)
    {
        // Calling show() method inside main() method
        h.show();
    }
}


输出
In a nested class method

示例 1B

Java

// Java Program to Demonstrate Nested class 
// Where Error is thrown
 
// Class 1
// Outer class
class Outer {
 
    // Method defined inside outer class
    void outerMethod()
    {
 
        // Print statement
        System.out.println("inside outerMethod");
    }
 
    // Class 2
    // Inner class
    class Inner {
 
        // Main driver method
        public static void main(String[] args)
        {
 
            // Display message for better readability
            System.out.println("inside inner class Method");
        }
    }
}

输出:

类型 2:方法本地内部类

内部类可以在外部类的方法中声明,我们将在下面的示例中说明,其中 Inner 是 outerMethod() 中的内部类。

示例 1

Java

// Java Program to Illustrate Inner class can be
// declared within a method of outer class
 
// Class 1
// Outer class
class Outer {
 
    // Method inside outer class
    void outerMethod()
    {
 
        // Print statement
        System.out.println("inside outerMethod");
 
        // Class 2
        // Inner class
        // It is local to outerMethod()
        class Inner {
 
            // Method defined inside inner class
            void innerMethod()
            {
 
                // Print statement whenever inner class is
                // called
                System.out.println("inside innerMethod");
            }
        }
 
        // Creating object of inner class
        Inner y = new Inner();
 
        // Calling over method defined inside it
        y.innerMethod();
    }
}
 
// Class 3
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating object of outer class inside main()
        // method
        Outer x = new Outer();
 
        // Calling over the same method
        // as we did for inner class above
        x.outerMethod();
    }
}
输出
inside outerMethod
inside innerMethod

方法局部内部类不能使用外部方法的局部变量,直到该局部变量未声明为最终变量。例如,以下代码会生成编译器错误。

示例 2

Java

class Outer {
   void outerMethod() {
      int x = 98;
      System.out.println("inside outerMethod");
      class Inner {
         void innerMethod() {
            System.out.println("x= "+x);
         }
      }
      Inner y = new Inner();
      y.innerMethod();
   }
}
class MethodLocalVariableDemo {
   public static void main(String[] args) {
      Outer x=new Outer();
      x.outerMethod();
   }
}
输出
inside outerMethod
x= 98

但是下面的代码编译并运行良好(注意这次 x 是最终的)

示例 3

Java

class Outer {
   void outerMethod() {
      final int x=98;
      System.out.println("inside outerMethod");
      class Inner {
         void innerMethod() {
            System.out.println("x = "+x);
         }
      }
      Inner y = new Inner();
      y.innerMethod();
   }
}
class MethodLocalVariableDemo {
    public static void main(String[] args){
      Outer x = new Outer();
      x.outerMethod();
    }
}
输出
inside outerMethod
x = 98

我们需要将局部变量声明为 final 的主要原因是局部变量一直在堆栈上,直到方法在堆栈上,但内部类的对象可能仍然存在于堆上。
方法本地内部类不能标记为私有、受保护、静态和瞬态,但可以标记为抽象和最终,但不能同时标记。

类型 3:静态嵌套类

静态嵌套类在技术上不是内部类。它们就像外部类的静态成员。

例子

Java

// Java Program to Illustrate Static Nested Classes
 
// Importing required classes
import java.util.*;
 
// Class 1
// Outer class
class Outer {
 
    // Method
    private static void outerMethod()
    {
 
        // Print statement
        System.out.println("inside outerMethod");
    }
 
    // Class 2
    // Static inner class
    static class Inner {
 
        public static void display()
        {
 
            // Print statement
            System.out.println("inside inner class Method");
 
            // Calling method inside main() method
            outerMethod();
        }
    }
}
 
// Class 3
// Main class
class GFG {
 
    // Main driver method
    public static void main(String args[])
    {
 
        Outer.Inner obj = new Outer.Inner();
 
        // Calling method via above instance created
        obj.display();
    }
}
输出
inside inner class Method
inside outerMethod

类型 4:匿名内部类

匿名内部类的声明根本没有任何名称。它们以两种方式创建。

  • 作为指定类型的子类
  • 作为指定接口的实现者

方式一:作为指定类型的子类

例子:

Java

// Java Program to Illustrate Anonymous Inner classes
// Declaration Without any Name 
// As a subclass of the specified type
 
// Importing required classes
import java.util.*;
 
// Class 1
// Helper class
class Demo {
 
    // Method of helper class
    void show()
    {
        // Print statement
        System.out.println(
            "i am in show method of super class");
    }
}
 
// Class 2
// Main class
class Flavor1Demo {
 
    //  An anonymous class with Demo as base class
    static Demo d = new Demo() {
        // Method 1
        // show() method
        void show()
        {
            // Calling method show() via super keyword
            // which refers to parent class
            super.show();
 
            // Print statement
            System.out.println("i am in Flavor1Demo class");
        }
    };
 
    // Method 2
    // Main driver method
    public static void main(String[] args)
    {
        // Calling show() method inside main() method
        d.show();
    }
}
输出
i am in show method of super class
i am in Flavor1Demo class

在上面的代码中,我们有两个类 Demo 和 Flavor1Demo。这里 demo 充当超类,匿名类充当子类,两个类都有一个方法 show()。在匿名类 show() 方法被覆盖。

方式二:作为指定接口的实现者

例子:

Java

// Java Program to Illustrate Anonymous Inner Classes
// Declaration Without Any Name
// As an implementer of Specified interface
 
// Interface
interface Hello {
 
    // Method defined inside interface
    void show();
}
 
// Main class
class GFG {
 
    // Class implementing interface
    static Hello h = new Hello() {
       
        // Method 1
        // show() method inside main class
        public void show()
        {
            // Print statement
            System.out.println("i am in anonymous class");
        }
    };
 
    // Method 2
    // Main driver method
    public static void main(String[] args)
    {
        // Calling show() method inside main() method
        h.show();
    }
}
输出
i am in anonymous class

输出说明: