java final成员变量吗_阳光沙滩博客-为什么Java匿名内部内使用局部变量需要加final?而访问成员变量却不用加final呢?...

前置知识

内存数据区域(Java内存结构)

在解析这个问题之前,得先有一些前置知识。

比如说,要知道什么是堆,什么是栈,什么是方法区,这数据区域存放什么内容?

可以参考这篇文章:

栈里面存放方法内容

比如说以下代码:

public class App {

public static void main(String[] args) {

sayHello();

}

private static void sayHello() {

System.out.println("hello world");

sayBye();

}

private static void sayBye() {

System.out.println("good bye...");

doSum();

}

private static void doSum() {

int a = 10;

int b = 29;

int sum = a + b;

System.out.println("sum is -- > " + sum);

}

}

打个断点

946e095e02be1ec5a975f1d13edd26ff.png

第一个方法都压进栈里

这里每一个Item叫做栈帧,也就是frame

执行的时候就Pop出去,顶部的先出栈,执行完毕。

所以如果是递归的话,一直压栈,容易导致栈内存溢出。

final关键字

这个我相信大家都知道,因为面试常问

final 修饰的变量值不能被修改,一般定义常量用此修饰

final 修饰的类不能被继承,比如说String

final 修饰的方法不可以被覆写

提个问题

final User user = new User("zhangsan",18);

用final修饰了一个成员,这个成员是User,里面有名称和年龄的属性。我可经修改它的年龄吗?

可以,只是你的user不能再指向其他对象。这个对象里的值还是可以修改的。所以,final修饰的对象,对象的属性是可以修改的。

案例

给我们的RecyclerView的Item设置点击事件。

@Override

public void onBindViewHolder(@NonNull InnerHolder holder,int position) {

TextView itemTv = holder.itemView.findViewById(R.id.left_category_tv);

if(mCurrentSelectedPosition == position) {

itemTv.setBackgroundColor(itemTv.getResources().getColor(R.color.colorEEEEEE,null));

} else {

itemTv.setBackgroundColor(itemTv.getResources().getColor(R.color.white,null));

}

final SelectedPageCategory.DataBean dataBean = mData.get(position);

itemTv.setText(dataBean.getFavorites_title());

holder.itemView.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

if(mItemClickListener != null && mCurrentSelectedPosition != position) {

//修改当前选中的位置

mCurrentSelectedPosition = position;

mItemClickListener.onLeftItemClick(dataBean);

notifyDataSetChanged();

}

}

});

}

我们给item设置了点击事件,而里面的匿名内部类使用到了方法里的局部变量

final SelectedPageCategory.DataBean dataBean = mData.get(position);

为什么要加final呢?

因为我们的方法调用时在栈里,出栈执行,就会释放掉了。

所以就没有dataBean 这个数据了。而创建的对象 ,在堆里,地址引用给了ItemView的onClickListener成员。

所以两者的声明周期不一样。dataBean 的声明周期在此方法执行完就释放了。

而匿名对象还在。为什么要加final呢?

前面我们说了,加了final修饰的变量则为常量,不可以改变其值。

而匿名内部类里用到的那个dataBean,是复制了一份到里面的方法里。这个打断点就知道了,可以看到当方法执行的时候,会在栈内存里有此变量。

有了final修饰,就是确保一致性。

为什么成员变量则不需要加final呢?

我们匿名内部类使用成员变量时,不需要加final,为什么呢?

我们的成员变量保存在哪里呢?我们创建对象的时候,会在堆内存里开新空间。堆内存什么时候回收,GC回收对吧。GC回收有一定的规则,对象没有被引用了才会去回收。

比如说标记-清除算法,标记-压缩算法,复制算法,分代收集算法。

所以确保了数据的一致性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值