Java之匿名类讲解

参考https://blog.csdn.net/jiaotuwoaini/article/details/51542059

匿名类,正如名字一样在java中没有名字标识的类,当然了编译后还是会安排一个名字的。

下面是一个关于匿名类的简单例子:

public class Client {  

    public static void main(String[] args) throws InterruptedException {
        Thread t=new Thread(new Runnable() {  

            @Override
            public void run() {
                System.out.println("hello,dusk!");  

            }
        });
        t.start();
    }  

}  

Java语言规范上是这么描述匿名类的:

匿名类的声明:

匿名类的声明是由java编译器自动派生自一个类实例创建表达式。

匿名类永远不能是抽象的。

匿名类总是隐式的final。

匿名类总是一个内部类;并且不能是static的。

匿名构造函数:

匿名类不能有显式声明的构造函数。相反的,Java编译器必须为这个匿名类自动提供一个匿名构造函数。匿名类C继承于父类S那么匿名构造函数是下面的形式:

  • 如果S不是一个内部类或者S是一个静态上下文中的局部类,那么这个匿名构造函数有一个形参为每一个在C的类实例创建表达式中的实际参数。

类的实例创建表达式的实际参数用来确定S的一个构造函数cs,使用方法调用相同的规则。

每一个匿名构造函数的形参必须和cs中的相关形参一致。

这个构造函数中显式的包括super(...)构造函数调用,这个实际参数是构造函数的形参,按它们声明的顺序。

  • 否则,C的构造函数第一个形参描述了这个值,直接包围实例i相对于S。参数的类型是S的class类型。

构造函数有一个额外的形参为每一个类实例创建语句声明在匿名类中的实际参数。第n个形参和第n-1个实际参数相关。

类的实例创建表达式的实际参数用来确定S的一个构造函数cs,使用方法调用相同的规则。

每一个匿名构造函数的形参必须和cs中的相关形参一致。

这个构造函数中显式的包括super(...)构造函数调用,这个实际参数是构造函数的形参,按它们声明的顺序。

在所有的情况下,匿名构造函数的throws语句必须列出所有的检查异常,包括父类构造函数显式调用语句抛出的和匿名类的实例初始化或者变量初始化抛出的异常。

注意:匿名构造函数的签名涉及到了一个不可达类型是可能的(例如,出现在父类构造函数中的类型),这不会导致任何编译时和运行时错误。

实际使用中我们只需注意这几点儿:

1、使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。
      2、匿名内部类中是不能定义构造函数的。
      3、匿名内部类中不能存在任何的静态成员变量和静态方法。
      4、匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。
      5、匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。

编译时的命名规则:

  • 内部类的class文件命名是:主类+$+内部类名
  • 匿名类的class文件命名是:主类+$+(1,2,3....)

定义一个场景:

package com.dusk.anonymous;  

public class AnonymousClassTest {
    private Runnable r1=new Runnable() {  

        @Override
        public void run() {
            System.out.println(1);
        }
    };
    public void method1(){
        Runnable r2=new Runnable() {  

            @Override
            public void run() {
                System.out.println(2);
            }
        };
    }
    public static void main(String[] args) {
            Runnable r3=new Runnable() {  

                @Override
                public void run() {
                    System.out.println(3);
                }
            };
    }
}  

从代码中我们可以看出定义了三个匿名类:

我们反编译出来:

package com.dusk.anonymous;  

import java.io.PrintStream;  

class AnonymousClassTest$1
  implements Runnable
{
  AnonymousClassTest$1(AnonymousClassTest paramAnonymousClassTest) {}  

  public void run()
  {
    System.out.println(1);
  }
}  

package com.dusk.anonymous;  

import java.io.PrintStream;  

class AnonymousClassTest$2
  implements Runnable
{
  AnonymousClassTest$2(AnonymousClassTest paramAnonymousClassTest) {}  

  public void run()
  {
    System.out.println(2);
  }
}  

package com.dusk.anonymous;  

import java.io.PrintStream;  

class AnonymousClassTest$3
  implements Runnable
{
  public void run()
  {
    System.out.println(3);
  }
}  

我们可以看出匿名类的名字中的数字和他们在代码中出现的位置一模一样。

原文地址:https://www.cnblogs.com/lijingran/p/9095652.html

时间: 2024-10-12 08:36:39

Java之匿名类讲解的相关文章

Java通过匿名类来实现回调函数

在C语言中,函数名可以当做函数指针传递给形参从而实现回调 void f1() { printf("f1()\n"); } void f2() { printf("f2()\n"); } void f3() { printf("f3()\n"); } void do_func(void(*f)()) { f(); } int main() { do_func(f1); do_func(f2); do_func(f3); } 在C++11中,实现回调

java中匿名类的注意细节

abstract class Outer{ int num; public Outer(int x){ num = x; } public abstract void show1(); public abstract void show2(); } public class PC{ public static void main(String[] args){ new Outer(55)//构造父类部分 //子类重写部分 { public void show1(){ System.out.pri

java:使用匿名类直接new接口

java中的匿名类有一个倍儿神奇的用法,见下面代码示例: package contract; public interface ISay { void sayHello(); } 上面是一个简单的接口,下面是如何使用: package jimmy; import contract.ISay; public class Program { public static void main(String[] args) { ISay say = new ISay() { public void say

Java的匿名类示例

本文将通过正则表达式来过滤文件夹中的某些特殊文件,并打印出来.这其中涉及到文件过滤器,其中应用到了匿名类. package date0815.demo1; /** * Java匿名内部类 * @author zzw * */ import java.io.File; import java.io.FilenameFilter; import java.util.Arrays; import java.util.regex.Pattern; public class Test1 { public

浅谈Java的匿名类

在实际的项目中看到一个很奇怪的现象,Java可以直接new一个接口,然后在new里面粗暴的加入实现代码.就像下面这样.那么问题来了,new出来的对象没有实际的类作为载体,这不是很奇怪吗? 思考以下代码的输出是什么? Runnable x = new Runnable() { @Override public void run() { System.out.println(this.getClass()); } }; x.run(); 实际答案是出现xxxx$1这样一个类名,它是编译器给定的名称.

Java学习-匿名类

1.筛选出符合条件的Hero:要求hp>100 && damage<50 匿名类实现: 先定义接口HeroChecker,其中的test()方法实现了Hero的筛选 1 package generic; 2 3 import charactor.Hero; 4 5 public interface HeroChecker { 6 public boolean test(Hero h); 7 } 1 package generic; 2 3 import java.util.Ar

JAVA学习--匿名类的使用

1 public class TestProduct { 2 public static void main(String[] args) { 3 TestProduct t = new TestProduct(); 4 //方式一:创建一个实现Product接口的类的对象,并将此对象传入方法中 5 NoteBook n = new NoteBook(); 6 t.show(n); 7 //方式二:创建一个实现Product接口的匿名类的对象 8 Product p = new Product(

java中匿名类的讲解

匿名内部类也就是没有名字的内部类 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写 但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口 实例1:不使用匿名内部类来实现抽象方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 abstract class Person {     public abstract void eat(); } class Child extends Person {     public void eat()

java内部匿名类

匿名内部类也就是没有名字的内部类 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写 但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口 实例1:不使用匿名内部类来实现抽象方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 abstract class Person {     public abstract void eat(); } class Child extends Person {     public void eat()