📜  Java中的匿名内部类

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

Java中的匿名内部类

Java中的嵌套类是坚持了解匿名内部类之前的先决条件。它是一个没有名称的内部类,并且只为其创建了一个对象。匿名内部类在创建具有某些“附加”的对象实例时可能很有用,例如覆盖类或接口的方法,而不必实际子类化一个类。

匿名类表达式的语法类似于构造函数的调用,不同之处在于代码块中包含类定义。

句法:

// Test can be interface,abstract/concrete class
Test t = new Test() 
{
   // data members and methods
   public void test_method() 
   {
      ........
      ........
    }   
};

现在让我们来讨论一下常规类(普通类)和匿名内部类之间的区别

  • 普通类可以实现任意数量的接口,但匿名内部类一次只能实现一个接口。
  • 常规类可以扩展一个类并同时实现任意数量的接口。但是匿名内部类可以扩展一个类或可以实现一个接口,但不能同时实现两者。
  • 对于常规/普通类,我们可以编写任意数量的构造函数,但我们不能为匿名内部类编写任何构造函数,因为匿名类没有任何名称,并且在定义构造函数时类名和构造函数名称必须相同。

访问封闭范围的局部变量,以及声明和访问匿名类的成员

和本地类一样,匿名类可以捕获变量;它们对封闭范围的局部变量具有相同的访问权限:

  • 匿名类可以访问其封闭类的成员。
  • 匿名类无法访问其封闭范围内未声明为 final 或有效 final 的局部变量。
  • 与嵌套类一样,匿名类中的类型(例如变量)声明会隐藏封闭范围内具有相同名称的任何其他声明。

匿名类对其成员也有与本地类相同的限制:

  • 我们不能在匿名类中声明静态初始化器或成员接口。
  • 匿名类可以具有静态成员,前提是它们是常量变量。

方法:

匿名内部类是通用的,通过下面列出的两种方式创建:

  1. 类(可以是抽象的或具体的)
  2. 界面

现在让我们举一个例子来理解匿名内部类,让我们举一个简单的程序

例子

Java
// Java program to demonstrate Need for
// Anonymous Inner class
 
// Interface
interface Age {
 
    // Defining variables and methods
    int x = 21;
    void getAge();
}
 
// Class 1
// Helper class implementing methods of Age Interface
class MyClass implements Age {
 
    // Overriding getAge() method
    @Override public void getAge()
    {
        // Print statement
        System.out.print("Age is " + x);
    }
}
 
// Class 2
// Main class
// AnonymousDemo
class GFG {
    // Main driver method
    public static void main(String[] args)
    {
        // Class 1 is implementation class of Age interface
        MyClass obj = new MyClass();
 
        // calling getage() method implemented at Class1
        // inside main() method
        obj.getAge();
    }
}


Java
// Java Program to Demonstrate Anonymous inner class
 
// Interface
interface Age {
    int x = 21;
    void getAge();
}
 
// Main class
class AnonymousDemo {
   
    // Main driver method
    public static void main(String[] args)
    {
 
        // Myclass is hidden inner class of Age interface
        // whose name is not written but an object to it
        // is created.
        Age oj1 = new Age() {
           
            @Override public void getAge()
            {
                // printing  age
                System.out.print("Age is " + x);
            }
        };
       
        oj1.getAge();
    }
}


Java
// Java program to illustrate creating an immediate thread
// Using Anonymous Inner class that extends a Class
 
// Main class
class MyThread {
   
    // Main driver method
    public static void main(String[] args)
    {
        // Using Anonymous Inner class that extends a class
        // Here a Thread class
        Thread t = new Thread() {
           
            // run() method for the thread
            public void run()
            {
                // Print statement for child thread
                // execution
                System.out.println("Child Thread");
            }
        };
 
        // Starting the thread
        t.start();
 
        // Displaying main thread only for readability
        System.out.println("Main Thread");
    }
}


Java
// Java program to illustrate defining a thread
// Using Anonymous Inner class that implements an interface
 
// Main class
class MyThread {
   
    // Main driver method
    public static void main(String[] args)
    {
        // Here we are using Anonymous Inner class
        // that implements a interface i.e. Here Runnable
        // interface
        Runnable r = new Runnable() {
           
            // run() method for the thread
            public void run()
            {
                // Print statement when run() is invoked
                System.out.println("Child Thread");
            }
        };
 
        // Creating thread in main() using Thread class
        Thread t = new Thread(r);
 
        // Starting the thread using start() method
        // which invokes run() method automatically
        t.start();
 
        // Print statement only
        System.out.println("Main Thread");
    }
}


