JAVA匿名内部类(Anonymous(Classes)的具体使用)

本文主要介绍了JAVA匿名内部类,匿名内部类在我们JAVA程序员的日常工作中经常要用到,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

JAVA匿名内部类(Anonymous,Classes)的具体使用,久久派带你了解更多相关信息。

目录
  • 1.前言
  • 2.匿名内部类
    • 2.1 定义匿名内部类
    • 2.2 匿名内部类的语法
  • 3.访问作用域内的局部变量、定义和访问匿名内部类成员
    • 4.匿名内部类实例
      • 写在最后:

        1.前言

        匿名内部类在我们JAVA程序员的日常工作中经常要用到,但是很多时候也只是照本宣科地用,虽然也在用,但往往忽略了以下几点:为什么能这么用?匿名内部类的语法是怎样的?有哪些限制?因此,最近,我在完成了手头的开发任务后,查阅了一下JAVA官方文档,将匿名内部类的使用进行了一下总结,案例也摘自官方文档。感兴趣的可以查阅官方文档(https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html)。

        2.匿名内部类

        匿名内部类可以使你的代码更加简洁,你可以在定义一个类的同时对其进行实例化。它与局部类很相似,不同的是它没有类名,如果某个局部类你只需要用一次,那么你就可以使用匿名内部类(Anonymous classes enable you to make your code more concise. They enable you to declare and instantiate a class at the same time. They are like local classes except that they do not have a name. Use them if you need to use a local class only once.)

        本节包括以下几个方面:

        • 定义匿名内部类
        • 匿名内部类的语法
        • 访问作用域的局部变量、定义和访问匿名内部类成员
        • 匿名内部类实例

        2.1 定义匿名内部类

        首先看下官方文档中给的例子:

        public class HelloWorldAnonymousClasses {    /**     * 包含两个方法的HelloWorld接口     */    interface HelloWorld {        public void greet();        public void greetSomeone(String someone);    }    public void sayHello() {        // 1、局部类EnglishGreeting实现了HelloWorld接口        class EnglishGreeting implements HelloWorld {            String name = \"world\";            public void greet() {                greetSomeone(\"world\");            }            public void greetSomeone(String someone) {                name = someone;                System.out.println(\"Hello \" + name);            }        }        HelloWorld englishGreeting = new EnglishGreeting();        // 2、匿名类实现HelloWorld接口        HelloWorld frenchGreeting = new HelloWorld() {            String name = \"tout le monde\";            public void greet() {                greetSomeone(\"tout le monde\");            }            public void greetSomeone(String someone) {                name = someone;                System.out.println(\"Salut \" + name);            }        };        // 3、匿名类实现HelloWorld接口        HelloWorld spanishGreeting = new HelloWorld() {            String name = \"mundo\";            public void greet() {                greetSomeone(\"mundo\");            }            public void greetSomeone(String someone) {                name = someone;                System.out.println(\"Hola, \" + name);            }        };        englishGreeting.greet();        frenchGreeting.greetSomeone(\"Fred\");        spanishGreeting.greet();    }    public static void main(String... args) {        HelloWorldAnonymousClasses myApp = new HelloWorldAnonymousClasses();        myApp.sayHello();    }}

        运行结果为:

        1 Hello world
        2 Salut Fred
        3 Hola, mundo

        该例中用局部类来初始化变量englishGreeting,用匿类来初始化变量frenchGreeting和spanishGreeting,两种实现之间有明显的区别:

        1)局部类EnglishGreetin继承HelloWorld接口,有自己的类名,定义完成之后需要再用new关键字实例化才可以使用;

        2)frenchGreeting、spanishGreeting在定义的时候就实例化了,定义完了就可以直接使用;

        3)匿名类是一个表达式,因此在定义的最后用分号\”;\”结束。

        2.2 匿名内部类的语法

        如上文所述,匿名类是一个表达式,匿名类的语法就类似于调用一个类的构建函数(new HelloWorld()),除些之外,还包含了一个代码块,在代码块中完成类的定义,见以下两个实例:

        案例一,实现接口的匿名类:

        HelloWorld frenchGreeting = new HelloWorld() {   String name = \"tout le monde\";   public void greet() {         greetSomeone(\"tout le monde\");   }   public void greetSomeone(String someone) {        name = someone;        System.out.println(\"Salut \" + name);   } };

        案例二,匿名子类(继承父类):

        public class AnimalTest {    private final String ANIMAL = \"动物\";    public void accessTest() {        System.out.println(\"匿名内部类访问其外部类方法\");    }    class Animal {        private String name;        public Animal(String name) {            this.name = name;        }        public void printAnimalName() {            System.out.println(bird.name);        }    }    // 鸟类,匿名子类,继承自Animal类,可以覆写父类方法    Animal bird = new Animal(\"布谷鸟\") {        @Override        public void printAnimalName() {            accessTest();           // 访问外部类成员            System.out.println(ANIMAL);  // 访问外部类final修饰的变量            super.printAnimalName();        }    };    public void print() {        bird.printAnimalName();    }    public static void main(String[] args) {        AnimalTest animalTest = new AnimalTest();        animalTest.print();    }}

        运行结果:

        运行结果:
        匿名内部类访问其外部类方法
        动物
        布谷鸟

        从以上两个实例中可知,匿名类表达式包含以下内部分:

        • 操作符:new;
        • 一个要实现的接口或要继承的类,案例一中的匿名类实现了HellowWorld接口,案例二中的匿名内部类继承了Animal父类;
        • 一对括号,如果是匿名子类,与实例化普通类的语法类似,如果有构造参数,要带上构造参数;如果是实现一个接口,只需要一对空括号即可;
        • 一段被\”{}\”括起来类声明主体;
        • 末尾的\”;\”号(因为匿名类的声明是一个表达式,是语句的一部分,因此要以分号结尾)。

        3.访问作用域内的局部变量、定义和访问匿名内部类成员

        匿名内部类与局部类对作用域内的变量拥有相同的的访问权限。

        (1)、匿名内部类可以访问外部内的所有成员;

        (2)、匿名内部类不能访问外部类未加final修饰的变量(注意:JDK1.8即使没有用final修饰也可以访问);

        (3)、属性屏蔽,与内嵌类相同,匿名内部类定义的类型(如变量)会屏蔽其作用域范围内的其他同名类型(变量):

        案例一,内嵌类的属性屏蔽:

        public class ShadowTest {    public int x = 0;    class FirstLevel {        public int x = 1;        void methodInFirstLevel(int x) {            System.out.println(\"x = \" + x);            System.out.println(\"this.x = \" + this.x);            System.out.println(\"ShadowTest.this.x = \" + ShadowTest.this.x);        }    }    public static void main(String... args) {        ShadowTest st = new ShadowTest();        ShadowTest.FirstLevel fl = st.new FirstLevel();        fl.methodInFirstLevel(23);    }}

        输出结果为:

        x = 23
        this.x = 1
        ShadowTest.this.x = 0

        这个实例中有三个变量x:1、ShadowTest类的成员变量;2、内部类FirstLevel的成员变量;3、内部类方法methodInFirstLevel的参数。

        methodInFirstLevel的参数x屏蔽了内部类FirstLevel的成员变量,因此,在该方法内部使用x时实际上是使用的是参数x,可以使用this关键字来指定引用是成员变量x:

        System.out.println(\"this.x = \" + this.x); 

        利用类名来引用其成员变量拥有最高的优先级,不会被其他同名变量屏蔽,如:

        System.out.println(\"ShadowTest.this.x = \" + ShadowTest.this.x); 

        案例二,匿名内部类的属性屏蔽:

         public class ShadowTest {    public int x = 0;    interface FirstLevel {     void methodInFirstLevel(int x);    }    FirstLevel firstLevel =  new FirstLevel() {        public int x = 1;        @Override        public void methodInFirstLevel(int x) {            System.out.println(\"x = \" + x);            System.out.println(\"this.x = \" + this.x);            System.out.println(\"ShadowTest.this.x = \" + ShadowTest.this.x);        }    };    public static void main(String... args) {        ShadowTest st = new ShadowTest();        ShadowTest.FirstLevel fl = st.firstLevel;        fl.methodInFirstLevel(23);    }}

        输出结果为:

        x = 23
        this.x = 1
        ShadowTest.this.x = 0

        (4)、匿名内部类中不能定义静态属性、方法;  

        public class ShadowTest {    public int x = 0;    interface FirstLevel {     void methodInFirstLevel(int x);    }    FirstLevel firstLevel =  new FirstLevel() {        public int x = 1;        public static String str = \"Hello World\";   // 编译报错        public static void aa() {        // 编译报错        }        public static final String finalStr = \"Hello World\";  // 正常        public void extraMethod() {  // 正常            // do something        }    };}

        (5)、匿名内部类可以有常量属性(final修饰的属性);

        (6)、匿名内部内中可以定义属性,如上面代码中的代码:private int x = 1;

        (7)、匿名内部内中可以可以有额外的方法(父接口、类中没有的方法);

        (8)、匿名内部内中可以定义内部类;

        (9)、匿名内部内中可以对其他类进行实例化。

        4.匿名内部类实例

        官方提供的两个实例供大家参考:

        实例一:

        import javafx.event.ActionEvent;import javafx.event.EventHandler;import javafx.scene.Scene;import javafx.scene.control.Button;import javafx.scene.layout.StackPane;import javafx.stage.Stage;public class HelloWorld extends Application {    public static void main(String[] args) {        launch(args);    }    @Override    public void start(Stage primaryStage) {        primaryStage.setTitle(\"Hello World!\");        Button btn = new Button();        btn.setText(\"Say \'Hello World\'\");        btn.setOnAction(new EventHandler<ActionEvent>() {            @Override            public void handle(ActionEvent event) {                System.out.println(\"Hello World!\");            }        });        StackPane root = new StackPane();        root.getChildren().add(btn);        primaryStage.setScene(new Scene(root, 300, 250));        primaryStage.show();    }}

        实例二:

        import javafx.application.Application;import javafx.event.ActionEvent;import javafx.event.EventHandler;import javafx.geometry.Insets;import javafx.scene.Group;import javafx.scene.Scene;import javafx.scene.control.*;import javafx.scene.layout.GridPane;import javafx.scene.layout.HBox;import javafx.stage.Stage;public class CustomTextFieldSample extends Application {    final static Label label = new Label();    @Override    public void start(Stage stage) {        Group root = new Group();        Scene scene = new Scene(root, 300, 150);        stage.setScene(scene);        stage.setTitle(\"Text Field Sample\");        GridPane grid = new GridPane();        grid.setPadding(new Insets(10, 10, 10, 10));        grid.setVgap(5);        grid.setHgap(5);        scene.setRoot(grid);        final Label dollar = new Label(\"$\");        GridPane.setConstraints(dollar, 0, 0);        grid.getChildren().add(dollar);        final TextField sum = new TextField() {            @Override            public void replaceText(int start, int end, String text) {                if (!text.matches(\"[a-z, A-Z]\")) {                    super.replaceText(start, end, text);                }                label.setText(\"Enter a numeric value\");            }            @Override            public void replaceSelection(String text) {                if (!text.matches(\"[a-z, A-Z]\")) {                    super.replaceSelection(text);                }            }        };        sum.setPromptText(\"Enter the total\");        sum.setPrefColumnCount(10);        GridPane.setConstraints(sum, 1, 0);        grid.getChildren().add(sum);        Button submit = new Button(\"Submit\");        GridPane.setConstraints(submit, 2, 0);        grid.getChildren().add(submit);        submit.setOnAction(new EventHandler<ActionEvent>() {            @Override            public void handle(ActionEvent e) {                label.setText(null);            }        });        GridPane.setConstraints(label, 0, 1);        GridPane.setColumnSpan(label, 3);        grid.getChildren().add(label);        scene.setRoot(grid);        stage.show();    }    public static void main(String[] args) {        launch(args);    }}

        写在最后:

        这篇文章是我在阅读官方文档的同时加以自己的理解整理出来的,可能受英文原版的影响,有些地方表达得不准确或是不清楚还希望读者能够指正。另外,体会到了那些翻译英文技术书的人确实不容易,英文的文章看上去意思都很清楚,但是想要再用中文表述出来却不那么容易。

        到此这篇关于JAVA匿名内部类(Anonymous Classes)的具体使用的文章就介绍到这了,更多相关JAVA 匿名内部类内容请搜索趣讯吧以前的文章或继续浏览下面的相关文章希望大家以后多多支持趣讯吧!

        版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请发送邮件至 55@qq.com 举报,一经查实,本站将立刻删除。转转请注明出处:https://www.szhjjp.com/n/10906.html

        (0)
        nan
        上一篇 2021-08-08
        下一篇 2021-08-08

        相关推荐

        • 创建facebook账号(怎么创建facebook账号)

          创建facebook账号(怎么创建facebook账号)。久久派带你了解更多相关信息。做外贸,跨境电商的卖家难免要用到Facebook,ins,领英等国外社交平台,尤其是到了年底最后旺季冲刺,库存清货,Facebook的使用需求就更高了,不过最近好几个卖家说,

          2022-01-18
          0
        • 美阿拉斯加州海域发生8.1级地震?8.1级地震是什么概念

          地震的破坏力是非常大的,每次大型地震都不可避免的造成人员伤亡和经济损失。据了解美国当地时间28日美阿拉斯加州海域发生8.1级地震,那么8.1级地震是什么概念呢?一起来看看吧!

          2021-07-29
          0
        • 中国向俄罗斯遣返在逃毒犯!曾被国际刑警组织签发红色通报

          原标题:中国向俄罗斯遣返在逃毒犯!曾被国际刑警组织签发红色通报应俄罗斯内政部门请求,11日中国警方在上海浦东机场将俄罗斯籍涉毒逃犯多罗申科遣送出境,移交俄方。遣返前,中俄双方有关部门代表在上海举行移交仪式,签署移交犯罪嫌疑人备忘录。据了解,

          2021-09-12
          0
        • 锦州老兵系列报道?锦州红海滩也挺美摄影爱好者(,姜福林)

          2021年8月29日讯,锦州红海滩也挺美最先推出红海滩这个旅游景观的地方当属辽宁的盘锦。应该说有海的地方就有红海滩,因为海滩上生长着一种特殊的草本植物~碱蓬草。碱蓬草一年生植物,辽宁4-5月份出牙,10月份成熟,最高可达一米。初为绿色,

          2021-08-29
          0
        • 小米12ultra什么时候上市(小米12ultra最新消息)

          小米12ultra的外观大致确定下来了,环形的镜头布局,不过这个设计,真的是非常拉跨,不如没有设计,下面就一起来了解一i西安小米12ultra什么时候上市。小米12U这款手机将于2022年的三月份和广大消费者见面;性能方面,小米12U这款手机将采用的

          2022-01-16
          0
        • 班主任工作随笔(班主任工作随笔及感悟)

          这届学生又带了二年多了,虽说我与许多家长从未谋面,就是家访时见到的也更多是爷爷奶奶们,但我想我与家长的心却是相通的。望子成龙、望女成凤或许是每个为人父、为人母的心愿,我想普天下的父母心愿也许都是如此。作为老师的我们何尝不是一样的心情呢?特别是作

          2022-01-14
          0

        发表回复

        登录后才能评论