博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从一开始,说出事java匿名内部类
阅读量:7126 次
发布时间:2019-06-28

本文共 2557 字,大约阅读时间需要 8 分钟。

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对象中保存了这个变量,那么下次运行到,同一个对象。所以变量肯定是同样的,这样也就解开我们的疑惑了。

总结一下:

在我们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。博客,未经同意不得转载。

你可能感兴趣的文章
HTTP/2
查看>>
[单刷APUE系列]第十七章——高级进程间通信
查看>>
分布式之消息队列的特点、选型、及应用场景详解
查看>>
多迪学员问到最多的问题:为什么要学习Python编程语言?
查看>>
从vue中学习defineProperty
查看>>
漂亮的颜色
查看>>
Android Volley 源码解析(二),探究缓存机制
查看>>
Go源码剖析:内置类型
查看>>
102. Binary Tree Level Order Traversal
查看>>
SAP云平台对Kubernetes的支持
查看>>
原来实现GCP用客户端登录这么简单啊
查看>>
PAT A1057 分块思想
查看>>
PAT A1007 动态规划
查看>>
VUE父子组件传递数据
查看>>
前端知识点——图片
查看>>
别人家的程序员是如何使用 Java 进行 Web 抓取的?
查看>>
95%的技术面试必考的JVM知识点都在这,另附加分思路!
查看>>
日期类问题
查看>>
区块链入门之基础知识
查看>>
mysql锁(Innodb)
查看>>