Android工程师技术话术

技术

1.    开发中都遇到了什么问题?

(1)剖析

企业提出这个问题的原因大致有两个原因,其一验证面试人员的履历是否真实,如果面试人员没有经历过真实的项目那么他是无法真实且准确的预料开发中所遇到的问题的;其二,企业着实想通过这个问题考验面试人员的逻辑思维能力及问题处理能力,那么问题来了,解决问题的士兵就是好士兵了吗?其实不然,企业更希望面试人员可以提供更多的解决方案。

(2)目标

能够通过对这个问题的回答获得主导权,尽量回答更多的问题,从而避免面试官提问,面试官每天都面试那么多人,他们很累的。

(3)参考话术

对于这个问题,我们在以往的项目开发过程中确实遇到了一些比较棘手的问题,比如在之前做过的新闻项目(或电商项目)中由于业务需要,我们不得不频繁的加载网络图片,从而导致内存溢出的现象大频率出现,这在当时确实是个比较头痛的事儿,后来经过我们小组会议确定了一种解决方案,那就是使用开源项目ImageLoader来实现图片缓存处理,ImageLoader是一款非常优秀的开源项目,在GItHub上可以下载到,那么在CSDN上也有很多技术大牛对ImageLoader发表了很多优秀的博文,ImageLoader可以实现三级缓存,多线程下载图片,图片不仅可以来源于网络,也可以来源于本地的文件系统,而且ImageLoader还可以支持随意的配置线程池、图片下载器、内存缓存策略、硬盘缓存策略、图片显示等一些列的配置信息,最主要的,ImageLoader可以实现图片下载过程的监听,那么在图片缓存的开源框架中,优秀的产品不仅仅有ImageLoader一款,比如Picasso、Glide也都是非常的优秀,而且使用起来也非常的容易上手,我们站在用户的需求上考虑,如果用户要求更完美的展现图片的细节,那么非Picasso莫属,如果更注重于顺滑的图片滑动体验,Glide更加合适,然而当时我们公司为什么选择了ImageLoader呢,主要原因还是在于ImageLoader可以支持图片下载的过程监听。

在项目开发过程中,奇葩的问题实在是太多了,比如说之前我们做过的一款电商项目(或新闻项目),由于用户加了一些比较特色的需求,我们大概用了2个多月的时间把项目完成,交付给了甲方,由于刚开始他们的用户并不多,可能是他们公司运营方面做的比较到位,在大概半年左右的时间用户量就达到了一个比较理想的数字,也就是去年年初的时候吧,随着平板电脑的普及,他们发现软件在手机上运行的都挺理想的,但是在平板电脑上用起来就不舒服了,很多页面都走样了,然后找到了我们公司,做了二次开发,我们接到项目的时候,经过小组讨论分析,确定是屏幕适配的问题,其实当时我们也挺头痛的,但是没办法,公司是要挣钱的,问题很简单方法多得很,最开始我们考虑使用权重的方式来实现,大部分页面还是中规中矩的,但是大体效果还不是特别的理想,后来我们也是选择了一款Google提供的开源项目PercentSupport,这款百分比布局开源项目也可以在GitHub上下载到,有了他,我们笑了,问题解决了,在后来的项目开发中我也学习到了其他的解决方案,比如说AutoLayout,我认为,经验就是这样通过在不断的开发,不断的总结,不断的学习中积累的,其实说到底我还是得感谢XXX(上家公司名称),也是他成就了今天的我。

(4)总结

通过以上的参考话术,大家想想,有哪些问题面试官不会再问你了?

a.    你都浏览过那些开源项目?

b.   请讲一下ImageLoader的缓存原理?

c.    如何实现屏幕适配的?

d.   如何解决内存优化的问题?

e.    你会使用GitHub吗?

f.     你的学习能力怎么样?

g.    你的工作(项目)经历?

h.   是否可以独立开发?

 

2.    IM(即时通讯)方面

