谈谈java中的WeakReference

本文详细解析了Java中的弱引用概念,通过实例分析了弱引用如何避免内存泄漏,并介绍了其在不同场景下的合理使用。主要内容包括对象可达性判断、强引用与内存泄漏的关系、弱引用的优势及避免内存泄漏的方法。

java语言中为对象的引用分为了四个级别,分别为 强引用 、软引用、弱引用、虚引用。

本文只针对java中的弱引用进行一些分析,如有出入还请多指正。

在分析弱引用之前,先阐述一个概念:什么是对象可到达和对象不可到达状态。

其实很简单,我举个例子:

现在有如下两个类class A class B,在JVM上生成他们两个类的实例分别为 instance a  instance b

有如下表达式:

A a = new A();

B b = new B();

两个强引用对象就生成了,好吧,那么这个时候我做一下修改:

A a = new A();

B b = new B(a);

B的默认构造函数上是需要一个A的实例作为参数的,那么这个时候 A和B就产生了依赖,也可以说a和b产生了依赖,我们再用一个接近内存结构的图来表达:

 

a是对象A的引用,b是对象B的引用,对象B同时还依赖对象A,那么这个时候我们认为从对象B是可以到达对象A的。

于是我又修改了一下代码

A a = new A();

B b = new B(a);

a = null;

A对象的引用a置空了,a不再指向对象A的地址,我们都知道当一个对象不再被其他对象引用的时候,是会被GC回收的,很显然及时a=null,那么A对象也是不可能被回收的,因为B依然依赖与A,在这个时候,造成了内存泄漏!

那么如何避免上面的例子中内存泄漏呢?

很简单:

A a = new A();

B b = new B(a);

a = null;

b = null;

这个时候B对象再也没有被任何引用,A对象只被B对象引用,尽管这样,GC也是可以同时回收他们俩的,因为他们处于不可到达区域。

 

弱引用来了!

A a = new A();

WeakReference wr = new WeakReference(a);

//B b = new B(a);

 

当 a=null ,这个时候A只被弱引用依赖,那么GC会立刻回收A这个对象,这就是弱引用的好处!他可以在你对对象结构和拓扑不是很清晰的情况下,帮助你合理的释放对象,造成不必要的内存泄漏!!

