- 浏览: 890848 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (687)
- java (127)
- servlet (38)
- struts (16)
- spring (22)
- hibernate (40)
- javascript (58)
- jquery (18)
- tomcat (51)
- 设计模式 (6)
- EJB (13)
- jsp (3)
- oracle (29)
- RUP (2)
- ajax (3)
- java内存管理 (4)
- java线程 (12)
- socket (13)
- path (5)
- XML (10)
- swing (2)
- UML (1)
- JBPM (2)
- 开发笔记 (45)
- Note参考 (15)
- JAXB (4)
- Quartz (2)
- 乱码 (2)
- CSS (2)
- Exception (4)
- Tools (7)
- sqlserver (3)
- DWR (7)
- Struts2 (47)
- WebService (2)
- 问题解决收藏 (7)
- JBOSS (7)
- cache (10)
- easyUI (19)
- jQuery Plugin (11)
- FreeMarker (6)
- Eclipse (2)
- Compass (2)
- JPA (1)
- WebLogic (1)
- powerdesigner (1)
- mybatis (1)
最新评论
-
bugyun:
受教了,谢谢
java 正则表达式 过滤html标签 -
xiongxingxing_123:
学习了,感谢了
java 正则表达式 过滤html标签 -
wanmeinange:
那如果无状态的。对同一个任务并发控制怎么做?比如继承Quart ...
quartz中参数misfireThreshold的详解 -
fanjieshanghai:
...
XPath 元素及属性查找 -
tianhandigeng:
还是没明白
quartz中参数misfireThreshold的详解
2009-5-21
Thinking In Java里面的说法(唯一正确的说法): 如果定义一个匿名内部类,并且希望它使用一个在其外部定的对象,那么编译器会要求其参数引用是final 的。
Java代码
public class Tester {
public static void main(String[] args) {
A a = new A();
C c = new C();
c.shoutc(a.shout(5));
}
}
////////////////////////////////////////////////////////
class A {
public void shouta() {
System.out.println("Hello A");
}
public A shout(final int arg) {
class B extends A {
public void shouta() {
System.out.println("Hello B" + arg);
}
}
return new B();
}
}
////////////////////////////////////////////////////////
class C {
void shoutc(A a) {
a.shouta();
}
}
public class Tester {
public static void main(String[] args) {
A a = new A();
C c = new C();
c.shoutc(a.shout(5));
}
}
////////////////////////////////////////////////////////
class A {
public void shouta() {
System.out.println("Hello A");
}
public A shout(final int arg) {
class B extends A {
public void shouta() {
System.out.println("Hello B" + arg);
}
}
return new B();
}
}
////////////////////////////////////////////////////////
class C {
void shoutc(A a) {
a.shouta();
}
}
第5行c.shoutc(a.shout(5)),在a.shout(5)得到返回值后,a的shout()方法栈被清空了,即arg不存在了,而c.shoutc()却又调用了a.shouta()去执行System.out.println("Hello B" + arg)。
再来看Java虚拟机是怎么实现这个诡异的访问的:有人认为这种访问之所以能完成,是因为arg是final的,由于变量的生命周期,事实是这样的吗?方法栈都不存在了,变量即使存在,怎么可能还被访问到?试想下:一个方法能访问另一个方法的定义的final局部变量吗(不通过返回值)?
研究一下这个诡异的访问执行的原理,用反射探测一下局部内部类 。编译器会探测局部内部类中是否有直接使用外部定义变量的情况,如果有访问就会定义一个同类型的变量,然后在构造方法中用外部变量给自己定义的变量赋值,而后局部内部类所使用的变量都是自己定义的变量,所以就可以访问了。见下:
class A$1$B
{
A$1$B(A, int);
private final int var$arg;
private final A this$0;
}
A$1$B类型的对象会使用自定义的var$arg变量,而不是shout()方法中的final int arg变量,当然就可以访问了。
那么为什么外部变量要是final的呢?即使外部变量不是final,编译器也可以如此处理:自己定义一个同类型的变量,然后在构造方法中赋值就行了。原因就是为了让我们能够挺合逻辑的直接使用外部变量,而且看起来是在始终使用 外部的arg变量(而不是赋值以后的自己的字段)。
考虑出现这种情况:在局部内部类中使用外部变量arg,如果编译器允许arg不是final的,那么就可以对这个变量作变值操作(例如arg++),根据前面的分析,变值操作改变的是var$arg,而外部的变量arg并没有变,仍然是5(var$arg才是6)。因此为了避免这样如此不合逻辑的事情发生:你用了外部变量,又改变了变量的值,但那个变量却没有变化,自然的arg就被强行规定必须是final所修饰的,以确保让两个值永远一样,或所指向的对象永远一样(后者可能更重要)。
还有一点需要注意的是内部类与方法不是同时执行的,比如实现ActionListener,只有当事件发生的时候才会执行,而这时方法已经结束了。
转自http://qiuqiao.iteye.com/blog/393761
Thinking In Java里面的说法(唯一正确的说法): 如果定义一个匿名内部类,并且希望它使用一个在其外部定的对象,那么编译器会要求其参数引用是final 的。
Java代码
public class Tester {
public static void main(String[] args) {
A a = new A();
C c = new C();
c.shoutc(a.shout(5));
}
}
////////////////////////////////////////////////////////
class A {
public void shouta() {
System.out.println("Hello A");
}
public A shout(final int arg) {
class B extends A {
public void shouta() {
System.out.println("Hello B" + arg);
}
}
return new B();
}
}
////////////////////////////////////////////////////////
class C {
void shoutc(A a) {
a.shouta();
}
}
public class Tester {
public static void main(String[] args) {
A a = new A();
C c = new C();
c.shoutc(a.shout(5));
}
}
////////////////////////////////////////////////////////
class A {
public void shouta() {
System.out.println("Hello A");
}
public A shout(final int arg) {
class B extends A {
public void shouta() {
System.out.println("Hello B" + arg);
}
}
return new B();
}
}
////////////////////////////////////////////////////////
class C {
void shoutc(A a) {
a.shouta();
}
}
第5行c.shoutc(a.shout(5)),在a.shout(5)得到返回值后,a的shout()方法栈被清空了,即arg不存在了,而c.shoutc()却又调用了a.shouta()去执行System.out.println("Hello B" + arg)。
再来看Java虚拟机是怎么实现这个诡异的访问的:有人认为这种访问之所以能完成,是因为arg是final的,由于变量的生命周期,事实是这样的吗?方法栈都不存在了,变量即使存在,怎么可能还被访问到?试想下:一个方法能访问另一个方法的定义的final局部变量吗(不通过返回值)?
研究一下这个诡异的访问执行的原理,用反射探测一下局部内部类 。编译器会探测局部内部类中是否有直接使用外部定义变量的情况,如果有访问就会定义一个同类型的变量,然后在构造方法中用外部变量给自己定义的变量赋值,而后局部内部类所使用的变量都是自己定义的变量,所以就可以访问了。见下:
class A$1$B
{
A$1$B(A, int);
private final int var$arg;
private final A this$0;
}
A$1$B类型的对象会使用自定义的var$arg变量,而不是shout()方法中的final int arg变量,当然就可以访问了。
那么为什么外部变量要是final的呢?即使外部变量不是final,编译器也可以如此处理:自己定义一个同类型的变量,然后在构造方法中赋值就行了。原因就是为了让我们能够挺合逻辑的直接使用外部变量,而且看起来是在始终使用 外部的arg变量(而不是赋值以后的自己的字段)。
考虑出现这种情况:在局部内部类中使用外部变量arg,如果编译器允许arg不是final的,那么就可以对这个变量作变值操作(例如arg++),根据前面的分析,变值操作改变的是var$arg,而外部的变量arg并没有变,仍然是5(var$arg才是6)。因此为了避免这样如此不合逻辑的事情发生:你用了外部变量,又改变了变量的值,但那个变量却没有变化,自然的arg就被强行规定必须是final所修饰的,以确保让两个值永远一样,或所指向的对象永远一样(后者可能更重要)。
还有一点需要注意的是内部类与方法不是同时执行的,比如实现ActionListener,只有当事件发生的时候才会执行,而这时方法已经结束了。
转自http://qiuqiao.iteye.com/blog/393761
发表评论
-
操作系统的目标和作用
2012-07-05 23:46 1326操作系统的目标 目前存在着多种类型的OS,不同类型的OS ... -
利用(ffmpeg)生成视频缩略图(java)
2012-07-01 01:11 0对于上传视频生成缩略图使用的是ffmpeg进行生成的。 自己在 ... -
对Java多线程技术中所有方法的详细解析
2012-06-06 11:32 784一、run()和start() 这两个 ... -
java乱码
2012-06-06 11:33 968自从接触Java和JSP以来, ... -
学习apache commons-io类库中的文件清除器
2011-07-06 23:26 1440学习apache commons-io 1.4类库中的File ... -
java 正则表达式 过滤html标签
2011-05-24 15:10 5352前段时间开发的时候要读取一篇文章的简介内容(也就是前200个字 ... -
转---Eclipse中web-inf和meta-inf文件夹的信息
2011-05-24 13:08 1131Eclipse中web-inf和meta-inf ... -
logback与Log4J的区别
2011-05-17 23:34 1432Logback和log4j是非常相似 ... -
性能优化
2011-04-14 16:10 1174(1)jdbc性能优化 jdbc程序的性能主要由两个因素决定 ... -
JAVA的Random类(转)
2011-04-12 00:21 908Random类中实现的随机算法是伪随机,也就是有规则的随机。在 ... -
非阻塞的Socket链接
2011-04-10 21:59 890import java.io.IOException; ... -
创建临时文件
2011-04-10 21:55 1091package net.java2000.io; ... -
面向对象设计的基本原则
2011-04-07 10:28 1143摘自:http://soft6.com/tech/6/6501 ... -
proxool
2011-04-02 15:01 856属性列表说明: fatal-sql- ... -
当前Java软件开发中几种认识误区
2011-04-01 10:12 876越来越多人开始使用Java ... -
Java中查看一个方法被调用的层次(Reflection、StackTrace)
2011-04-01 00:53 2032package test; public class Mai ... -
反序列化时恢复transient字段
2011-03-30 13:20 1212我们知道将字段设置为transient,可以避免该自动被序列化 ... -
用socket连接服务器直接发送接收邮件
2011-03-22 17:22 1301首页 新闻 论坛 问答 博客 招聘 更多 ▼ 专栏 &l ... -
利用JavaMail收/发Gmail邮件(SSL)
2011-03-22 17:21 2388Gmail目前已经启用了POP3和SMTP服务,具体情况请看 ... -
Java 反射与内省
2011-03-14 22:08 1073一、java反射机制 JAVA反 ...
相关推荐
- 当局部内部类需要访问所在方法的局部变量时,JVM会自动为这些局部变量创建副本,并存储在局部内部类的隐式成员变量中。 - 这一行为仅适用于final修饰的局部变量。 #### 示例分析 考虑以下代码示例: ```java ...
方法内部类对象不能使用该内部类所在方法的非final局部变量。 四、匿名内部类 匿名内部类是指不具有名称的内部类。匿名内部类适合使用场景包括:只用到类的一个实例、类在定义后马上用到、类非常小、给类命名并...
- 局部内部类可以直接访问外部类的成员,并且可以访问该方法中的局部变量,但这些局部变量必须是最终的(`final`)或者本质上不可变的。 **5. 匿名内部类:** - 匿名内部类是没有名称的内部类,通常用于实现接口或...
局部内部类不能有访问修饰符,也不能访问外部类的静态成员,但可以访问方法参数的final变量以及所在代码块内的变量。局部内部类的主要用途是提供有限的封装,通常用于实现回调或匿名回调函数。 3. 静态内部类: ...
局部内部类可以访问其所在方法或块的局部变量,但这些变量必须声明为final。 7. **嵌套类**: 嵌套类是所有内部类的总称,包括静态和非静态内部类。嵌套类的概念比内部类更宽泛,内部类是嵌套类的一个子集。 8. *...
被声明为 private 的成员只能被所在类访问,不能被其他类访问。 #### 2. 其他类修饰词 - **abstract**:表示抽象类。一个类如果被声明为 abstract,则它不能被实例化,主要用于提供一个基类供其他类继承。抽象类...
局部内部类可以访问它所在的作用域内的所有变量,包括final修饰的局部变量。 3. **匿名内部类**:匿名内部类没有名字,通常用于简化代码和快速创建一次性使用的类。它们常用于实现接口或继承类,并且可以作为参数、...
如果要访问方法的局部变量或参数,这些变量必须声明为final。 3. 静态内部类: 静态内部类不需要外部类的实例就可以创建对象,但不能直接访问外部类的非静态成员。它主要用于创建与外部类弱耦合的辅助类。 4. ...
- **局部内部类**:在方法或作用域内定义,只能访问该作用域内的变量(需final修饰)和外部类的静态成员。 3. **匿名内部类与接口** - **实现接口**:匿名内部类可以直接实现一个接口,并提供接口中所有方法的...
- 局部内部类可以访问其所在方法或代码块内的局部变量,但这些变量必须是final或实际上不可变的。 ##### 4. 匿名内部类 匿名内部类是一种没有名字的内部类,常用于简化代码编写,特别是创建接口的实例时。 - **...
- 局部内部类只能访问所在方法的final参数和变量,这是因为局部内部类的生命周期超出了它所在方法的生命周期,为了保持访问的稳定性,编译器会为final变量在局部内部类中创建副本。 - 当方法执行完毕,局部变量的...
•局部内部类不能在外部类以外的地方使用,那么局部内部类也不能使用访问控制符和static修饰 匿名内部类 •匿名内部类适合创建那种只需要一次使用的类,定义匿名内部类的语法格式如下: •new 父类构造器...
5. **局部内部类的访问权限**:局部内部类可以访问其所在方法或块的final变量以及类的成员变量,但不能直接访问非final的局部变量。这是因为局部变量在其所在的作用域内,而局部内部类的生命周期超出了这个范围,...
匿名内部类可以访问外部类的所有成员变量和方法,包括私有的成员。 #### 6. 数组 (Array) 数组是一种数据结构,用于存储相同类型的一系列元素。数组中的每个元素都有一个索引,索引从0开始。在Java中,数组可以通过...
学习和理解Java中的方法是编程的基础,通过熟练掌握方法的声明、调用、参数传递和返回,能有效提升编程效率和代码质量。此外,掌握方法的高级特性,如重载、递归等,对于编写复杂程序至关重要。 在"Java基础精品课...
- 如果内部类定义在方法中,它可以访问方法中的final局部变量以及该方法所在类的所有实例变量。 - 静态内部类则不能直接访问外部类的非静态成员,因为它不持有对外部类实例的引用。 5. **数据类型转换**: - ...
5. **局部内部类与变量访问**:局部内部类可以访问其所在方法内的 `final` 变量和所有成员变量,但不能直接访问非 `final` 局部变量。这是因为局部内部类的生命周期超出了局部变量的作用域,为了保持一致性,Java ...
5. **局部内部类访问变量**:局部内部类可以访问其所在作用域内的final变量以及所有的成员变量(包括静态和非静态),但不能直接访问非final的局部变量。 6. **case语句中的值类型**:在switch语句的case子句中,...
在给定的例子中,局部内部类`Animal`可以访问`work`(作为`final`变量)和`name`(成员变量),但不能访问非`final`的`age`变量。 6. **常量类与`instanceof`**: - `Math`和`String`都是`final`类,不能被继承。`...