最近回顾了下内部类的用法,有两个问题备忘下。
1 内部类标准用法
java中内部类用处很广,但是感觉标准用法如下:
内部类child使用private修饰符,实现一个公开的接口interface,然后通过父类parent的public方法初始化newInstance,在外部通过接口interface访问,而内部类child又可以访问父类parent的内部资源
其中最经典的例子当属于util中的Iterator方式了。父类AbstractList中有private内部类Itr,实现了java.util.Iterator接口,然后内部类中可以访问AbstractList的各种变量和方法
private class Itr implements Iterator<E>{
public E next() {
checkForComodification();
try {
E next = get(cursor);
lastRet = cursor++;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
在外部通过接口访问
List list=new ArrayList();
Iterator it=list.iterator();//通过接口访问
it.next();
这样做能够实现外部接口,访问内部变量,且不暴露访问细节
因为内部类是private的,只能在父类内部访问,在外部不能访问,因此就和根本不存在一样
List list=new ArrayList();
List.Itr it=list.new Itr();//不能通过这种标准方式访问
2 匿名内部类和final
另外关于匿名内部类只能访问final类型的局部变量的原因,确定的是匿名内部类一般可能是线程之类的,生命周期远比一般的方法调用要长。
有一种说法是内部类里面将该变量copy一份,如果该变量还可以随意赋值的话,可能导致内部类中的那份copy和外部的相比不一样了,因此需要final修饰符,但是感觉这样不对,写了个例子测试了下,如下:
private static void test() throws Exception{
final List<String> list = new ArrayList<String>();
list.add("aa");
list.add("bb");
new Thread() {
public void run() {
int i = 0;
while (true) {
i++;
if (i == 10)
break;
System.out.println(list);
try { Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
list.add("cc");
Thread.sleep(2000);
list.add("dd");
}
代码的目的是匿名类里面不停访问list,匿名类外部修改list,结果如下:
[aa, bb, cc]
[aa, bb, cc]
[aa, bb, cc, dd]
[aa, bb, cc, dd]
[aa, bb, cc, dd]
[aa, bb, cc, dd]
[aa, bb, cc, dd]
[aa, bb, cc, dd]
[aa, bb, cc, dd]
从结果可以看到匿名类内部和外部访问的是同一个对象,而不是通过copy的方式。
因此怀疑final类型的局部变量的生命周期比一般的局部变量周期要长,在方法调用完毕之后还存在。
分享到:
相关推荐
定义一个复数类 complex ,它的内部具有两个实例变量:realPart和imagPart,分别代表复数的实部和虚 部,编程实现要求的数学运算。 (1)实现两个复数相加。复数加运算的原则是:复数的实部和虚部分别相加。 (2...
最全面的java内部类总结,概念和实例帮助深入理解!
文章目录Java内部类:你真得了解方法内部类吗?...普通内部类主要有两个要点需要掌握 持有父类引用,故可以访问父类任何访问权限的变量、方法 内部类在父类外部的创建方式 public class Main{ public sta
这个代码实现了一个简单的购物车系统。...最后定义了一个内部类Item,用来表示商品,包括商品名称和价格两个属性。在main方法中创建了一个ShoppingCart对象,并演示了如何添加商品、移除商品以及获取总价的操作。
outputMax.java 求两个数中的最大数 overflowExample.java 演示溢出 precedence.java 演示自加运算符的优先级 primeNumber.java 输出100-200之间的所有素数 ranking.java 评定成绩等级 rankingBySwitch.java ...
java实现输入任意两个日期输出月份数和天数,综合考虑闰年、2月等因素,对于整月计算利息或按天数计算利息提供基础工具类。也可以吧内部类独立出来,方便跨包调用,可自行调整。很实用的一个实现。其他百度查到的很...
java.rmi.registry 提供 RMI 注册表的一个类和两个接口。 java.rmi.server 提供支持服务器端 RMI 的类和接口。 java.security 为安全框架提供类和接口。 java.security.acl 此包中的类和接口已经被 java.security...
内部java实现多个数据库,保持数据同步案例。
基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...
6.3 小结:Java其实是个类和对象的世界 152 6.4 习题 153 第7章 Java中的方法——给汽车丰富多彩的功能 154 教学视频:2小时55分钟 7.1 方法:让汽车动开动 154 7.1.1 引出问题:开动汽车 154 7.1.2 那么,...
6.3 小结:Java其实是个类和对象的世界 152 6.4 习题 153 第7章 Java中的方法——给汽车丰富多彩的功能 154 教学视频:2小时55分钟 7.1 方法:让汽车动开动 154 7.1.1 引出问题:开动汽车 154 7.1.2 那么,...
作为刚入门Java的小白,这两天看到内部类,这里做一个总结,若有错误,欢迎指正~ 内部类是指在一个外部类的内部再定义一个类。类名不需要和文件夹相同。 内部类分为: 成员内部类、局部内部类、静态嵌套类、...
java.rmi.registry 提供 RMI 注册表的一个类和两个接口。 java.rmi.server 提供支持服务器端 RMI 的类和接口。 java.security 为安全框架提供类和接口。 java.security.acl 此包中的类和接口已经被 java.security ...
它包含以下两个主要部分: 1. PageInfo 内部类:这是一个泛型类,封装了分页所需的信息,包括当前页码、页面大小、总页数、总记录数和当前页的记录列表。 2. pagedList 静态方法:这是一个泛型方法,接收总记录数...
java.awt.dnd Drag 和 Drop 是一种直接操作动作,在许多图形用户界面系统中都会遇到它,它提供了一种机制,能够在两个与 GUI 中显示元素逻辑相关的实体之间传输信息。 java.awt.event 提供处理由 AWT 组件所激发的...
基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...
1、一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 7 2、Java有没有goto? 7 3、说说&和&&的区别。 8 4、在JAVA中如何跳出当前的多重嵌套循环? 8 5、switch语句能否作用在byte上,能否作用在...
基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...
《Java范例开发大全》共22章,内容涉及Java开发环境的搭建、Java基础类型与运算符、条件控制语句、异常处理、数组、字符串、输入输出流、面向对象及其四大特征、内部类与接口、Java常用类、集合、多线程编程、Java...