我们之前在XXX项目中使用到了即时通讯技术,在此之前对于IM技术我也做过些许的技术储备,比如OpenFire服务器的搭建,asmack开源框架的理解,曾经我也参考了CSDN上的一些技术大牛发表的博文写了一个关于IM的Demo,但是当时由于项目工期问题和服务器的投入问题,我们还是放弃了自主研发,选择了一款第三方的产品,融云IM,在确定选择这款产品之前,我们也在当期口碑比较好的其他产品中做了一个比较,比如说环信,可以说最开始我们用的就是环信做的Demo,可能是运气的问题吧,我们用的时候,环信的服务器总是不稳定,掉线的情况频频发生,消息送达率也非常低,而且断线重连做的也不是很理想,所以后来我们也就放弃了,当时还有一款腾讯的产品叫信鸽,他在服务器方面做的还是非常理想的,但是他不支持即时通讯,我们想要实现IM只能用推聊的方式来实现,所以经过最终的考量,我们还是选择了融云,融云非常的好用,他为我们提供了一套核心依赖库和一套界面库,通过这套界面库,我们可以实现快速集成,记得当时我们的即时通讯功能不到一个星期就全完成了,非常好用。

3.    支付方面

我们在xxx项目中用到了支付技术,当时我们用到的是支付宝支付和银联支付,支付方面都比较简单了,在确认集成后,支付宝公司和银联会提供给我们相关的集成文档和SDK,我们就是按照这些资料进行集成的,相关实现都很简单,我那边也保留了最开始做的Demo的源码,如果咱们公司要用的话,我这边很快就能完成工作。

4.    第三方SDK

出于个人的想法啊,我个人还是比较喜欢自主研发的,但是在项目开发过程中,往往因为工期的原因我们不得不选择一些第三方提供的SDK,缩短研发周期,毕竟公司不是慈善机构,需要快速的回拢资金,那么在以往的项目中,我们地图(百度地图)、支付宝、银联、IM(融云)、推送(极光推送或个推)、社会化分享(MoBO)、第三方登录(友盟)方面的SDK用到的还是比较多的。

5.    产品介绍

首先要夸赞和认同自己的项目,你想一下,如果你都不认同自己的项目,那么其他人还会认同你的项目吗?他只会视你的现年购买为不入流的玩物,这就是一种心理暗示的体现。

在介绍项目的同时,我们应当圆滑的由项目引到开发项目遇到的问题上(参考话术1. 开发中都遇到了什么问题?),这样,你想一下,面试官还会问你开发中都遇到了什么问题吗?

6.    加密

我们之前做项目的时候经常使用到加密算法,我了解的常用的加密算法有对称加密和非对称加密两大类型,对称加密就是加密和解密使用同一个密钥,比如说当前被大家广为使用的DES加密算法;那么非对称加密就是加密和解密使用的不是同一个密钥,非对称加密呢通常有两个密钥,分别是“公钥”和“私钥”,他们必须配对使用,否则不能打开加密文件,当然“公钥”是对外公布的,“私钥”则不能对外公布,只能由持有人自己知道,它的优越性就在这里,因为对称式的加密方法如果是在网络上传输加密文件就很难不把密钥告诉对方,不管用什么方法都有可能被别窃听到。而非对称式的加密方法有两个密钥,且其中的“公钥”是可以公开的,也就不怕别人知道,收件人解密时只要用自己的私钥即可以,这样就很好地避免了密钥的传输安全性问题,比如说当前使用非对称加密的有HTTPS。

那么MD5算法其实严格来说,他并不能算是一种加密算法,他只能说是一种摘要算法(摘要算法:数据摘要算法是密码学算法中非常重要的一个分支,它通过对所有数据提取指纹信息以实现数据签名、数据完整性校验等功能,由于其不可逆性,有时候会被用做敏感信息的加密。数据摘要算法也被称为哈希(Hash)算法、散列算法)。MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。那么我们在开发中一般使用MD5来签名用户的密码。

我们公司之前开发中也常用加密算法,大家都知道如果是HTTP的GET请求的话,在IE上请求接口,响应的内容会直接明文显示,那么这就毫无安全可言了,对于这种情况我们在接口方面使用了BASE64加密算法进行加密并用GZIP进行了压缩处理,在手机端我们将请求到的数据先通过GZIP解压缩再使用BASE64加密算法进行解密处理获得明文,这样在安全性上得到了一个保证。

7.    组织架构

我们公司因为是外包公司嘛,组织架构上也不是特别的明确,基本大部分的决策性工作比如财务、销售都由老板来做了,我上面有个项目经理,人挺好的,我还有6个同事,2个ios的,2个安卓(加上我)的,1个美工,1个做接口的,人事工作如果老板在就老板做,但是基本都是项目经理来做了。

