java内部类、匿名类原本以为它们的使用已经很滑, 成绩, 就在昨天晚上12指向时钟发生重大事故。事故的严重程度再说吧,那是因为我没有睡一晚睡眠。

那以下先用一段模拟代码来描写叙述下我出现的问题的:

public class Test {
public static void main(String[] args) throws InterruptedException {
View v = new View();
v.show(1);
Thread.sleep(500);
v.mTextView.execute();
Thread.sleep(1000);
v.show(2);
Thread.sleep(500);
v.mTextView.execute();
}
} class View {
public TextView mTextView; public void show(int position) {
if(mTextView == null) {
mTextView = new TextView();
mTextView.setListener(new Listener() {
@Override
public void click() {
System.out.println("position = " + position);
}
});
} mTextView.show();
}
} class TextView {
private Listener mListener; public void setListener(Listener l) {
mListener = l;
} public void execute() {
mListener.click();
} public void show() {
System.out.println("textview show...");
}
} interface Listener {
public void click();
}

不出意外的话。 console肯定是打印的1  2。 可是偏偏就在这困扰到我了。打印的结果是1  1, 细致顺一下代码,我们就应该去思考这个匿名内部类究竟是怎么使用的外部类那个方法的參数的。

从打印的结果上看, 我猜想肯定是在这个内部类的实例中保存了position參数。那带着这个猜想。我们来debug一下程序。

这是第一次运行到的时候, 发现什么问题了吗。

在mListener中居然有一个和position相关的变量。到这里,我们感觉那个推測可能是正确的。再往下思考,既然在mListener对象中保存了这个变量,那么下次运行到,同一个对象。所以变量肯定是同样的,这样也就解开我们的疑惑了。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWliaW4wNTA2/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

总结一下:

在我们new一个匿名内部类的时候,假设使用了方法中的东西,那么jvm会给我们的匿名类加一个构造方法,而且将这个參数传递进来,比如上面的样例中:

class View$Listener {
public View$Listener(int position) {
this.Listener$position = position;
} public void click() {
...
}
}

既然知道了这些。那么我们的疑惑也就解开了, 那上面的问题怎么解决呢? 事实上我们非常早之前就已经知道解决方法了,想想android中自己定义Adapter的getView()方法。你会恍然大悟。上面的问题怎么解决呢?就是把setListener放到if后面,而不是里面。

public class Test {
public static void main(String[] args) throws InterruptedException {
View v = new View();
v.show(1);
Thread.sleep(500);
v.mTextView.execute();
Thread.sleep(1000);
v.show(2);
Thread.sleep(500);
v.mTextView.execute();
}
} class View {
public TextView mTextView; public void show(int position) {
if(mTextView == null) {
mTextView = new TextView();
// mTextView.setListener(new Listener() {
// @Override
// public void click() {
// System.out.println("position = " + position);
// }
// });
} mTextView.setListener(new Listener() {
@Override
public void click() {
System.out.println("position = " + position);
}
}); mTextView.show();
}
} class TextView {
private Listener mListener; public void setListener(Listener l) {
mListener = l;
} public void execute() {
mListener.click();
} public void show() {
System.out.println("textview show...");
}
} interface Listener {
public void click();
}

这样在每次调用show方法时,都会又一次new一个Listener内部类。

版权声明:本文来源于Loader's Blog。博客,未经同意不得转载。

