search
HomeJavajavaTutorialDetailed explanation of anonymous inner classes
Detailed explanation of anonymous inner classesDec 15, 2016 pm 12:29 PM
anonymous inner class

In the Java Improvement Chapter - Detailed Explanation of Internal Classes, anonymous internal classes are briefly introduced. However, there are many other detailed problems with internal classes, so this blog was derived. In this blog, you can learn about the use of anonymous inner classes, things to pay attention to in anonymous inner classes, how to initialize anonymous inner classes, and why the formal parameters used by anonymous inner classes must be final.


1. Use anonymous inner classes Internal classes

Since anonymous inner classes have no names, the way they are created is a bit strange. The creation format is as follows:

new 父类构造器(参数列表)|实现接口()    
    {    
     //匿名内部类的类体部分    
    }

Here we see that to use anonymous inner classes we must inherit a parent class or implement an interface. Of course, we can only inherit one parent class or implement an interface. At the same time, it does not have the class keyword, because anonymous inner classes directly use new to generate a reference to an object. Of course this reference is implicit.

public abstract class Bird {  
    private String name;  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
      
    public abstract int fly();  
}  
  
public class Test {  
      
    public void test(Bird bird){  
        System.out.println(bird.getName() + "能够飞 " + bird.fly() + "米");  
    }  
      
    public static void main(String[] args) {  
        Test test = new Test();  
        test.test(new Bird() {  
              
            public int fly() {  
                return 10000;  
            }  
              
            public String getName() {  
                return "大雁";  
            }  
        });  
    }  
}  
------------------  
Output:  
大雁能够飞 10000米

In the Test class, the test() method accepts a Bird type parameter. At the same time, we know that there is no way to directly new an abstract class. We must first have an implementation class before we can new its implementation class instance. So use the anonymous inner class directly in the main method to create a Bird instance.

Since an anonymous inner class cannot be an abstract class, it must implement all abstract methods in its abstract parent class or interface.名 For this anonymous internal code, it can actually be split into the following form:

public class WildGoose extends Bird{  
    public int fly() {  
        return 10000;  
    }  
      
    public String getName() {  
        return "大雁";  
    }  
}  
  
WildGoose wildGoose = new WildGoose();  
test.test(wildGoose);

Here the system will create an object that inherits anonymous class from the Bird class, which is transformed into a reference to Bird type.

There is a flaw in the use of anonymous inner classes, that is, they can only be used once. When creating an anonymous inner class, it will immediately create an instance of the class, and the definition of the class will disappear immediately, so the anonymous inner class It cannot be reused. For the above example, if we need to use the inner class in the test() method multiple times, it is recommended to redefine the class instead of using an anonymous inner class.


2. Precautions

In the process of using anonymous inner classes, we need to pay attention to the following points:

1. When using anonymous inner classes, we must inherit a class or implement an interface, but both You can't have both, and you can only inherit one class or implement one interface.

2. Constructors cannot be defined in anonymous inner classes.

3. There cannot be any static member variables and static methods in anonymous inner classes.

4. Anonymous inner classes are local inner classes, so all restrictions on local inner classes also apply to anonymous inner classes.

5. An anonymous inner class cannot be abstract. It must implement all abstract methods of the inherited class or implemented interface.


3. Why should the formal parameters used be final

When we pass parameters to anonymous inner classes, if the formal parameter needs to be used in the inner class, then the formal parameter must be final. That is to say: when the formal parameter of the method needs to be used in the inner class, the formal parameter must be final.

Why does it have to be final?

First of all, we know that after the internal class is compiled successfully, it will generate a class file. This class file is not the same class file as the external class, but only retains a reference to the external class. When the parameters passed in by the external class need to be called by the internal class, from the perspective of the Java program, they are called directly:

public class OuterClass {  
    public void display(final String name,String age){  
        class InnerClass{  
            void display(){  
                System.out.println(name);  
            }  
        }  
    }  
}

From the above code, it seems that the name parameter should be called directly by the internal class? In fact, it is not the case. The actual operation after java compilation is as follows:

public class OuterClass$InnerClass {  
    public InnerClass(String name,String age){  
        this.InnerClass$name = name;  
        this.InnerClass$age = age;  
    }  
      
      
    public void display(){  
        System.out.println(this.InnerClass$name + "----" + this.InnerClass$age );  
    }  
}

So judging from the above code, the internal class does not directly call the parameters passed by the method, but uses its own constructor to back up the parameters passed in. What the method calls is actually its own properties rather than the parameters passed in by the external method.

       直到这里还没有解释为什么是final?在内部类中的属性和外部方法的参数两者从外表上看是同一个东西,但实际上却不是,所以他们两者是可以任意变化的,也就是说在内部类中我对属性的改变并不会影响到外部的形参,而然这从程序员的角度来看这是不可行的,毕竟站在程序的角度来看这两个根本就是同一个,如果内部类该变了,而外部方法的形参却没有改变这是难以理解和不可接受的,所以为了保持参数的一致性,就规定使用final来避免形参的不改变。

      简单理解就是,拷贝引用,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变。

      故如果定义了一个匿名内部类,并且希望它使用一个其外部定义的参数,那么编译器会要求该参数引用是final的。


       四、匿名内部类初始化

       我们一般都是利用构造器来完成某个实例的初始化工作的,但是匿名内部类是没有构造器的!那怎么来初始化匿名内部类呢?使用构造代码块!利用构造代码块能够达到为匿名内部类创建一个构造器的效果。