8.    工作分配流程及协作

流程的话,一般都是老板在外面谈项目,如果项目是二次开发或是接口和美化都有的话,项目经理会给我们讲讲实现的需求,分配工期,我们就可以工作了,但是我们每天都有日报,周末的时候也会开周总结会。如果接到的项目是新项目,我们经理就会给我们开会,根据用户需求设计原型图,当然我们经理都会要求我们做原型图,在Axure方面我还是很不错的,然后确认原型,大概这个阶段不会太长,最长时间基本也不会超过1个星期,当然这段时间加班是必不可少的,甲方确认原型后我们的美工就开始做UI设计了,我们几个研发主要就是设计接口,接口名,JSON结构体,输入参数和输出参数都定好,然后出接口文档,之后大家就按照这个接口协议进行开发,由于协议对好了,开发完成后基本都能对接上,等美工把切图做好了,我们再把图片替换做相应屏幕的适配。

9.    3年工作经验项目数量不够

您也知道咱们做外包的项目周期都非常短,基本2-3个月就一个项目,快的可能1个月就完成了,我这3年基本做了也差不多20左右个项目了,但是咱们写简历嘛,主要还是把最经典的项目写上去,我觉得我这三年的工作中最中意的就是这5个了。

10.自定义控件

说到自定义控件,无非就是重写measure方法和layout方法,根据咱们的业务需求测量和重绘控件,像这种自定义控件的需求千篇一律,掌握好了原理,基本都能实现。




1.下拉刷新时头部导航条的透明度会随着scrollview的滑动距离改变而改变,滑动到一定距离时,界面右下方会出现一个小火箭,点击它,界面会有一个置顶功能。首先我会自定义一个组件,继承LinearLayout,添加一个header view,保证是第一个添加到linearlayout的最上端,设置topMargin的值为负的header View高度,即将其隐藏在最上方,之后需要添加footer view,由于是线性布局可以直接添加,只要AdapterView的高度是MATCH_PARENT,那么footer view就会被添加到最后,并隐藏。下来刷新和上拉加载都要进行手指滑动距离的判断,当header view的topMargin>=0时,说明已经完全显示出来了,修改header view 的提示状态,footer 准备刷新,手指移动过程,还没有释放移动footer view高度同样和移动header view高度是一样,都是通过修改header view的topmargin的值来达到。为了实现偏移控制,一般自定义View/ViewGroup都需要重载computeScroll()方法,我会判断scrollview的滑动距离动态去给导航条的背景设置透明度,滑动渐变的效果,当滑到一定距离时,我会把小火箭显示出来,点击是会调用scrollview的scrollTo()方法,实现置顶功能。


2.图片的缓存处理
在加载图片的时候,如果图片比较大时而界面上只需要显示一小块,那么会造成内存浪费,继续加载更多也可能会出现内存溢出,这时使用缓存技术是必备的,这里我用的是IamgeLoader的LruCache类,首先将ImageLoader类设成单例,并在构造函数中初始化了LruCache类,把它的最大缓存容量设为最大可用内存的1/8。然后又提供了其它几个方法可以操作LruCache,以及对图片进行压缩和读取。首先自定义一个继承自ScrollView的类,这样就允许用户可以通过滚动的方式来浏览更多的图片。这里提供了一个loadMoreImages()方法,是专门用于加载下一页的图片的,因此在onLayout()方法中我们要先调用一次这个方法,以初始化第一页的图片。然后在onTouch方法中每当监听到手指离开屏幕的事件,就会通过一个handler来对当前ScrollView的滚动状态进行判断,如果发现已经滚动到了最底部,就会再次调用loadMoreImages()方法去加载图片。在这个方法中,使用了一个循环来加载这一页中的每一张图片,每次都会开启一个LoadImageTask,用于对图片进行异步加载。然后在LoadImageTask中,首先会先检查一下这张图片是不是已经存在于SD卡中了,如果还没存在,就从网络上下载,然后把这张图片存放在LruCache中。接着将这张图按照一定的比例进行压缩,并找出当前高度最小的一列,把压缩后的图片添加进去就可以了。另外,为了保证图片都能够合适地被回收,这里还加入了一个可见性检查的方法,即checkVisibility()方法。这个方法的核心思想就是检查目前照片墙上的所有图片,判断出哪些是可见的,哪些是不可见。然后将那些不可见的图片都替换成一张空图,这样就可以保证程序始终不会占用过高的内存。当这些图片又重新变为可见的时候,只需要再从LruCache中将这些图片重新取出即可。如果某张图片已经从LruCache中被移除了,就会开启一个LoadImageTask,将这张图片重新加载到内存中。


