java实例化对象后面添加花括号的理解分析

article/2025/10/26 0:55:07

java实例化对象后面添加花括号的理解分析

昨天在看MyBatis官方文档时看到这么一段代码
  return new SQL() {{SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FIRST_NAME, P.LAST_NAME");FROM("PERSON P");if (id != null) {WHERE("P.ID like #{id}");}if (firstName != null) {WHERE("P.FIRST_NAME like #{firstName}");}if (lastName != null) {WHERE("P.LAST_NAME like #{lastName}");}ORDER_BY("P.LAST_NAME");}}.toString();
在类构造器后面加两对花括号{{}},这是我第一次见到这种写法,加一对{}我知道这是用来创建匿名子类,一般是用来实例化接口或实例化抽象类,但是里面还有一对{}是怎么个意思呢?通过自己判断以及问人和百度,得到答案是这是代码块,和普通类里定义代码块一样,但真的是这样吗?先附上主体代码,接着一步步分析解读

public class AppTest {int num; //声明AppTest成员属性//静态打印方法public static void staticPrint(String msg) {System.out.println(msg);}//成员打印方法public void memberPrint(String msg) {System.out.println(msg);}public static void main(String[] args) {AppTest test = new AppTest(); //创建AppTest实例对象test.num = 5;test.run(); //调用成员方法Person staticPerson = new Person("静态张三") {@Overridepublic void printName() {System.out.println("静态子类打印name:" + super.name);}{staticPrint("继承了Person的AppTest静态内部类构造器调用外部类的静态方法");System.out.println("继承了Person的AppTest静态内部类构造器调用父类的方法输出name:");printName();}};Class clzz = staticPerson.getClass();System.out.println("实例化对象person的全限定类名:" + clzz.getName());Class superClzz = clzz.getSuperclass();System.out.println("实例化对象person的全限定父类类名:" + superClzz.getName());}public void run() {Person memberPerson = new Person("张三") {@Overridepublic void printName() {System.out.println("成员子类打印name:" + super.name);}{System.out.println("上下文中AppTest成员对象的num属性值:"+AppTest.this.num);staticPrint("继承了Person的AppTest成员内部类构造器中调用外部类AppTest的静态方法");memberPrint("继承了Person的AppTest成员内部类构造器中调用外部类AppTest的成员方法");printName();}};Class clzz = memberPerson.getClass();System.out.println("实例化对象person的全限定类名:" + clzz.getName());Class superClzz = clzz.getSuperclass();System.out.println("实例化对象person的全限定父类类名:" + superClzz.getName());}
}class Person {protected String name;{System.out.println("Person实例初始化...");}public Person() {}public Person(String name) {this.name = name;}void printName() {System.out.println("name:"+name);}
}

打印结果

Person实例初始化...
上下文中AppTest成员对象的num属性值:5
继承了Person的AppTest成员内部类构造器中调用外部类AppTest的静态方法
继承了Person的AppTest成员内部类构造器中调用外部类AppTest的成员方法
成员子类打印name:张三
实例化对象person的全限定类名:com.farmlay.modules.blog.test.AppTest$2
实例化对象person的全限定父类类名:com.farmlay.modules.blog.test.Person
Person实例初始化...
继承了Person的AppTest静态内部类构造器调用外部类的静态方法
继承了Person的AppTest静态内部类构造器调用父类的方法输出name:
静态子类打印name:静态张三
实例化对象person的全限定类名:com.farmlay.modules.blog.test.AppTest$1
实例化对象person的全限定父类类名:com.farmlay.modules.blog.test.Person
一共创建了2个Person实例对象,分别是在静态main方法中和成员方法run中创建,通过打印对象的 Class.getName()我们发现2个对象的className分别是在这里插入图片描述在这里插入图片描述,className中有美元符号一般表示这是内部类(java命名不建议含有$),继续看他们的父类是Person

也就是说这两个Person对象其实是2个继承了Person类的AppTest内部类的实例化对象

通过编译可以看到确实是有2个AppTest内部类
在这里插入图片描述
然后我们再回过头来看打印信息

继承了Person的AppTest成员内部类构造器中调用外部类AppTest的静态方法
继承了Person的AppTest成员内部类构造器中调用外部类AppTest的成员方法继承了Person的AppTest静态内部类构造器调用外部类的静态方法

仔细看看2个对象打印出来的信息有什么不一样,成员方法中打印出来的是成员内部类,而静态方法中打印出来的是静态内部类,等等。。为什么明明是在{{}}代码块中调用的方法却打印“构造器中调用”?开始不是说和普通类定义代码块是一样的吗?我们可以通过jad反编译工具看看这到底是怎么回事

AppTest$1

static class AppTest$1 extends Person
{public void printName(){System.out.println((new StringBuilder()).append("\u9759\u6001\u5B50\u7C7B\u6253\u5370name\uFF1A").append(super.name).toString());}AppTest$1(String s){super(s);AppTest.staticPrint("\u7EE7\u627F\u4E86Person\u7684AppTest\u9759\u6001\u5185\u90E8\u7C7B\u6784\u9020\u5668\u8C03\u7528\u5916\u90E8\u7C7B\u7684\u9759\u6001\u65B9\u6CD5");System.out.println("\u7EE7\u627F\u4E86Person\u7684AppTest\u9759\u6001\u5185\u90E8\u7C7B\u6784\u9020\u5668\u8C03\u7528\u7236\u7C7B\u7684\u65B9\u6CD5\u8F93\u51FAname\uFF1A");printName();}
}

AppTest$2

class AppTest$2 extends Person
{public void printName(){System.out.println((new StringBuilder()).append("\u6210\u5458\u5B50\u7C7B\u6253\u5370name\uFF1A").append(super.name).toString());}final AppTest this$0;AppTest$2(String s){this$0 = AppTest.this;super(s);System.out.println((new StringBuilder()).append("\u4E0A\u4E0B\u6587\u4E2DAppTest\u6210\u5458\u5BF9\u8C61\u7684num\u5C5E\u6027\u503C\uFF1A").append(num).toString());AppTest.staticPrint("\u7EE7\u627F\u4E86Person\u7684AppTest\u6210\u5458\u5185\u90E8\u7C7B\u4EE3\u7801\u5757\u4E2D\u8C03\u7528\u5916\u90E8\u7C7BAppTest\u7684\u9759\u6001\u65B9\u6CD5");memberPrint("\u7EE7\u627F\u4E86Person\u7684AppTest\u6210\u5458\u5185\u90E8\u7C7B\u4EE3\u7801\u5757\u4E2D\u8C03\u7528\u5916\u90E8\u7C7BAppTest\u7684\u6210\u5458\u65B9\u6CD5");printName();}
}

AppTest

public class AppTest
{public AppTest(){}public static void staticPrint(String s){System.out.println(s);}public void memberPrint(String s){System.out.println(s);}public static void main(String args[]){AppTest apptest = new AppTest();apptest.num = 5;apptest.run();Person person = new Person("\u9759\u6001\u5F20\u4E09") {public void printName(){System.out.println((new StringBuilder()).append("\u9759\u6001\u5B50\u7C7B\u6253\u5370name\uFF1A").append(super.name).toString());}{AppTest.staticPrint("\u7EE7\u627F\u4E86Person\u7684AppTest\u9759\u6001\u5185\u90E8\u7C7B\u6784\u9020\u5668\u8C03\u7528\u5916\u90E8\u7C7B\u7684\u9759\u6001\u65B9\u6CD5");System.out.println("\u7EE7\u627F\u4E86Person\u7684AppTest\u9759\u6001\u5185\u90E8\u7C7B\u6784\u9020\u5668\u8C03\u7528\u7236\u7C7B\u7684\u65B9\u6CD5\u8F93\u51FAname\uFF1A");printName();}}
;Class class1 = person.getClass();System.out.println((new StringBuilder()).append("\u5B9E\u4F8B\u5316\u5BF9\u8C61person\u7684\u5168\u9650\u5B9A\u7C7B\u540D\uFF1A").append(class1.getName()).toString());Class class2 = class1.getSuperclass();System.out.println((new StringBuilder()).append("\u5B9E\u4F8B\u5316\u5BF9\u8C61person\u7684\u5168\u9650\u5B9A\u7236\u7C7B\u7C7B\u540D\uFF1A").append(class2.getName()).toString());}public void run(){Person person = new Person("\u5F20\u4E09") {public void printName(){System.out.println((new StringBuilder()).append("\u6210\u5458\u5B50\u7C7B\u6253\u5370name\uFF1A").append(super.name).toString());}final AppTest this$0;{this$0 = AppTest.this;super(s);System.out.println((new StringBuilder()).append("\u4E0A\u4E0B\u6587\u4E2DAppTest\u6210\u5458\u5BF9\u8C61\u7684num\u5C5E\u6027\u503C\uFF1A").append(num).toString());AppTest.staticPrint("\u7EE7\u627F\u4E86Person\u7684AppTest\u6210\u5458\u5185\u90E8\u7C7B\u4EE3\u7801\u5757\u4E2D\u8C03\u7528\u5916\u90E8\u7C7BAppTest\u7684\u9759\u6001\u65B9\u6CD5");memberPrint("\u7EE7\u627F\u4E86Person\u7684AppTest\u6210\u5458\u5185\u90E8\u7C7B\u4EE3\u7801\u5757\u4E2D\u8C03\u7528\u5916\u90E8\u7C7BAppTest\u7684\u6210\u5458\u65B9\u6CD5");printName();}}
;Class class1 = person.getClass();System.out.println((new StringBuilder()).append("\u5B9E\u4F8B\u5316\u5BF9\u8C61person\u7684\u5168\u9650\u5B9A\u7C7B\u540D\uFF1A").append(class1.getName()).toString());Class class2 = class1.getSuperclass();System.out.println((new StringBuilder()).append("\u5B9E\u4F8B\u5316\u5BF9\u8C61person\u7684\u5168\u9650\u5B9A\u7236\u7C7B\u7C7B\u540D\uFF1A").append(class2.getName()).toString());}int num;
}
可以看出来成员方法中通过new Person(“张三”){{}}会创建成员内部类,静态方法中通过new Person(“静态张三”){{}}会创建静态内部类,在{{}}定义的行为被定义在了构造器中,这是因为编译器会将构造代码块的内容添加到每个未调用其它构造器的方法体的最前面,但是构造器会先执行super构造器,成员类比静态类多个 final AppTest this$0 成员对象、构造方法中有 this$0 = AppTest.this;这样就可以持有外部类的引用,我们编码时需要这样写AppTest.this.num。

总结

new Object(){{}} 意思是在当前类下创建一个继承至Object的内部类;外层{}中可重写或实现或定义新方法(不能定义静态方法);内层{}最终是构造函数,由Object()指定重写具体哪个构造函数。

----1:静态方法中是创建一个静态内部类,在{{}}里可以调用外部类的静态方法、父类的方法
----2:成员方法中是创建一个成员内部类,在{{}}里可以调用外部类的方法、父类的方法,持有外部类的引用

http://chatgpt.dhexx.cn/article/V4lscLiR.shtml

相关文章

Unity 创建/实例化对象

在程序运行过程中创建、实例化对象物体需要用到Object类中的 Instantiate 函数,例如,我们场景中有一个物体A: 现在我们想要在场景中创建五个该物体,则用Instantiate函数将该物体作为参数传入: using UnityEngine;pu…

几种对象实例化方式详解

一)对象实例化常用方式 方式一:直接new一个对象,最常用的一种。 方式二:反射,通过Class.forName("类的全限定名")。 方式三:构造器,通过Class.forName("类的全限定名")&…

yolov5剪枝 实战

(1)步骤 剪枝的一般步骤只是在正常训练的后面加上了稀疏化训练和剪枝的步骤。 (2)稀疏化训练 主要区别 稀疏化训练的代码和正常训练的代码的差别主要体现在 ①反向传播 ②优化器 ③parse_opt代码 接下来从代码执行训练简单分析…

Spark 推测执行(speculative)

一 speculative简介 在spark作业运行中,一个spark作业会构成一个DAG调度图,一个DAG又切分成多个stage,一个stage由多个Task组成,一个stage里面的不同task的执行时间可能不一样,有的task很快就执行完成了,…

INT8 中的稀疏性:加速的训练工作流程和NVIDIA TensorRT 最佳实践

INT8 中的稀疏性:加速的训练工作流程和NVIDIA TensorRT 最佳实践 文章目录 INT8 中的稀疏性:加速的训练工作流程和NVIDIA TensorRT 最佳实践结构稀疏量化在 TensorRT 中部署稀疏量化模型的工作流程案例研究:ResNet-34要求第 1 步:…

非引导方法深度补全系列——1—— 《Sparsity invariant cnns》文章细读

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 创新点 论文概述 方法详解 网络结构: 杂七杂八 总结 参考 创新点 1.提出了一种稀疏卷积层,在卷积过程中使用二进制有效性掩码来指示缺失…

模型剪枝三:Learning Structured Sparsity in Deep Neural Networks

论文:https://arxiv.org/abs/1608.03665 代码:https://github.com/wenwei202/caffe/tree/scnn 1 核心思想 前面两篇文章https://blog.csdn.net/cdknight_happy/article/details/110953977和https://blog.csdn.net/cdknight_happy/article/details/1110…

Exploring Sparsity in Image Super-Resolution for Efficient Inference

目录 原文翻译 Abstract 1. Introduction 2. Related Work 4. Our SMSR Network 4.1. Sparse Mask Generation 4.2. Sparse Mask Convolution 5. Experiments 5.1. Implementation Details 5.2. Model Analysis 5.3. Comparison with State-of-the-art Methods Conclusion …

稀疏大模型简述:从MoE、Sparse Attention到GLaM

文 | 唐工源 | 知乎 Sparsity, ..., is another important algorithmic advance that can greatly improve efficiency. 稀疏性,是(神经架构搜索)之外另一个重要的算法进步,可以大大提高效率。 The use of sparsity in models is…

Sparse Learning

Sparse Learning 本文的内容主要来自余凯老师在CVPR2012上给的Tutorial。前面在总结ScSPM和LLC的时候,引用了很多Tutorial上的图片。其实这个Tutorial感觉写的挺好的,所以这次把它大致用自己的语言描述一下。不过稀疏编码是前两年比较火的东西&#xff0…

理解sparse coding

稀疏编码系列: (一)----Spatial Pyramid 小结(二)----图像的稀疏表示——ScSPM和LLC的总结(三)----理解sparse coding(四)----稀疏模型与结构性稀疏模型 -------------…

干货!SparCL,将Sparsity用在连续学习任务,相同表现下训练效率提升23倍!

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入! 作者简介 王梓枫 美国东北大学博士生,主要研究方向持续学习(Continual Learning)。 个人主页:https://kingspencer.github.io/ 报告题目 SparCL: 边缘设备上的稀疏…

MORE CONVNETS IN THE 2020S: SCALING UP KER- NELS BEYOND 51 × 51 USING SPARSITY

论文链接: https://arxiv.org/pdf/2207.03620.pdf code: https://github.com/VITA-Group/SLaKlink MORE CONVNETS IN THE 2020S: SCALING UP KER- NELS BEYOND 51 51 USING SPARSITY 一、引言(二)、大内核注意力(二)、卷积中的大…

Self-supervised Learning for Label Sparsity in Computational Drug Repositioning

论文地址:Self-supervised Learning for Label Sparsity in Computational Drug Repositioning 1. Introduction 药物重定位旨在根据已知的药物-疾病关联性揭示上市药物的新用途。其背后的逻辑是:目前市场上的小分子药物具有多靶点特性,这意…

xgboost:分割Sparsity-aware Split Finding

Sparsity-aware Split Finding1 在许多现实问题中,输入 x x x是稀疏的是很常见的。造成稀疏性的可能原因有很多: 1)数据中存在缺失值; 2)统计中频繁出现零项; 3)特征工程的处理结果,如独热编码。 重要的是使算法意识到数据中…

Sparsity constraint稀疏约束详解

Sparsity constraint稀疏约束详解 引子: 线性模型是我们经常使用的一种模型,比如: 文本分类中,bag-of-words 有p 20 K 个特征, 共有 N 5K 个文本样例; 在图像去模糊化,图像分类中,…

[机器学习速成课程] 稀疏性正则化 (Regularization for Sparsity)-学习笔记

稀疏性和 L1 正则化 学习目标: 计算模型大小通过应用 L1 正则化来增加稀疏性,以减小模型大小 降低复杂性的一种方法是使用正则化函数,它会使权重正好为零。对于线性模型(例如线性回归),权重为零就相当于完…

机器学习14:稀疏性-Sparsity

现实世界中,问题的特征的数量往往是很大的,而其中起决定性作用的往往是很小的一部分,稀疏规则化算子的引入会学习去掉这些没有信息的特征,也就是把这些特征对应的权重置为 0。 1.稀疏性正则化:L₁ 正则化 稀疏向量通常…

稀疏(sparsity)矩阵的行压缩存储

压缩矩阵行或列来存储矩阵的格式是很普遍的,它们不会存储不必要的元素(即空值)。但是它们也不是非常有效的,当在一个矩阵-向量积或预解决的每个简单标量中需要间接寻址。行压缩存储方式会把一个稀疏矩阵行的非零数值放在连续的存储…

redis删除锁

redis删除锁 参考:百度安全验证 前言 在分布式系统中,由于redis分布式锁相对于更简单和高效,成为了分布式锁的首先,被我们用到了很多实际业务场景当中。 但不是说用了redis分布式锁,就可以高枕无忧了,如…