首先在写完这篇博客时感谢几位作者的文章:

https://www.cnblogs.com/txbblog/p/10364558.html

https://blog.csdn.net/chengqiuming/article/details/91352913?depth_1-utm_source=distribute.pc_relevant.none-                   task-blog-                    BlogCommendFromBaidu-1&utm_source=distribute.pc_relevant.none-task-                      blog-                 BlogCommendFromBaidu-1

https://blog.csdn.net/qq_40990854/article/details/81067371

今天看《Thinking in Java》时候看到这里:

public class Parcel7 {public Contents contents() {return new Contents() { // Insert a class definitionprivate int i = 11;public int value() { return i; }}; // Semicolon required in this case}public static void main(String[] args) {Parcel7 p = new Parcel7();Contents c = p.contents();}
} ///:~

然后自己敲了发现有报错:

自然作者大大在后面有一定程度的解释:创建一个继承自Contents的匿名内部类的对象

但是怀着疑问我又去查了一下匿名类。

经过查阅资料我们总结一下匿名类和匿名对象,之后可能你看作者的代码可能会理解。

一、匿名对象

匿名对象:通俗的来说就是——没有名字的对象!(这是最重要的概念)

特征:
      1.语法上: 只创建对象,但是不用变量来接收

     2. 匿名对象的使用:
             (1).匿名对象也是一个对象,具有对象的所有功能
             (2).每一次使用匿名对象时,都是一个新的对象, 每次创建匿名对象都是不同的对象,一个匿名对象,只能使用一次,即匿名对象只能调用一次

Eg:

package test;public class TestAnonymousClass {public void print() {}public static void main(String[] args) {// TODO Auto-generated method stubnew TestAnonymousClass().print();}}

在这里的重点是:

new TestAnonymousClass();   //匿名对象的创建
new TestAnonymousClass().print(); //匿名对象调用方法

在这里我们没有像平常时候那样去new一个新对象,平时我们会如下做:

TestAnonymousClass() test = new TestAnonymousClass();
test.print();

我们可以看到如果我们想要创建一个匿名对象的话我们只需要去:new 类名(参数列表);

如果我们想要去调用自己创建的方法或者变量的话直接:new 类名(参数列表).方法名(参数列表);

3.那么我们想要知道匿名对象有什么好处那?

匿名对象的好处在以下场景应用会比较便利:

        (1)、创建匿名对象直接调用方法,没有变量名

new Scanner(System.in);

(2)、一旦调用两次方法,就是创建了两个对象,造成空间浪费

new Scanner(System.in).nextInt();
new Scanner(System.in).nextInt();

         PS一个匿名对象,只能使用一次。

                Eg:

package test;public class TestAnonymousClass {String name;public static void main(String[] args) {// TODO Auto-generated method stubnew TestAnonymousClass().name = "Tuo";System.out.println("The result is: "+new TestAnonymousClass().name);}}

在上面的代码中我们加载了匿名对象并给这个类的“name”变量一个值,但是如果你去打印它就会发现:

这是因为:

匿名对象在创建完之后,直接被系统释放掉了。也就是说,在类中的全局变量是随着类的加载而加载,这样,在使用new TestAnonymousClass().name时,由于是匿名的,类就终结了,因此上一个初始化name属性的“tuo”就消失了。

如果不想让初始化的属性值消失,那么您可以在创建类时,将想保留的属性定义为静态的!

就像这样:

package test;public class TestAnonymousClass {static String name;public static void main(String[] args) {// TODO Auto-generated method stubnew TestAnonymousClass().name = "Tuo";System.out.println("The result is: "+new TestAnonymousClass().name);}}

       (3)、匿名对象可以作为方法的参数和返回值

                   1)作为参数 

public class Test {public static void input(Scanner sc){System.out.println(sc);}public static void main(String[] args) {// 普通方式Scanner sc = new Scanner(System.in);input(sc);//匿名对象作为方法接收的参数input(new Scanner(System.in));} }    

                 2)作为返回值(这个大家应该比较熟悉,在《Thinking in Java》中也比较常见)

public class Test2 {public static void main(String[] args) {// 普通方式Scanner sc = getScanner();}public static Scanner getScanner(){//普通方式//Scanner sc = new Scanner(System.in);//return sc;//匿名对象作为方法返回值return new Scanner(System.in);}
}

二、匿名类(匿名内部类)

如果要执行的任务需要一个对象,但却不值得创建全新的对象(原因可能是所需的类过于简单,或者是由于它只在一个方法内部使用),匿名类就显得非常有用。

1、定义匿名内部类的语法格式如下:

new 父类构造器(实参列表) | 实现接口(){

//匿名内部类的类体部分

}

        (1)从上面的定义可以看出,匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类,或实现一个接                   口。(这个能够很好地解释我刚开始遇到的问题)

2)两条规则:

1)匿名内部类不能是抽象类。

                    2)匿名内部类不能定义构造器。由于匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以初始化块,                                可以通过初始化块来完成构造器需要完成的工作。
2、具体实现有以下三种方式:

(1)、最常用的创建匿名内部类的方式是创建某个接口类型的对象。

package test;
interface Purchase{public double getPrice();public String getName();
}
public class TestAnonymousClass {public void test(Purchase p){System.out.println("购买了" + p.getName()+ ",花费了" + p.getPrice());
}public static void main(String[] args) {// TODO Auto-generated method stubTestAnonymousClass test = new TestAnonymousClass();/**调用test()方法时,需要传入一个Product参数,此处传入其匿名内部类的实例*/test.test(new Purchase(){public double getPrice(){return 567.8;}public String getName(){return "显卡";}});}}

在这里我们需要注意的是注释的文字以及下面的代码即:

 new Purchase(){public double getPrice(){return 567.8;}public String getName(){return "显卡";}
}

Ps:

定义匿名内部类无须class关键字,而是在定义匿名内部类时直接生成该匿名内部类的对象。     

最后贴出我们打印的内容:

(2)、当通过接口来创建匿名内部类时,匿名内部类不能显示创建构造器,因此匿名内部类里只有一个隐式的无参构造器,             故new接口名后的括号里不能传入参数值。如果通过继承父类来创建匿名内部类时,匿名内部类将拥有和父类相似的               构造器,此处的相似指的是拥有相同的形参列表。

package test;
abstract class Device{private String name;public abstract double getPrice();public Device(){}public Device(String name){this.name = name;}// 此处省略了name的setter和getter方法public void setName(String name){this.name = name;}public String getName(){return this.name;}
}
public class TestAnonymousClass {public void test(Device d){System.out.println("购买了" + d.getName()+ ",花费了" + d.getPrice());}public static void main(String[] args){TestAnonymousClass test = new TestAnonymousClass();// 调用有参数的构造器创建Device匿名实现类的对象test.test(new Device("电子示波器"){public double getPrice(){return 67.8;}});// 调用无参数的构造器创建Device匿名实现类的对象Device d = new Device(){// 初始化块{System.out.println("匿名内部类的初始化块...");}// 实现抽象方法public double getPrice(){return 56.2;}// 重写父类的实例方法public String getName(){return "键盘";}};test.test(d);}}

这里主要注意的代码即:

  test.test(new Device("电子示波器"){public double getPrice(){return 67.8;}});// 调用无参数的构造器创建Device匿名实现类的对象Device d = new Device(){// 初始化块{System.out.println("匿名内部类的初始化块...");}// 实现抽象方法// 重写父类的实例方法public String getName(){return "键盘";}};

Ps:由于匿名内部类不能是抽象类,所以匿名内部类必须实现它的抽象父类或接口里包含的所有抽象方法。如果有需要,也可以         重写父类中的普通方法

     如果我们删除上面代码main方法中对   public abstract double getPrice()   的重写,就会报错:

我们贴出结果:

(3)、在Java 8之前,Java要求被局部内部类、匿名内部类访问的局部变量必须使用final修饰,从Java 8开始这个限制取消                   了,Java 8更加智能:如果局部变量被匿名内部类访问,那么该局部变量相对于自动使用了final修饰。

package test;
interface A{void test();
}public class TestAnonymousClass {public static void main(String[] args){int age = 8;     // ①/***  下面代码将会导致编译错误*  由于age局部变量被匿名内部类访问了,因此age相当于被final修饰了age = 2;* */A a = new A(){public void test(){/** * 在Java 8以前下面语句将提示错误:age必须使用final修饰* 从Java 8开始,匿名内部类、局部内部类允许访问非final的局部变量*/System.out.println(age);}};a.test();}    }

Ps:Java 8将这个功能称为“effectively final”,它的意思是对于被匿名内部类访问的局部变量,可以用final修饰,也可以不用           final修饰,但必须按照有final修饰的方式来使用——也就是一次赋值后,以后不能重新赋值。

结果

对java中匿名对象和匿名类的简单理解相关推荐

  1. Java中TimeZone(时区)类的简单使用

    package com.wk.timeimport java.util.TimeZone;public class LocaleTimeZone {public static void main(St ...

  2. java中常用API、Scanner类、匿名对象、Random类、ArrayList类、对象数组

    java中常用API: API:Application Programming Interface,应用程序编程接口.Java API是JDK中提供给我们使用的类的说明文档.这些类将底层的代码实现封装 ...

  3. java 为什么有匿名类_全面了解Java中的内部类和匿名类

    Java内部类(Inner Class),类似的概念在C++里也有,那就是嵌套类(Nested Class),乍看上去内部类似乎有些多余,它的用处对于初学者来说可能并不是那么显著,但是随着对它的深入了 ...

  4. Java中的内部类和匿名类

    内部类 Java中的类有两种重要的成员,即成员变量和方法.其实Java还允许类有一种成员,即在一个类中声明另一个类,这就是内部类,而包含内部类的类叫做外嵌类. 内部类和外嵌类之间的关系如下: 1.内部 ...

  5. JAVA中同目录下定义类,以及对象的创建与使用,内存图的原理

    JAVA中同目录下定义类,以及对象的创建与使用(听课笔记) JAVA中对象的创建与使用(听课笔记) 示例一 同文件目录下,创建了三个类OOTest01,User,Address类,之间的调用 示例二 ...

  6. Java中的对象和类

    一. OOP中的基本概念     Java的编程语言是面向对象的,采用这种语言进行编程称为面向对象编程(Object-Oriented Programming, OOP), 它允许设计者将面向对象设计 ...

  7. 【性能优化】面试官:Java中的对象和数组都是在堆上分配的吗?

    写在前面 从开始学习Java的时候,我们就接触了这样一种观点:Java中的对象是在堆上创建的,对象的引用是放在栈里的,那这个观点就真的是正确的吗?如果是正确的,那么,面试官为啥会问:"Jav ...

  8. java中String对象和String变量

    2019独角兽企业重金招聘Python工程师标准>>> java中String对象和String变量 (2011-12-27 20:40:27) 转载▼ 标签: it 最近在论坛上看 ...

  9. Java中的对象序列化操作

    文章目录 1 Java中的对象序列化操作 1 Java中的对象序列化操作 首先看一下对象序列化的操作步骤: 创建一个类,继承Serializable接口 创建对象 将对象写入文件 从文件读取对象信息 ...

  10. 【译】Java中的对象序列化

    前言 好久没翻译simple java了,睡前来一篇. 译文链接: http://www.programcreek.com/2014/01/java-serialization/ 什么是对象序列化 在 ...

最新文章

  1. LaTex中编辑公式的上下角标出现的问题---允许{}的嵌套吗?
  2. Visual Studio 2013编译Mozilla NPAPI 示例注意事项
  3. python界面长什么样子-这可能是最好玩的python GUI入门实例(推荐)
  4. reg型变量怎么赋值_UiPath变量的介绍和使用
  5. 鸟哥的Linux私房菜(基础篇)- 第二十四章、 X Window 配置介绍
  6. openresty获取nginx请求url中的所有参数
  7. Redis的分布式锁详解
  8. 手机端适应_不轻易透露的超强技巧!详解iVX中怎样做设备自适应
  9. 注册中心—常见注册中心组件对比分析
  10. HDU 2049 不容易系列之(4)——考新郎( 错排 )
  11. 要高薪地进入IT,你得这样做
  12. boost/container/small_vector.hpp: No such file or directory on Ubuntu 14.04
  13. scala Set入门到熟悉
  14. Java入门到进阶推荐书籍
  15. 【OpenCV教程】第一章 Mac上的安装和初步使用
  16. MagicDraw-需求图
  17. struts2拦截器实现登录拦截
  18. 数据可视化:推荐6个数据可视化工具软件平台
  19. Vue Tags Input
  20. 债券收益率预测模型_证券盈利预测模型

热门文章

  1. python开发视频播放器_Python使用PyQT制作视频播放器
  2. 计算机主机两个部分组成,计算机的主机由哪两个部分组成
  3. Telephony理解
  4. Creo Simulat 4.0有限元分析视频教程 料材 结构 网格 装配 散热分析
  5. 压缩感知中的数学知识:投影矩阵(projection matrix)
  6. 《Oracle内核技术解密》读书笔记(三)
  7. 使用CAT进行MRI脑图像分析
  8. 众安Java开发面试
  9. Google Chrome离线安装Native HLS Playback插件播放HLS
  10. 简单两步找回忘记的WiFi密码