断点续传:
1:当用户点击下载按钮是就要把文件路径的信息传给后台由service的onstartcom的方法接受穿过来的参数,由于service和activity都是主线程不能做耗时操作所以要开启一个子线程去做耗时操作网络下载和把数据写到本地文件并且把进度信息本地文件保存到数据库并把进度传给activity通过广播发送网络文件


网络下载的关键点:


1:获取网络文件的长度
2:在本地创建一个文件,设置其长度
3:从数据库中获取上次下载的进度
4:从上次下载的位置下载数据,同时保存进度到数据库
5:将下载进度回传activity
6:下载完成后删除下载信息




3.流式布局的实现
自定义ViewGroup,重点重写下面两个方法
1)onMeasure:测量子view的宽高,设置自己的宽和高
2)onLayout:设置子view的位置,onMeasure:根据子view的布局文件中属性,来为子view设置测量模式和测量值
当这个流式布局在被加载如内存并显示在屏幕上这一过程中,首先会调用view.measure(w,h)这个方法,表示测量view的宽度与高度,其中参数w与h分别表示这个控件的父控件的宽高。在view.measure()方法的调用过程中又会调用view本身的一个回调方法,onMeasure(),这个是view自身的一个回调方法,用于让开发者在自定义View的时候重新计算自身的大小。一般会在这个方法中循环遍历,计算出这个控件的全部子孙控件的宽高。在View的宽高计算完成以后,考虑将这个控件显示到屏幕的指定位置上,此时view的onLayout()方法会被调用。 一般同时会在这个方法中计算出全部子孙控件在这个控件中的位置。在onMeasure()中首先通过循环,遍历这个控件的所有子控件,同时调用子控件的measure()方法,这时measure方法的两个参数是控件能给这个子控件的最大宽高这里getChildMeasureSpec()方法的作用是用来计算一个合适子视图的尺寸大小(宽度或者高度),结合我们从子视图的LayoutParams所给出的MeasureSpec信息来获取最合适的结果。比如,如果这个View知道自己的大小尺寸,并且子视图的大小恰好跟父窗口一样大,父窗口必须用给定的大小去layout子视图,通过循环遍历,控制每个item子控件的显示位置,如果当前行还能放得下一个item,就放到当前行,如果放不下就放到下一行的最左边。


4.支付功能:
微信支付:
1)从微信开放平台上下载微信支付的SDK,使用其libammsdk.jar包。
2)在微信开放平台注册我们的应用(应用需要填写包名,应用的签名等)可以获取到APPID和APPSecret,然后申请开通支付功能,提交企业以及银行账户资料等待审核,审核通过了在线签订合同,之后就可以进行微信支付了,同时商户会收到邮件获得财付通商户账户,支付秘钥key,财付通权限秘钥,财付通商户标示id等开发关键数据。
3)预付订单:当用户确定购买商品之后,首先请求微信服务器获取access_tocken,提交预付订单package,添加签名,提交预付订单后会获取微信服务器返回的prepayid,接着把请求参数返回给手机端。
4)发起支付:调用api.sendReq(req);发起支付,发起支付的时候需要传入支付相关信息,相关信息以KEY-VALUE键值对方式用&拼接组成。例如:订单信息(订单号,交易付款时间,购买数量等),商品信息(商品名称,商品单价,商品描述等),支付信息(支付金额等)和notify_url(这个是通知地址,也就是微信的服务器把支付后成功与否等结果信息同步给我们公司服务器时候使用的地址)等。还需要拼接一个重要的签名参数sign,sign的值是上述这些交易信息MD5加密签名后的结果。
5)支付信息提交后会提交到微信的服务器,微信服务器完成整个支付功能后会给用户(客户端和服务器分别提示)成功或者失败的提示。
支付宝支付:
1)首先从支付宝平台下载SDK,使用其中的alipay.jar包。
2)当用户确定购买商品之后,首先生成订单,我们订单生成的规则就是用两个2-9的随机数+当前时间的毫秒值作为订单号。
3)调用支付宝的接口:调用支付宝的支付方法(方法Alipay.pay(String info)),支付方法需要传入支付相关信息,相关信息以KEY-VALUE键值对方式用&拼接组成。订单信息(订单号,交易付款时间,购买数量等),商品信息(商品名称,商品单价,商品描述等),支付信息(买方,卖方支付宝账号信息,支付金额等)和notify_url(这个是通知地址,也就是支付宝的服务器把支付后成功与否等结果信息同步给我们公司服务器时候使用的地址)等。还需要拼接一个重要的签名参数sign,sign的值是上述这些交易信息RSA签名后的结果。
4)支付信息提交后会提交到支付宝的服务器,支付宝的服务器完成整个支付功能后会给用户成功或者失败的提示界面。这个过程都是支付宝的功能。支付宝支付完成后,也会把信息同步给我们的服务器(也就是通过前面的notify_url这个地址)。
5)我们的服务器处理完毕之后,调用pay方法的时候其实也会接到返回值。返回值是json格式里面有很多信息,我们主要从中取结果状态码(resultStatus),根据状态码的数值判断支付是否成功,除了支付宝本身的提示界面以外,我们也会给用户一个我们自己的提示。