在准备Android开发面试时,面试题通常涵盖基础知识、进阶内容、项目经验、性能优化、源码理解等多个维度。以下是一些常见的Android开发面试题及答案解析,帮助系统性地梳理知识体系。 ### 一、Android基础相关面试题 1. **Activity生命周期是怎样的?** - Activity的生命周期主要包括`onCreate()`、`onStart()`、`onResume()`、`onPause()`、`onStop()`、`onDestroy()`等方法。这些方法在用户与应用交互过程中被调用,开发者可以通过重写这些方法来控制界面状态和资源释放。 - 在面试中,通常会问到`onStart()`与`onResume()`的区别,以及`onPause()`和`onStop()`的调用时机[^1]。 2. **Android四大组件是什么?** - 四大组件分别是: - `Activity`:负责用户界面展示和交互。 - `Service`:用于执行长时间运行的操作,不与用户交互。 - `BroadcastReceiver`:用于接收系统或应用广播。 - `ContentProvider`:用于不同应用间的数据共享。 3. **Intent的作用是什么?** - `Intent`用于在不同组件之间传递消息,启动`Activity`、`Service`或发送广播。可以分为显式Intent和隐式Intent两种形式。 ### 二、Android进阶相关面试题 1. **谈谈Handler机制的原理?** - `Handler`机制是Android中实现线程间通信的核心机制。它由`Handler`、`Looper`、`MessageQueue`和`Message`四个部分组成。 - `Looper`负责从`MessageQueue`中取出消息,`Handler`负责发送和处理消息。主线程默认拥有一个`Looper`,而子线程需要手动调用`Looper.prepare()`和`Looper.loop()`来开启消息循环。 2. **什么是ANR?如何避免ANR?** - ANR(Application Not Responding)是指应用在主线程中执行耗时操作导致界面无响应的情况。 - 避免ANR的方法包括: - 将耗时操作(如网络请求、数据库查询)放在子线程中执行。 - 使用`AsyncTask`、`HandlerThread`或`ExecutorService`等异步处理机制。 - 控制主线程中任务的执行时间,避免阻塞。 3. **Android中的内存泄漏如何检测与避免?** - 内存泄漏是指应用中某些对象不再使用,但由于某些引用未释放,导致GC无法回收这些对象。 - 检测工具包括: - `LeakCanary`:一个轻量级的内存泄漏检测库。 - `Android Profiler`:Android Studio内置的性能分析工具。 - 避免内存泄漏的方法包括: - 避免在静态类中持有`Context`的强引用。 - 使用弱引用(`WeakReference`)处理生命周期不确定的对象。 - 及时取消注册监听器、回调等。 ### 三、性能优化相关面试题 1. **如何优化App的启动速度?** - 启动优化可以从以下几个方面入手: - 减少`Application`和`Activity`的初始化时间。 - 延迟加载非核心功能。 - 使用`Splash`页优化用户感知体验。 - 避免在`onCreate()`中执行耗时操作。 2. **如何进行UI渲染优化?** - UI渲染优化包括: - 避免过度绘制(Overdraw),使用`Hierarchy Viewer`分析布局层级。 - 使用`ConstraintLayout`减少布局嵌套。 - 优化`RecyclerView`的使用,避免频繁创建和销毁`ViewHolder`。 - 使用`GPU渲染分析`工具检测渲染性能问题。 3. **谈谈Android中的冷启动、温启动、热启动的区别?** - 冷启动:应用从无到有启动,系统需要创建新的进程。 - 温启动:应用进程已经存在,但`Activity`需要重新创建。 - 热启动:应用进程和`Activity`都已存在,仅需恢复前台。 ### 四、项目经验与源码理解相关面试题 1. **你在项目中遇到过哪些性能瓶颈?是如何解决的?** - 面试官通常希望了解候选人在实际开发中解决问题的能力。可以从以下几个角度回答: - 内存泄漏问题:使用`LeakCanary`定位并修复。 - 页面卡顿:通过`TraceView`或`Systrace`分析卡顿原因。 - 网络请求优化:采用缓存策略、合并请求、使用`OkHttp`等。 2. **你是否阅读过Android源码?** - 如果有阅读过源码,可以举例说明,例如: - `Handler`机制的实现。 - `View`的绘制流程(`onMeasure()`、`onLayout()`、`onDraw()`)。 - `RecyclerView`的复用机制。 - 如果没有阅读过,建议可以提到正在学习《Android开发艺术探索》《Android进阶之光》等书籍作为补充。 3. **谈谈你对插件化/热修复的理解?** - 插件化是指将部分功能模块以插件形式加载运行,常用于大型App的模块解耦。 - 热修复是指在不发布新版本的情况下修复线上Bug,常用方案包括: - `Tinker`:基于dex差分的热修复。 - `AndFix`:基于方法替换的热修复。 - `Sophix`:阿里推出的热修复框架,支持类、资源、so库的修复。 ### 五、跨平台与新技术相关面试题 1. **是否了解Flutter?其原理是什么?** - Flutter是Google推出的跨平台开发框架,支持iOS和Android。 - 其核心原理是使用Dart语言编写代码,通过Skia引擎进行UI渲染,不依赖原生控件。 - Flutter采用“自带渲染引擎”的方式,保证了UI在不同平台的一致性。 2. **Kotlin与Java在Android开发中的区别?** - Kotlin具有更简洁的语法,支持空安全、扩展函数、协程等特性。 - Kotlin与Java完全兼容,可以混合使用。 - Android官方推荐Kotlin作为首选开发语言。 ### 示例代码:使用Handler实现主线程与子线程通信 ```java public class MainActivity extends AppCompatActivity { private Handler mHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); if (msg.what == 1) { // 更新UI TextView textView = findViewById(R.id.textView); textView.setText("收到子线程消息"); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Thread(() -> { // 子线程发送消息 Message message = Message.obtain(); message.what = 1; mHandler.sendMessage(message); }).start(); } } ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值