从一开始,说出事java匿名内部类的更多相关文章

  1. #随笔之java匿名内部类

    随笔之java匿名内部类 从今天起开始每日一篇技术博客,当然这只是我当天所学的一些随笔,里面或多或少会有理解不当的地方,希望大家多多指教,一起进步! 在讲匿名内部类之前,先讲讲内部类的一些概念. 1. ...

  2. (转)java匿名内部类详解

    原文:http://android.blog.51cto.com/268543/384844/   内部类是指在一个外部类的内部再定义一个类.类名不需要和文件夹相同. *内部类可以是静态static的 ...

  3. 【Java学习笔记之二十六】深入理解Java匿名内部类

    在[Java学习笔记之二十五]初步认知Java内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意 ...

  4. 【50】java 匿名内部类剖析

    匿名内部类介绍: 匿名内部类也就是没有名字的内部类 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写 但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口 匿名内部类的声明 ...

  5. JAVA匿名内部类(Anonymous Classes)

    1.前言 匿名内部类在我们JAVA程序员的日常工作中经常要用到,但是很多时候也只是照本宣科地用,虽然也在用,但往往忽略了以下几点:为什么能这么用?匿名内部类的语法是怎样的?有哪些限制?因此,最近,我在 ...

  6. Java匿名内部类访问外部

    匿名内部类访问外部局部变量必须是final修饰的,Java 1.8 会默认为其加上final 例子如下: public void send(String topicName, T obj) { Str ...

  7. 为什么Java匿名内部类访问的外部局部变量或参数需要被final修饰

    大部分时候,类被定义成一个独立的程序单元.在某些情况下,也会把一个类放在另一个类的内部定义,这个定义在其他类内部的类就被称为内部类,包含内部类的类也被称为外部类. class Outer { priv ...

  8. Java 匿名内部类 & 内部类

    一.JAVA中内部类和匿名内部类的区别 内部类:内部类可以是static的或者非static的,static内部类只能包含静态方法和静态类变量,只能访问外部类的静态元素,内部类可以实例化,多次使用. ...

  9. java匿名内部类使用场景列举

    示例一: package com;      interface Operation {       double operateTwoIntNum(int a, int b);   }      p ...

随机推荐

  1. PHP中如何实现 “在页面中一边执行一边输出” 的效果

    <?php    set_time_limit(0);  //在有关数据库的大量数据的时候,可以将其设置为0,表示无限制.    ob_end_clean();     //在循环输出前,要关闭 ...

  2. STL__queue_的应用

    转:http://hi.baidu.com/xiaotiandm/item/bda34511cf9e99098fbde41a 调用的时候要有头文件: #include<stdlib.h> ...

  3. poj2826(线段相交)

    传送门:An Easy Problem?! 题意:用两条线段接雨水,雨水是垂直落下的,问我们用给定的两条线段能接到多少水. 分析:看起来很简单,写起来略麻烦,先排除不能接到水的情况: 1. 两条线段不 ...

  4. UNIX 网络编程之线程

    概述: 实现并发服务器一般都是父进程accept一个连接,然后fork一个子进程,该子进程处理与该连接对端的客户之间的通信.但是fork是昂贵,耗资源和时间.而线程是轻量级线程,它的创建比进程的创建块 ...

  5. Linux段管理,BSS段,data段,.rodata段,text段

    近期在解决一个编译问题时,一直在考虑一个问题,那就是Linux下可执行程序执行时内存是什么状态,是依照什么方式分配内存并执行的.查看了一下资料.就此总结一下,众所周知.linux下内存管理是通过虚存管 ...

  6. POJ 1753 位运算+枚举

    题意: 给出4*4的棋盘,只有黑棋和白棋,问你最少几步可以使棋子的颜色一样. 游戏规则是:如果翻动一个棋子,则该棋子上下左右的棋子也会翻一面,棋子正反面颜色相反. 思路: 都是暴搜枚举. 第一种方法: ...

  7. 数学之路-python计算实战(19)-机器视觉-卷积滤波

    filter2D Convolves an image with the kernel. C++: void filter2D(InputArray src, OutputArray dst, int ...

  8. 聊聊高并发(三十八)解析java.util.concurrent各个组件(十四) 理解Executor接口的设计

    JUC包中除了一系列的同步类之外,就是Executor运行框架相关的类.对于一个运行框架来说,能够分为两部分 1. 任务的提交 2. 任务的运行. 这是一个生产者消费者模式,提交任务的操作是生产者,运 ...

  9. WebService之Soap头验证入门

    1.新建一个类,如"AuthHeaderUser",继承于"System.Web.Services.Protocols.SoapHeader"类 2.新建Web ...

  10. linux下执行strlwr函数出错:ld returned 1 exit status

    执行strlwr函数时报错.源程序例如以下: #include<stdio.h> #include<string.h> void main() { char s[10]={&q ...