5.xmpp实现聊天功能:
我项目中即时通讯主要使用XMPP实现的,它有一个开源项目androidpn,使用的时候客户端要用到asmack.jar包,这个jar包提供了通讯的功能,主要使用jar包中的XMPPConnection类。主要实现如下:
1)使用XMPPConnection类与服务器建立持久连接
2)在持久连接基础上进行用户注册(用户注册之后服务器就会记录该用户的信息,下次就能够识别)
3)在连接基础上进行用户登录认证(登录之后服务端会知道当前用户的状态)服务端只要记录了该用户的信息,就可以往用户手机上发送推送的信息了。
实现通讯功能主要是使用jar包中的Chat类完成信息的发送,发送信息的时候要注意的是用户的格式是用户名称@域/命名空间(例如:要给loupengfei聊天的话地址为:loupengfei@127.0.0.1/AndroidpnClient),这样服务端就能够把信息转给响应名称的人。
接收信息:
1)在用户建立连接的时候就定义了一个指定命名空间的解析器provider(负责解析服务端发过来的xml格式的消息) 
2)同时也注册一个包监听器PacketListener,当有信息发送过来的时候我们定义的解析器会收到信息,在解析中使用PULL解析方式把xml中信息解析出来然后封装成我们自定义的一个IQ的子类(就是消息Bean),然后带着消息进入到包监听类中,在包监听类中结合handler把聊天内容等更新到UI上。


6.自定义圆形头像:
1)首先通过setImageBitmap()方法设置图片Bitmap 
2)进入构造函数CircleImageView()获取自定义参数,以及调用setup()函数
3)进入setup()函数(非常关键),进行图片画笔边界画笔(Paint)一些重绘参数初始化:构建渲染器BitmapShader用Bitmap来填充绘制区域,设置样式和内外圆半径计算等,以及调用updateShaderMatrix()函数和 invalidate()函数
4)进入updateShaderMatrix()函数,计算缩放比例和平移,设置BitmapShader的Matrix参数等
5)触发ondraw()函数完成最终的绘制,使用配置好的Paint先画出绘制内圆形来以后再画边界圆形。


7.瀑布流照片墙的实现
瀑布流的布局方式虽然看起来好像排列的很随意,其实它是有很科学的排列规则的。整个界面会根据屏幕的宽度划分成等宽的若干列,由于手机的屏幕不是很大,这里我就分成三列。每当需要添加一张图片时,会将这张图片的宽度压缩成和列一样宽,再按照同样的压缩比例对图片的高度进行压缩,然后在这三列中找出当前高度最小的一列,将图片添加到这一列中。之后每当需要添加一张新图片时,都去重复上面的操作,就会形成瀑布流格局的照片墙。