Java
// Java program to illustrate defining a thread
// Using Anonymous Inner class that define inside argument
 
// Main class
class MyThread {
    // Main driver method
    public static void main(String[] args)
    {
        // Using Anonymous Inner class that define inside
        // argument
        // Here constructor argument
        Thread t = new Thread(new Runnable() {
           
            public void run()
            {
                System.out.println("Child Thread");
            }
        });
 
        t.start();
 
        System.out.println("Main Thread");
    }
}


输出:

输出说明:

在上面的程序中,接口 Age 是用 getAge() 方法创建的,x=21。 Myclass 是作为 Age 接口的实现类编写的。正如在 Program 中所做的那样,无需编写单独的类 Myclass。而是直接将 Myclass 的代码复制到这个参数中,如下所示:

Age oj1 = new Age() 
{
    @Override
    public void getAge() 
    {
        System.out.print("Age is " + x);
    }
};

例子:

Java

// Java Program to Demonstrate Anonymous inner class
 
// Interface
interface Age {
    int x = 21;
    void getAge();
}
 
// Main class
class AnonymousDemo {
   
    // Main driver method
    public static void main(String[] args)
    {
 
        // Myclass is hidden inner class of Age interface
        // whose name is not written but an object to it
        // is created.
        Age oj1 = new Age() {
           
            @Override public void getAge()
            {
                // printing  age
                System.out.print("Age is " + x);
            }
        };
       
        oj1.getAge();
    }
}
输出
Age is 21

匿名内部类的类型

根据声明和行为,有 3 种匿名 Inner 类:

  1. 扩展类的匿名内部类
  2. 实现接口的匿名内部类
  3. 定义内部方法/构造函数参数的匿名内部类

类型 1:扩展类的匿名内部类

我们可以有一个扩展类的匿名内部类。例如,我们知道可以通过扩展 Thread 类来创建线程。假设我们需要一个即时线程,但我们不想一直创建一个扩展 Thread 类的类。借助这种类型的 Anonymous Inner 类,我们可以定义一个就绪线程。

例子

Java

// Java program to illustrate creating an immediate thread
// Using Anonymous Inner class that extends a Class
 
// Main class
class MyThread {
   
    // Main driver method
    public static void main(String[] args)
    {
        // Using Anonymous Inner class that extends a class
        // Here a Thread class
        Thread t = new Thread() {
           
            // run() method for the thread
            public void run()
            {
                // Print statement for child thread
                // execution
                System.out.println("Child Thread");
            }
        };
 
        // Starting the thread
        t.start();
 
        // Displaying main thread only for readability
        System.out.println("Main Thread");
    }
}
输出
Main Thread
Child Thread

类型 2:实现接口的匿名内部类

我们还可以有一个实现接口的匿名内部类。例如,我们也知道通过实现 Runnable 接口我们可以创建一个 Thread。这里我们使用一个实现接口的匿名 Inner 类。

例子

Java

// Java program to illustrate defining a thread
// Using Anonymous Inner class that implements an interface
 
// Main class
class MyThread {
   
    // Main driver method
    public static void main(String[] args)
    {
        // Here we are using Anonymous Inner class
        // that implements a interface i.e. Here Runnable
        // interface
        Runnable r = new Runnable() {
           
            // run() method for the thread
            public void run()
            {
                // Print statement when run() is invoked
                System.out.println("Child Thread");
            }
        };
 
        // Creating thread in main() using Thread class
        Thread t = new Thread(r);
 
        // Starting the thread using start() method
        // which invokes run() method automatically
        t.start();
 
        // Print statement only
        System.out.println("Main Thread");
    }
}
输出
Main Thread
Child Thread

类型 3:定义内部方法/构造函数参数的匿名内部类

方法/构造函数参数中的匿名内部类通常用于图形用户界面 (GUI) 应用程序。为了让您熟悉语法,让我们看看下面的程序,它使用这种类型的匿名内部类创建线程

例子

Java

// Java program to illustrate defining a thread
// Using Anonymous Inner class that define inside argument
 
// Main class
class MyThread {
    // Main driver method
    public static void main(String[] args)
    {
        // Using Anonymous Inner class that define inside
        // argument
        // Here constructor argument
        Thread t = new Thread(new Runnable() {
           
            public void run()
            {
                System.out.println("Child Thread");
            }
        });
 
        t.start();
 
        System.out.println("Main Thread");
    }
}
输出
Main Thread
Child Thread