Java 基础面试题
Java的四大引用?
强引用(StrongReference):使用最普遍的引用,强引用的对象,GC不会回收它;Java虚拟机宁愿抛出异常错误,是程序终止也不会靠随意回收具有强引用的对象来解决内存不足的问题。
软引用(SofeReference):软引用的对象,只有内存不足的情况下,才会回收这些对象的内存。只要GC没回收,该对象就可以被程序使用。
弱引用(WeakReference):弱引用和软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。
虚引用(PhantomReference):与其他几种引用都不同,虚引用并不会决定对象的生命周期;如果对象只持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用必须和引用队列ReferenceQueue联合使用。
说一下面向对象的理解?
1. 面向对象就是把一个对象抽象成类,具体来说就是把一个对象的静态特征和动态特征抽象成属性和方法,也就是把一类事物的算法和数据结构(数据结构为多个元素之间存在的关系,一个数据结构是由n(n>=0)个元素组成的有限集合中的某种特定的关系)封装在一个类中,程序就是多个对象之间相互通信组成的
2. 面向对象具有封装、继承、多态三大特性
3. 所谓封装就是隐藏信息,实现细节
4.继承和多态,继承是多态的条件之一
5.多态就是一个事物具多种表现形态,使用不同的实例执行不同的操作
说一下抽象与接口的区别?
相同点:1、两者都不能实例化;2、可以拥有抽象方法。
区别:
1、抽象类定义的关键字是abstract class,接口定义的关键字是interface;
2、属性上,抽象类可以有静态变量、常量和成员变量,接口只能有常量;
3、抽象方法可以有普通方法,而接口jdk1.8之前只能有抽像方法(1.8之后,增加了静态方法和默认方法);
4、抽象方法可以有构造方法,接口不可以有构造方法。
5、一个类只能单继承一个父类,而一个接口可以继承多个父接口,同时,一个类可以实现多个接口却没有实现多个父类这一说法;
6、抽象方法在业务编程上更像一个模板,有自己的功能,同时也可以有优化补充的多种形式,而接口更像是一种规范和要求,实现就要按照要求来进行。
“==”和equals的区别?
== 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;
而 equals 默认情况下是引用比较,只是很多类重新了 equals 方法,
比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。
详情:https://segmentfault.com/a/1190000039132885
List、Set、Map的区别?
List中存储的数据是有顺序的,值是可重复的;
Map中存储的数据是无序的,它的键不允许重复,但是值可以重复的;
Set中存储的数据是无顺序的,值是允许重复的,但是元素在集合中的位置是由元素的hashCode决定的,即位置是固定的(Set集合是根据hashCode来进行数据存储的,所以位置是固定的,但是这个位置不是用户可以控制的,所以对于用户来说set中的元素还是无序的)
如何在Java中使用链式调用,是使用什么设计模式?
创建者模式
详情:https://blog.csdn.net/FeiChangWuRao/article/details/124862938
手写一个单例设计模式代码?
特点:
单例类在一个进程或线程中只能存在一个实例。
单例类的构造器必须私有化。不允许其它类来创建单例类,只有它自己能够创建自己。
单例类需要向其它类提供获取实例的方法,一般是静态的。
优点
减少了内存的开销。因为单例模式要做是严格控制只能存在一个实例,这样就会极大地减少实例反复创建时带来的内存开销。
更加容易管理和维护。没什么好说的,全部内容都写在这个类里,只需要修改这个类就行了。
缺点
扩展性不强。单例模式只专注于只有能存在一个实例,这就牺牲了它的扩展性。
与单一职责冲突。因为所有方法都要封装在单例类中,所以会越来越庞大,职责也会越来越不清晰。
Android面试题
一个线程有几个Looper?一个线程可以有几个Handler?
只能有一个,不然调用Looper.prepare()会抛出运行时异常,提示“Only one Looper may be created per thread”
可以创建无数个Handler,但是他们使用的消息队列都是同一个,也就是同一个Looper
handler的消息机制?
主要涉及的角色如下所示:
message:消息。
MessageQueue:消息队列,负责消息的存储与管理,负责管理由 Handler 发送过来的 Message。读取会自动删除消息,单链表维护,插入和删除上有优势。在其next()方法中会无限循环,不断判断是否有消息,有就返回这条消息并移除。
Looper:消息循环器,负责关联线程以及消息的分发,在该线程下从 MessageQueue获取 Message,分发给Handler,Looper创建的时候会创建一个 MessageQueue,调用loop()方法的时候消息循环开始,其中会不断调用messageQueue的next()方法,当有消息就处理,否则阻塞在messageQueue的next()方法中。当Looper的quit()被调用的时候会调用messageQueue的quit(),此时next()会返回null,然后loop()方法也就跟着退出。
Handler:消息处理器,负责发送并处理消息,面向开发者,提供 API,并隐藏背后实现的细节。
整个消息的循环流程还是比较清晰的,具体说来:
1、Handler通过sendMessage()发送消息Message到消息队列MessageQueue。
2、Looper通过loop()不断提取触发条件的Message,并将Message交给对应的target handler来处理。
3、target handler调用自身的handleMessage()方法来处理Message。
线程本地变量ThreadLocal?
ThreadLocal是一个关于创建线程局部变量的类。使用场景如下所示:
实现单个线程单例以及单个线程上下文信息存储,比如交易id等。
实现线程安全,非线程安全的对象使用ThreadLocal之后就会变得线程安全,因为每个线程都会有一个对应的实例。 承载一些线程相关的数据,避免在方法中来回传递参数。
当需要使用多线程时,有个变量恰巧不需要共享,此时就不必使用synchronized这么麻烦的关键字来锁住,每个线程都相当于在堆内存中开辟一个空间,线程中带有对共享变量的缓冲区,通过缓冲区将堆内存中的共享变量进行读取和操作,ThreadLocal相当于线程内的内存,一个局部变量。每次可以对线程自身的数据读取和操作,并不需要通过缓冲区与 主内存中的变量进行交互。并不会像synchronized那样修改主内存的数据,再将主内存的数据复制到线程内的工作内存。ThreadLocal可以让线程独占资源,存储于线程内部,避免线程堵塞造成CPU吞吐下降。
在每个Thread中包含一个ThreadLocalMap,ThreadLocalMap的key是ThreadLocal的对象,value是独享数据。
非静态内部类/匿名内部类为什么引起内存泄漏?
非静态内部类/匿名类会隐式的持有外部类的引用,从而导致内存泄露
activityA打开activityB的的,两个的生命周期怎么运行?
Activity A:onPause
Activity B:onCreate
Activity B:onStart
Activity B:onResume
Activity A:onStop
activity的启动模式有哪些,使用场景分别是什么?
standard:创建一个新的activity;
singleTop:栈顶复用;
singleTask:栈内复用;
singleInstanse: 回退栈中,只有这一个Activity,没有其他Activity;
动画的种类有哪些?
属性动画:
1、插值器:作用是根据时间流逝的百分比来计算属性变化的百分比
2、估值器:在1的基础上由这个东西来计算出属性到底变化了多少数值的类
其实就是利用插值器和估值器,来计出各个时刻View的属性,然后通过改变View的属性来实现View的动画效果
View动画:
1、作用对象是 View,可用 xml 定义,建议 xml 实现比较易读
2、支持四种效果:平移、缩放、旋转、透明度;
3、只是影像变化,view的实际位置还在原来地方。
帧动画:
1、通过 AnimationDrawable 实现,容易 OOM
2、是在xml中定义好一系列图片之后,使用AnimatonDrawable来播放的动画。
讲一下属性动画?
1、可作用于任何对象,可用 xml 定义,Android 3 引入,建议代码实现比较灵活
2、包括 ObjectAnimator、ValuetAnimator、AnimatorSet
3、时间插值器:根据时间流逝的百分比计算当前属性改变的百分比,系统预置匀速、加速、减速等插值器
4、类型估值器:根据当前属性改变的百分比计算改变后的属性值,系统预置整型、浮点、色值等类型估值器
5、使用注意事项:避免使用帧动画,容易OOM;界面销毁时停止动画,避免内存泄漏;开启硬件加速,提高动画流畅性
6、硬件加速原理:将 cpu 一部分工作分担给 gpu ,使用 gpu 完成绘制工作;从工作分摊和绘制机制两个方面优化了绘制速度
***事件分发机制,拦截的流程?手指触摸手机屏幕,页面事件怎么处理,怎么拉截?
https://cloud.tencent.com/developer/article/1791608
***自定义view流程是什么?
编写attr.xml文件;
构造函数,初始化View;
onMeasure()测量view的大小
onLayout()确定view的大小
onDraw绘制内容
详情:https://juejin.cn/post/6844903904543670279#heading-17
图片Glide框架的内存模式,有哪些内存缓存模式?
Glide的缓存机制,主要分为2种缓存,一种是内存缓存,一种是磁盘缓存。
使用内存缓存的原因是:防止应用重复将图片读入到内存,造成内存资源浪费。
使用磁盘缓存的原因是:防止应用重复的从网络或者其他地方下载和读取数据。
Glide怎么管理生命周期?怎么不会内存泄露?
因为Glide 在加载资源的时候,如果是在 Activity、Fragment 这一类有生命周期的组件上进行的话,会创建一个透明的 RequestManagerFragment 加入到FragmentManager 之中,感知生命周期,当 Activity、Fragment 等组件进入不可见,或者已经销毁的时候,Glide 会停止加载资源。
但是如果,是在非生命周期的组件上进行时,会采用Application 的生命周期贯穿整个应用,所以 applicationManager 只有在应用程序关闭的时候终止加载。
Gilde加载一张图片,内存做了什么优化?
1. 尺寸优化
2. 图片格式优化
3. 内存复用优化
详情请看:https://juejin.cn/post/6970683481127043085#heading-11
Gilde加载内存尺寸大小,他的计算公式是?
请看:https://juejin.cn/post/6970683481127043085#heading-11
线程池如何使用?几个参数分别是什么?有什么作用?
线程池的构造函数有7个参数,分别是corePoolSize、maximumPoolSize、keepAliveTime、unit、workQueue、threadFactory、handler
详情请看:https://www.cnblogs.com/vipstone/p/15983907.html
内存重启后,怎么处理fragment页面重叠的问题?
Activity中的onSaveInstanceState(Bundle outState)方法里,判断当前所有Fragment,将已经加载的Fragment进行保存
在onCreate(Bundle savedInstanceState)中恢复保存的Fragment:
初始化Fragment
详情请看:https://juejin.cn/post/6844903846221725709
自定义view如何取消手势的?
https://juejin.cn/post/6988137354758373384
broadcast广播有哪些?
分两种:BroadcastReceiver,LocalBroadcastReceiver
1、应用场景
1、BroadcastReceiver用于应用之间的传递消息;
2、而LocalBroadcastManager用于应用内部传递消息,比broadcastReceiver更加高效。
2、安全
1、BroadcastReceiver使用的Content API,所以本质上它是跨应用的,所以在使用它时必须要考虑到不要被别的应用滥用;
2、LocalBroadcastManager不需要考虑安全问题,因为它只在应用内部有效。
3、原理方面
(1) 与BroadcastReceiver是以 Binder 通讯方式为底层实现的机制不同,LocalBroadcastManager 的核心实现实际还是 Handler,只是利用到了 IntentFilter 的 match 功能,至于 BroadcastReceiver 换成其他接口也无所谓,顺便利用了现成的类和概念而已。
(2) LocalBroadcastManager因为是 Handler 实现的应用内的通信,自然安全性更好,效率更高。
有序广播和无序广播的区别?
1.无序广播
就是我们普通的广播,接收者接收无序广播没有优先级之分,并且无序广播不可以被拦截,接收者之间不能传递数据。
2.有序广播
接收者接收有序广播有优先级之分,有序广播可以被接收者拦截、修改。例如广播接收者A和B,A的优先级高于B,则广播会先发送到A,A可以拦截广播停止传播,一旦拦截后面的接收者将不会收到广播,而且A可以根据广播的数据内容给B发送数据,B也可以接收A的数据。
Android 进程间的通讯方式IPC(进程间通信)有哪些?Google推荐的方式是?
使用Bundle
使用文件共享
使用Messenger
使用AIDL
使用COntentProvider
使用Socket
详情请看:https://www.cnblogs.com/lixiansheng/p/11359922.html
内存泄露和内存溢出的场景?是如何解决的?
https://juejin.cn/post/7032202754902720520
项目中有用到哪些设计模式?
Glide的实现原理?
Glide 图片加载流程大致三可以分为三个阶段:发起请求、启动任务以及解码图片
Glide的缓存原理
请看:https://juejin.cn/post/6970683481127043085#heading-11
https://juejin.cn/post/6882536990400020494
谈一下Kotlin的优缺点?
Kotlin优点
简化空对象的处理(防止空指针)
属性访问代替Get/Set方法
快速创建List/Map集合类型
简化Parcelable实现
协程coroutines使调用逻辑简化
简化单例对象构造
安卓自动绑定xml文件中控件定义,不再需要使用findViewById或ButterKnife
使用when进行分支判断(替代Java中switch)
使用字符串模版简化字符串拼接
对象属性调用简化(使用with、apply、let等)
解构对象(Destructuring Declarations)
Kotlin缺点
编译速度不稳定,受不同情况印象较大。较少社区支持,Kotlin的开发人员社区很小,因此学习该语言的资源有限。
Java优点
轻便。借助与平台无关的Java虚拟机,Java程序几乎可以在任何系统上运行。
跨平台。Java语言支持Android应用程序开发和跨平台的应用程序开发。
资源资源。当Java开发Android时,它已经具有可用于开发过程的库和SDK。
Java缺点
速度比其他语言慢,Java需要更多的内存,并且与其他语言相比要慢得多。
重类型语言,Java需要较长的代码,这会导致更多的错误和错误,从而浪费更多时间。
项目中有什么难点?