8.屏幕适配
1)比重适配,控件在其父布局中的显示权重,一般用于线性布局中,如果控件过多,且显示比例也不相同的时候,控制起来就比较麻烦了,毕竟反比不是那么好确定的。
2)多个布局文件适配,就是对不同大小的屏幕提供不同的layout。比如横竖屏的切换,可以在res目录下建立layout-port和layout-land两个目录,里面分别放置竖屏和横屏两种布局文件,以适应对横屏竖屏自动切换。
3)多个drawable适配(图片的适配),就是对不同密度的屏幕提供不同的图片。在进行开发的时候,我们需要把合适大小的图片放在合适的文件夹里面。应尽量使用.9格式的图片,如需对密度为low的屏幕提供合适的图片,需新建文件夹drawable-ldpi/,并放入合适大小的图片。相应的,medium对应drawable-mdpi/,high对应drawable-hdpi/,extra high对应drawable-xhdpi/。
4)多个values适配,为了优质的用户体验,需要去针对不同的dpi设置,编写多套数值文件,要把生成的所有values文件夹放到res目录下,当设计师把UI高清设计图给你之后,你就可以根据设计图上的尺寸,以某一个分辨率的机型为基础,找到对应像素数的单位,然后设置给控件。


9.内存优化
1)静态变量引起内存泄露
静态变量是类相关的变量,它的生命周期是从这个类被声明,到这个类彻底被垃圾回收器回收才会被销毁。所以,一般情况下,静态变量从所在的类被使用开始就要一直占用着内存空间,直到程序退出。如果不注意,静态变量引用了占用大量内存的资源,造成垃圾回收器无法对内存进行回收,就可能造成内存的浪费。
2)使用Application的Context
在Android中,Application Context的生命周期和应用的生命周期一样长,而不是取决于某个Activity的生命周期。如果想保持一个长期生命的对象,并且这个对象需要一个 Context,就可以使用Application对象。可以通过调用Context.getApplicationContext()方法或者 Activity.getApplication()方法来获得Application对象。
3)及时关闭资源
Cursor是Android查询数据后得到的一个管理数据集合的类。正常情况下,如 果我们没有关闭它,系统会在回收它时进行关闭,但是这样的效率特别低。如果查询得到的数据量较小时还好,如果Cursor的数据量非常大,特别是如果里面 有Blob信息时,就可能出现内存问题。所以一定要及时关闭Cursor。
4)避免使用浮点数
通常的经验是,在Android设备中,浮点数会比整型慢两倍。
5)使用实体类比接口好
按照传统的观点Map会更好些,因为这样你可以改变他的具体实现类,只要这个类继承自Map接口。传统的观点对于传统的程序是正确的,但是它并不适合嵌入式系统。调用一个接口的引用会比调用实体类的引用多花费一倍的时间。如果HashMap完全适合你的程序,那么使用Map就没有什么价值。如果有些地方你不能确定,先避免使用Map,剩下的交给IDE提供的重构功能好了。(当然公共API是一个例外:一个好的API常常会牺牲一些性能)
6)避免使用枚举
枚举变量非常方便,但不幸的是它会牺牲执行的速度和并大幅增加文件体积。
使用枚举变量可以让你的API更出色,并能提供编译时的检查。所以在通常的时候你毫无疑问应该为公共API选择枚举变量。但是当性能方面有所限制的时候,你就应该避免这种做法了。
7)使用Bitmap及时调用recycle()
Bitmap是内存消耗大户,绝大多数的OOM崩溃都是在操作Bitmap时产生的,我们需要根据需求去加载图片的大小,例如在列表中仅用于预览时加载缩略图,只有当用户点击具体条目想看详细信息的时候,这时另启动一个fragment/activity/对话框等等,去显示整个图片。直接使用ImageView显示bitmap会占用较多资源,特别是图片较大的时候,可能导致崩溃,使用BitmapFactory.Options设置inSampleSize, 这样做可以减少对系统资源的要求。使用Bitmap过后,就需要及时的调用Bitmap.recycle()方法来释放Bitmap占用的内存空间,而不要等Android系统来进行释放。
8)对Adapter进行优化
如果一个对象只具有软引用,那么如果内存空间足够,垃圾回收器就不会回收它;如果内存 空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。软引用可以和一个引用队 列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
如果一个对象只具有弱引用,那么在垃圾回收器线程扫描的过程中,一旦发现了只具有弱引 用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。弱

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值