public class OutClass {  
    public InnerClass getInnerClass(final int age,final String name){  
        return new InnerClass() {  
            int age_ ;  
            String name_;  
            //构造代码块完成初始化工作  
            {  
                if(0 < age && age < 200){  
                    age_ = age;  
                    name_ = name;  
                }  
            }  
            public String getName() {  
                return name_;  
            }  
              
            public int getAge() {  
                return age_;  
            }  
        };  
    }  
      
    public static void main(String[] args) {  
        OutClass out = new OutClass();  
          
        InnerClass inner_1 = out.getInnerClass(201, "chenssy");  
        System.out.println(inner_1.getName());  
          
        InnerClass inner_2 = out.getInnerClass(23, "chenssy");  
        System.out.println(inner_2.getName());  
    }  
}


更多详解匿名内部类相关文章请关注PHP中文网!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Java 匿名内部类如何解决内存泄漏问题?Java 匿名内部类如何解决内存泄漏问题?May 01, 2024 pm 10:30 PM

匿名内部类可导致内存泄漏,问题在于它们持有外部类的引用,从而阻止外部类被垃圾回收。解决方法包括:1.使用弱引用,当外部类不再被强引用持有时,垃圾回收器会立即回收弱引用对象;2.使用软引用,垃圾回收器会在进行垃圾回收时需要内存时才回收软引用对象。在实战中,例如Android应用中,可以通过使用弱引用来解决因匿名内部类引起的内存泄漏问题,从而在不需要监听器时回收匿名内部类。

Java 匿名内部类的设计模式有哪些?Java 匿名内部类的设计模式有哪些?May 02, 2024 pm 04:42 PM

匿名内部类是Java中没有显式名称、通过new表达式创建的特殊内部类,主要用于实现特定接口或扩展抽象类,并在创建后立即使用。常见的匿名内部类设计模式包括:适配器模式:将一个接口转换为另一个接口。策略模式:定义和替换算法。观察者模式:注册观察者并处理事件。它在实际应用中非常有用,例如按字符串长度排序TreeSet、创建匿名线程等。

Java 匿名内部类有哪些优势?Java 匿名内部类有哪些优势?Apr 30, 2024 am 11:39 AM

匿名内部类在Java中作为方便创建子类、简化代码和处理事件(例如按钮单击)的特殊内部类。实战案例包括:事件处理:使用匿名内部类为按钮添加单击事件监听器。数据转换:使用Collections.sort方法和匿名内部类作为比较器对集合进行排序。

Java 匿名内部类的生命周期是怎样的?Java 匿名内部类的生命周期是怎样的?May 01, 2024 pm 04:06 PM

匿名内部类的生命周期由其作用域决定:方法局部内部类:仅在创建它的方法范围内有效。构造器内部类:与外部类实例绑定,当外部类实例释放时释放。静态内部类:与外部类同时加载卸载。

Java 匿名内部类有哪些常见错误?Java 匿名内部类有哪些常见错误?May 02, 2024 am 09:03 AM

匿名内部类使用错误:在非线程安全环境中使用捕获未声明的异常访问超出范围的变量

Java 匿名内部类如何优化性能?Java 匿名内部类如何优化性能?May 02, 2024 am 08:48 AM

匿名内部类的性能问题在于每次使用都会重新创建,可通过以下策略优化:1.将匿名内部类存储在局部变量中;2.使用非静态内部类;3.使用lambda表达式。实战测试表明lambda表达式优化效果最佳。

Java 匿名内部类的替代方案是什么?Java 匿名内部类的替代方案是什么?Apr 30, 2024 pm 01:15 PM

Lambda表达式作为匿名内部类的替代方案,提供了更简洁的方式来定义函数式接口的实现:使用简短语法(parameters)->expression定义匿名函数。适用于需要实现函数式接口(只有一个抽象方法)的场合。能够简化列表排序和线程定义等任务。

Java 匿名内部类如何应用于线程?Java 匿名内部类如何应用于线程?May 02, 2024 pm 01:57 PM

匿名内部类可简化多线程代码的创建,无需命名,支持即时定义和使用线程类。主要优势在于简化代码,而限制是无法扩展。在需要快速创建一两个线程时使用,保持代码简短,如果需要更复杂的逻辑,应创建单独的类文件。

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
Repo: How To Revive Teammates
1 months agoBy尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Atom editor mac version download

Atom editor mac version download

The most popular open source editor

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

Powerful PHP integrated development environment

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools