Java中的匿名内部类及内部类的二三事
匿名内部类适合创建那些只需要使用一次的类,它的语法有些奇怪,创建匿名内部类会立即创建一个该类的实例,这个类定义立即消失,且不能重复使用。
定义匿名类的格式如下:
new 实现接口() |父类构造器(实参列表){
//匿名内部类的类体部分
}
从定义来看,匿名内部类必须继承一个父类,或者实现一个接口,但是最多只能继承一个父类或者实现一个接口。
关于匿名内部类,还有如下两条规则:
- 匿名内部类不能是抽象类,因为系统在创建匿名内部类时,会立即创建匿名内部类的对象。因此不允许将匿名内部类定义成抽象类。
- 匿名内部类不能定义构造器。因为匿名内部类没有类名,所以无法定义构造器。但是匿名内部类可以定义初始化块,通过实例初始化块来完成构造器需要完成的事情。
下面给出了一个常见的匿名内部类的使用示例:
public class Main {
public static void main(String[] args){
Main main = new Main();
main.test(new Man(){
//这里传入一个Man接口的匿名实现类的实例
public void talk(){
System.out.print("I'm a man!");
//output I'm a man!
}
});
}
public void test(Man m){
//调用该方法需要传入一个Man类型参数
m.talk();
}
}
interface Man{
void talk();
}
定义一个匿名内部类无需使用class关键字,而是在定义匿名内部类时直接生成该匿名内部类的对象。
由于匿名内部类不能是抽象类,所以匿名内部类必须实现它的抽象父类或者接口里包含的抽象方法。
虽然上面的例子完全可以采用使用实现类对象的方法来完成相同的功能,但是明显使用匿名内部类更加简洁。
当通过实现接口来创建匿名内部类时,匿名内部类不能显式创建构造器,因此匿名内部类只有一个隐式的无参数构造器,故new接口名后的括号中不能传入参数。
但是如果通过继承父类来创建匿名内部类时,匿名内部类将拥有和父类相似的构造器,注意此处相似的构造器指的是拥有相同形参列表。
下面是通过继承父类来创建匿名内部类的示例:
public class Main {
public static void main(String[] args){
Main main = new Main();
main.test(new Man("Amos H"){
//这里传入一个Man接口的匿名实现类的实例
public void talk(){
System.out.println(this.getName());
//output Amos H
}
public int getHight(){
return 175;
}
});
}
public void test(Man m){
//调用该方法需要传入一个Man类型参数
m.talk();
}
}
abstract class Man{
private String name;
public Man(String name){
this.name = name;
}
public void talk(){
System.out.println(name);
};
public String getName(){
return name;
}
public abstract int getHight();
}
可以看到,创造匿名内部类可以使用和父类相同的参数列表,调用父类的构造器。
当创建匿名内部类时,必须实现接口或者抽象父类中的所有抽象方法。如果有必要的话,可以重写父类中的普通方法。
内部类的二三事:
非静态内部类对象和外部类对象的关系如何?
非静态内部类对象必须寄生在外部类对象中,而外部类对象则不一定有非静态内部类对象寄生其中。因此外部类对象不能访问非静态内部类对象,而非静态内部类对象可以访问外部类成员,因为存在内部类必然存在外部类。
非静态内部类对象是否可以有静态初始化块?
非静态内部类对象不可以有静态初始化块,但是可以有普通初始化块。非静态内部类普通初始化块的作用与外部类初始化块的作用完全相同。
为何静态内部类的实例方法也不能访问外部类的实例属性?
因为静态内部类是外部类的类相关的,而不是外部类的对象相关的。静态内部类对象不是寄生在外部类的实例中,而是寄生在外部类的类本身中。当静态内部类对象存在时,并不一定存在一个被它寄生的外部类对象,静态内部类对象只持有外部类的类引用,并没有持有外部类对象的引用。如果允许静态内部类的实例方法访问外部类的实例成员,但找不到被寄生的外部类对象,这将引起错误。
如何实例化一个非静态内部类
非静态内部类的子类不一定是内部类,它也可以是一个外部类。但是非静态内部类的子类实例一样要保留一个引用,该引用用于指向其父类所在外部类的对象。也就是说,如果一个内部类子类的对象存在,则一定存在与之对应的外部类对象。因为要实例化一个非静态内部类的语法通常是这样的:
Out.In in = new Out().new In();
可以看到,非静态内部类的构造器必须使用外部类对象来调用。
Java中的匿名内部类及内部类的二三事的更多相关文章
- java中的几种内部类
Java中的几种内部类 内部类,听名字就可以知道是什么意思,就是类里面的类.有成员内部类,静态内部类,局部内部类和匿名内部类. 下面说一个每种内部类的的使用. 一. 成员内部类
- java中的匿名内部类总结(转)
源出处: java中的匿名内部类总结 匿名内部类也就是没有名字的内部类 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写 但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接 ...
- java中的匿名内部类
匿名内部类在java编码中不是很常见,它可一让类实现多继承的特性(多个父类~1个子类) java中的匿名内部类总结http://www.cnblogs.com/nerxious/archive/201 ...
- Java中使用google.zxing快捷生成二维码(附工具类源码)
移动互联网时代,基于手机端的各种活动扫码和收付款码层出不穷:那我们如何在Java中生成自己想要的二维码呢?下面就来讲讲在Java开发中使用 google.zxing 生成二维码. 一般情况下,Java ...
- java中的四种内部类使用(1)
内部类 (一) 概述 把类定义在另一个类的内部,该类就被称为内部类. 举例:把类Inner定义在类Outer中,类Inner就被称为内部类. class Outer { class Inner { } ...
- Java中的集合框架-Collection(二)
上一篇<Java中的集合框架-Collection(一)>把Java集合框架中的Collection与List及其常用实现类的功能大致记录了一下,本篇接着记录Collection的另一个子 ...
- java中注解的使用与实例 (二)
java 注解,从名字上看是注释,解释.但功能却不仅仅是注释那么简单.注解(Annotation) 为我们在代码中添加信息提供了一种形式化的方法,是我们可以在稍后 某个时刻方便地使用这些数据(通过 解 ...
- java中常用的工具类(二)
下面继续分享java中常用的一些工具类,希望给大家带来帮助! 1.FtpUtil Java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...
- 走进Java中的持有对象(容器类)【二】Collection
概述 通过前文的学习,我们对容器的分类及常用容器类的作用有了基本的认识.本文将针对Collection容器的功能与使用进行细致分析. 基本操作 Collection集合抽象出的目的是为存放独立元素的序 ...
随机推荐
- 00SQL表字段说明
SELECT d.name 表名 , a.colorder 字段序号 , a.name 字段名 , ISNULL(g.[value], '') AS 字段说明 , ( CASE WHEN COLUMN ...
- 背水一战 Windows 10 (122) - 其它: 通过 Windows.System.Profile 命名空间下的类获取信息, 查找指定类或接口的所在程序集的所有子类和子接口
[源码下载] 背水一战 Windows 10 (122) - 其它: 通过 Windows.System.Profile 命名空间下的类获取信息, 查找指定类或接口的所在程序集的所有子类和子接口 作者 ...
- 公司项目接触到了FormData,总结一下
Javascript FormData() 对象! 1.创建 var formData = new FormData(); 2.如果有form对象 则先获取form表单 然后初始化时直接加入进去 eg ...
- Akka-Cluster(4)- DistributedData, 分布式数据类型
在实际应用中,集群环境里共用一些数据是不可避免的.我的意思是有些数据可以在任何节点进行共享同步读写,困难的是如何解决更改冲突问题.本来可以通过分布式数据库来实现这样的功能,但使用和维护成本又过高,不值 ...
- Javascript高级编程学习笔记(70)—— 事件(14)内存和性能
由于事件处理程序是现代的web程序交互能力的提供者 所以在日常实践中,我们免不了要向页面中添加大量的事件处理程序(不管是用于用户交互还是用于统计用户数据) 在创建GUI(图形用户界面)的语言(如C#) ...
- Ubuntu18.04版本设置root账户
Linux系统下文件的权限十分重要,大多数操作都需要一定的权限才可以操作,Ubuntu18.04默认安装是没有设置root账户的,因此想要获得root账户登录可以使用以下步骤: 1.首先获得临时的 ...
- Git使用详细教程(3):git add, git commit详解
在使用git之前,我们首先要初始化一个git管理的仓库,这里以博客(blog)为例 git init blog 我们进入目录,执行git status查看git状态,可以看到一个新的git管理的项目目 ...
- java mongodb连接配置实践——生产环境最优
之前百度,google了很多,发现并没有介绍mongodb生产环境如何配置的文章, 当时想参考下都不行, 所以写篇文章,大家可以一块讨论下. 1. MongoClientOptions中的连接池配置: ...
- 解决关于:TypeError: Class constructor Model cannot be invoked without 'new'
问题描述:在工作过程中出现 TypeError: Class constructor Model cannot be invoked without 'new' 这个错误 以下是报错代码: class ...
- Android--使用剪切板在Activity中传值
在Activity之间传递数据还可以利用一些技巧,不管windows还是Linux操作系统,都会支持一种叫剪切板的技术,也就是某一个程序将一些数据复制到剪切板上,然后其他的任何程序都可以从剪切板中获取 ...