@Awille
2022-04-24T12:18:44.000000Z
字数 9752
阅读 390
未分类
1、context继承关系,dialog能否用applicationcontext启动
2、泛型擦除
泛型引入目标:
类型安全
泛型的主要目标是提高 Java 程序的类型安全
编译时期就可以检查出因 Java 类型不正确导致的 ClassCastException 异常
符合越早出错代价越小原则
消除强制类型转换
泛型的一个附带好处是,使用时直接得到目标类型,消除许多强制类型转换
所得即所需,这使得代码更加可读,并且减少了出错机会
编译器生成的代码跟不使用泛型(和强制类型转换)时所写的代码几乎一致,只是更能确保类型安全而已
泛型擦除指的是编译后,类型变量会被擦除, 有指定限定类型的有其限定类型,没有指定的用object替换。如果是指定上限,用其上限代替,如果指定下限,用其下限代替。
在调用泛型方法时,可以指定泛型,也可以不指定泛型。
在不指定泛型的情况下,泛型变量的类型为该方法中的几种类型的同一父类的最小级,直到Object
在指定泛型的情况下,该方法的几种类型必须是该泛型的实例的类型或者其子类

3、信号量
4、可见性、有序性、原子性
volatile可以保证可见性与有序性,有序性保障:
对volatile变量的读写操作会保持我们写程序定义的顺序。还有对volatile操作时,不能将对volatile变量操作前面的语句放在该操作后面,也不能将对volatile变量操作后面的语句放到语句前面。 volatile实现原理:内存屏障。
https://www.cnblogs.com/dolphin0520/p/3920373.html
5、锁降级
6、逆变、协变
LSP(Liskov Substitution principle) Liskov替换原则。
四层协议:
逆变协变用来描述类型传唤后的继承关系。
协变:你可以把子类的list对象赋值给父类的list引用。即子类的泛型类型,也属于泛型类型的子类。 你声明一个父类的类型,我给你赋值一个子类的对象。(java普通对象支持协变,但是泛型不支持)
但是你假如想让泛型支持协变,可以让你用子类的泛型对象赋值给父类的引用,可以使用通配符 ?extend,但这么写后,你只能用他不能修改他。
而 ? super 可以让支持逆变,让你把父类的泛型对象赋值给子类的泛型引用。
A继承自B时,A的协变也继承自B, 即A<=B, f(A)<=f(B)
java泛型不支持协变:你不可以把子类的list对象赋值给父类list的引用。 子类的泛型类型,不属于泛型类型的子类。
逆变:A继承自B时,A的逆变 > B的逆变。
java的普通变量,支持协变,由于A继承B, A的协变也继承B , 所以你声明B,是可以赋值A给他的。
java的泛型不支持协变,如果你生命一个父类的List引用,不能给赋值一个子类的list对象。 不支持协变的原因是类型擦除,由于编译时泛型参数会被擦除,为了保证类型安全,不支持协变。
7、try catch finally
. finally中的语句一定会执行,如果finally中有return, 那么会返回finally中的return的值。如果finally中没有return,如果对返回类型为基本类型,不会对返回值有影响,因为会存到局部变量表当中,如果是对对象内部值操作,会印象返回的对象里面的值。
https://www.cnblogs.com/sunshineweb/p/7656463.html
8、栈内存溢出:
栈内存 = 栈深度 * 栈帧大小 栈深度
StackOverFlow与OOM的区别?分别发生在什么时候,JVM栈中存储的是什么,堆存储的是什么?
stackoverflow指的是栈内存溢出(栈深度 * 栈帧大小),一般是递归造成的。
oom一般是堆内存溢出
9、虚引用:
虚引用主要用来跟踪对象被垃圾回收器回收的活动
10、方法区类的回收
* 类的实例都被回收
* 类的classloader被回收
* class对象没有被引用。
11、PathClassLoader与DexClassLoader的区别是什么?
DexClassLoader可以指定自己的optimizedDirectory,所以它可以加载外部的dex。 而PathClassLoader没有optimizedDirectory,所以它只能加载内部的dex,这些大都是存在系统中已经安装过的apk里面的,:只能加载系统中已经安装过的apk
12、java 锁的分类:
乐观锁、悲观锁
可重入锁
自旋锁
独享锁、共享锁
ReadWriteLock 读共享,读写共享,写写独享锁。
公平锁、非公平锁。 自选锁
13、 sleep是可中断的么
可以
14、java线程状态:

15、BroadcastReciver的静态注册与动态注册的区别?
静态:manifest注册,不需要解注册,静态注册的广播不受程序是否启动的约束,当应用程序关闭之后,还是可以接收到广播。
动态:动态注册,需要取消注册。
16、 广播的分类与工作原理
标准广播:异步执行,在广播发出后,所有的广播接收器会在同一时间接收到这条广播,广播无法被截断。
有序广播:同步执行,广播发出后,优先级高的广播接收器可以优先接收到这条广播,并可以在优先级较低的广播接收器之前截断停止发送这条广播。
17、可以再onReceive中开启线程么,会有什么问题?
可以,但是不可靠。因为onrceive方法执行时时激活态,执行结束后不再时激活态了。 开线程的话,生命周期不一致,可能导致其他的问题。
19、 Fragment的构造函数为啥不让传参?(B站)
Fragment是用反射的方式创建的,而且有mArguments来控制参数。因此要用特定的方式来传递参数:
https://www.jianshu.com/p/cc681ac9ddbd#comments
20、 Fragment add与replace的区别,分别对Fragment的生命周期影响
覆盖原fragment, 添加入一个新fragment后, 原来的fragment仍然存活。
replace 是先remove掉相同id的所有fragment,然后在add当前的这个fragment。
21、View.inflater过程与layoutinflater(东方头条)
23、onTouchListener onTouchEvent onClick的执行顺序
ontouchlistener > ontouchvent > onclick
onTouch return false 那么onlongclick不会执行,longclick过,onclick不会执行
ontouch返回false, longclick与onlick不会执行。
24、invalidate() 和 postInvalicate() 区别
postInvalicate 切换到了主线程
25、自定义View执行invalidate()方法,为什么有时候不会回调onDraw()
自定义一个ViewGroup,重写onDraw。
onDraw可能不会被调用,原因是需要先设置一个背景(颜色或图)。
表示这个group有东西需要绘制了,才会触发draw,之后是onDraw。
因此,一般直接重写dispatchDraw来绘制viewGroup
26、handler的Callback和handlemessage都存在,但callback返回true handleMessage还会执行么?(字节跳动、小米)
有msg.callback 直接执行msg.callback, 没有则检查handler callback, 有则执行hanllercallback,如果handlercallback返回true则不执行handlermessage。
27、Handler的sendMessage和postDelay的区别?(字节跳动)
一样的,都会调用sendmsgDelay, sendmessage delay入参为0.
28、ANR
5s内无法响应用户输入事件(例如键盘输入, 触摸屏幕等).
BroadcastReceiver在10s内无法结束.
29、如何判断一个 APP 在前台还是后台?
自己通过activity的生命周期来做
30、.如何做应用保活?
Android一般的进程优先级划分:
1.前台进程 (Foreground process)
2.可见进程 (Visible process)
3.服务进程 (Service process)
4.后台进程 (Background process)
5.空进程 (Empty process)
通过将Android中的Service的setForeground接口可以将后台Service设置为前台Service
AndroidManifest中"静态"注册系统广播监听器
31.一张图片100x100在内存中的大小?
图片加载框架:高效加载图片
https://www.cnblogs.com/dasusu/p/9789389.html
ARGB_8888:占用4个字节,默认该格式显示
ARGB_4444:占用2个字节
RGB_565:占用2个字节
ALPHA:占用1个字节
px = dp * (当前dpi / 160)
32.打开多个页面,如何实现一键退出?
33.LiveData的生命周期如何监听的?(B站)
34、非阻塞生产消费者模式
一、Java 基础相关
1.1 数据结构与算法
1.1.1 常用的数据结构有哪些?
1.1.2 数组
(1).如何在一个1到100的整数数组中找到丢失的数字?
开一个bool数组记录。 用下标也行,重复下标错误。
(2).如何在给定的整数数组中找到重复的数字? (小米)
借助set。 排序然后找到重复的。
(3).如何在未排序整数数组中找到最大值和最小值?(字节跳动)
便利一遍
(4).在Java中如何从给定数组中删除多重复制?
(5).大数相加(今日头条)
字符串翻转 然后相加
1.1.3 链表
(1).那查询第一个跟倒数第二个呢?(这就不一样了,第一个直接给了头结点,倒数第二个需要从倒数第一个开始查询,走两步) (腾讯)
(2).arrayList底层原理 (滴滴 字节跳动)
数组
(3).如何在一次遍历中找到单个链表的中值?(中国平安)
遍历一遍记录下来 然后找到中值
(4).如何证明给定的链表是否包含循环?如何找到循环的头节点? (优酷)
快慢指针。
(5).两个有交叉的单链表,求交叉点 (华为)
记录下来
(6).如何得到单链表的长度? 360
遍历
(7).如何在不使用递归的情况下逆转单链表? (小米/美团)
(8).怎么判断链表有环? (滴滴)
快慢指针。
1.1.4 队列&堆栈
(1).如何使用栈实现队列的功能?(广州荔枝FM)
两个栈呗
(2).两个栈实现一个队列 (蘑菇街)
(3).两个队列实现一个栈 (腾讯)
(4).对比一下队列和栈,以及它们底部实现 (腾讯)
队列 数组
1.1.5 二叉树
(1).如何在给定的二叉树中执行先序遍历?(百度)
(2).如何实现后序遍历算法? (百度)
(3).如何在给定数组中执行二分法搜索? (苏宁)
(4).已知前序遍历为{1,2,4,7,3,5,6,8},中序遍历为{4,7,2,1,5,3,8,6},它的二叉树是怎么样的? 58
(5).输入两棵二叉树 A 和 B,判断 B 是不是 A 的子结构。 (爱奇艺)
(6).请实现两个函数,分别用来序列化二叉树和反序列化二叉树。 (YY)
(7).平衡二叉树和红黑树的区别?(字节跳动)
(8).什么是平衡二叉树,它有什么特征 (美团)
(9).B 树,B+树
1.1.6 HashMap
(1).HashMap的底层原理是什么?线程安全么? (百度 美团)
done
(2).HashMap中put是如何实现的? (滴滴)
done
(3).谈一下hashMap中什么时候需要进行扩容,扩容resize()又是如何实现的?
done
(4).什么是哈希碰撞?怎么解决? (滴滴 美团)
done
(5).HashMap和HashTable的区别 (小米)
done
(6).HashMap中什么时候需要进行扩容,扩容resize()是如何实现的? (滴滴)
done
(7).hashmap concurrenthashmap原理 (美团)
done
(8).arraylist和hashmap的区别,为什么取数快?(字节跳动)
done
1.1.8排序算法有哪些?
(1).top-k排序(堆排序,位图法) (美团)
(2).冒泡排序的手写 (华捷艾米)
(3).堆排序算法的手写 (华捷艾米)
(4).椭圆形场地有两个赛道,可以同时提供两匹马比赛,两匹马比赛后,可以获知两匹马中跑的快的那匹马,但是没有计时工具。问题,如何最优的算法(比赛次数最少),获知10匹马中速度最快的三匹马 (阿里)
(5).输入一个整型无序数组,对堆排序的方法使得数组有序 (阿里)
(6).如何使用快速排序算法对整数数组进行排序? (CVTE)
1.1.9 查找算法
(1).有序数组的二分查找算法 (百度)
1.1.10 串
(1).给定一个字符串,请你找出其中不含有重复字符的 最长子串的长度。 (字节跳动)
(2).给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
1.1.11 请写出以下算法的时间复杂度
冒泡排序法 插入排序法 堆排序法 二叉树排序法
n2
1.1.12 其他算法
(1).常用的对称加密算法,有什么同? (字节跳动)
AES堆成 rsa非堆成
(2).如何在无序(有负数)的数组中查找是否存在和为target的两个数组合,twoSum(); (字节)
待回忆
总结答题:
1、Serializable 与 Parcelable
* 序列化目的:磁盘保存,网络传输、数据activity间传递
* pracelable性能要比 Serializable好,大概是快十多倍: 原因:
a、Parcelable是面向内存存储的,Serializable是面向磁盘的,在内存使用专用,pracelable性能要比 Serializable好。
b、serializable是基于反射机制的,会产生大量临时变量,会导致GC比较频繁
但是进行持久性存储时,还是用serialzible,因为parcelable版本不同,是有差异的。
为什么 serializable要使用uid,因为反序列化是根据uid来进行匹配的,如果未指定uid,那么修改属性会导致uid发生改变,而导致反序列化失败。
2、threadpool是如何对线程存活时间进行控制的?
线程池中维护了一个阻塞队列,对于非核心线程(线程数超过核心线程数)获取获队列中任务的时候,是有设置等待时间的,等待的时间就是非核心线程存活的时间。
3、anr的类型,以及如何获取anr
anr类型:扫雷:对于屏幕响应,假设某一次点击事件或者键盘事件导致程序发生了anr,那么在下次点击时间发生的时候,如果5s内未能响应,那么anr就会被系统报出来。 定时炸弹,比如广播的onReceive,从onReceive开始执行前就设置一个10s的定时器,如果10s结束后未执行完成,那么anr就会被系统报出来。
servie是前台service为20s内,后台服务200s内
contentprovider publish在10s内未执行完成
获取系统的anr:发生anr异常时会保存信息拿到 /data/anr/traces.txt中。
4、点击事件传递 从屏幕开始

a、用户触摸手机屏幕,系统将产生的设备节点保存到/dev/input目录下
b、IMS 中,底层EventHub通过epoll机制监听目录,将事件读出并加工传递给InputReader。
c、InputReader处理加工后交给InputDispatcher进行分发,通过socket通知UI进程的InputEventReceiver接收事件
d、InputEventReceiver将回调事件一步步传递给activity来处理。
e、activity现将事件传递给decorview进行处理,如果decoervoew消耗则返回true,否则调用自己的ontouchevent。
f、对viewgroup的dispatchTouchEvent,首先调用onInterceptTouchEvent判断是都自己处理,如果自己消费则调用自己的onTouchEvent否则调用子view的dispatchTouchEvent进行事件的分发。当某个view最终拦截消费事件,那么同一时间序列中的后续时间都直接交由这个子view进行处理。后续序列中onInterceptTouchEvent都不再被调用。
g、具体的事件处理,首先调用ontouchlistener的ontouch,返回true则结束消费,返回false则调用onTouchEvent。
当事件被viewgroup的子元素消费时,mfirstTouchTarget会被赋值,如果viewgroup本身消费那么mfirstTouchTarget会为空,那么后续的move事件都会默认让这个viewgroup处理,是否拦截函数也不调用。 只有子元素消费时,后续的事件才会继续查询viewgroup是否需要拦截。
外部拦截法:重写父view的onInterceptTouchEvent, 判断事件是否需要自己拦截。 对于DOWN事件要不拦截。
内部拦截法:父元素除了DOWN都默认拦截,子元素重写dispatchtouevent,对于DOWN事件,把父元素的禁止拦截标志位设为true。 这样父类就不会拦截事件了,在MOVE的时候,根据需要把父类的标志位设为false,让父类调用自己得函数是否进行拦截,这种情况都默认消费。
5、concurrenthashmap、hashmap、linkedhashmap
put操作:
a、得到key hash值, 通过与操作得到插入的数组位置,如果对应node为空,cas尝试插入节点。 如果cas插入失败或者node不为空,synchronied锁住节点,进行节点插入。
b、1.7 concurrenthashmap size 1.8 size
1.7 遍历计算每个segment的大小,计算两次,然后对比这两次modcount是否有变化,如果没变化返回大小,如果有变化则锁住所有segment计算大小。
1.8、basecount + contercells数组里面的值得和。 basecount:如果countcell数组为空,直接cas累加到basecount当中,如果失败调用fulladdcount
如果countcells数组不为空,cas写入当前线程产生的随机值下标 数值进行累加,如果失败调用fulladdcount
fulladdcount:countercells初始化,将累加值cas写入countercells中,如果失败将cas写入basecount, 以上过程不断循环。
lru: accessorder 为true removeEldestEntry回调
6、如何检测nativecrash
注册信号量进行检测。
7、recyclerview 四级缓存 sparsearray
a、一级缓存:changescrap 需要onBindveiwholder进行重下新数据绑定 mAttachSrap 未与recycler分离的列表
b、屏幕外缓存 mcacheview 默认数量为22
c、自定义缓存 viewcacheextendsion
d、recyclerviewpool 需要重新bindviewhodler。 以viewtype进行存储,每个viewtype最多存储5个,可多个recycler共享。
8、mvvm livedata viewmodel
9、从字节码层面做包体积优化
a、在dex文件阶段(dexbuilder + mergedex) 做冗余去除、内容精简、格式优化。 冗余去除包括你,单纯去除无用的代码指令,包括去除冗余赋值,无副作用代码删除。
减少方法和字段的数量,从而有效减少DEX数量。短方法内联,常量字段消除,R常量内联。
b、R文件内联
10.kotlin协程对比线程、线程池的优势
a、协程是一个优秀的线程调度框架,他可以让我们用接近同步的方式写出异步的代码,避免了回调地域。
b、任务可取消
c、在性能上,协程跟使用线程池的性能是一致的,协程在这方面并没有性能提升。 首先对于IO调用,用户程序会进行内核调用,对于内核调用会使线程进入阻塞状态,比如等待网络IO,无论是线程还是协程,都跨不过这个坎,都会进入阻塞,协程为什么说自己不阻塞,实际上是在他内部实现逻辑上帮助了你进行线程切换,在协程任务结束的时候切换回原来的线程。
11.实际项目中怎么用的协程
Global.launch(指定Dispatcher) {
// 书写协程体
}
launch :启动协程,返回Job,更多用来发起一个无需等待结果的耗时任务。
async:启动协程,返回deferred,deferred继承job,增加了wait方法,启动一个需要等待结果的耗时任务。
withcontext,切换线程并阻塞当前线程。
runblocking:启动一个新协程并阻塞当前线程,直至协程体内逻辑执行完成。
12.retrofit的优势,为什么okhttp要结合retrofit用?
retrofit源码需要熟悉一下下:
a、更简单的接口定义方式
b、提供可以对返回的Call进行自定义适配,比如可以与Rxjava结合转成observable对象。
13.mvvm在实际使用中有什么问题?怎么解决?
14.热修复的原理,怎么实现
15.gradle的编译流程是什么
a、编译class文件。首先是 R文件、android源代码、aidl产生的接口文件通过 java compiler生成class文件。
b、dex整合。class文件 进过 dexbuilder跟 mergeDex两个task 生成dex文件
c、资源文件整合。dex与资源整合成apk文件
d、签名
16.gradle插件怎么实现
这个用例子简单说一下
一个safechecker
一个iconversion
17.长连接怎么实现的
header Connection:keep-alive
18、应用保活
背景:android在内存较低的情况下,会关闭一些优先级比较低的进程以增大内存运行更重要的进程。
android进程优先级:前台进程>可见进程>服务进程>后台进程
保活就是要提升进程优先级。
a、屏幕锁屏时1个像素的activity、解锁时销毁。
b、利用notification
c、注册系统广播拉活,比如网络变化
d、该方案将Service的onStartCommand方法的返回值设置为START_STICKY,利用系统机制在Service挂掉后自动拉活。
19、View.inflater过程与layoutinflater
https://blog.csdn.net/chenliguan/article/details/82314122
20、pending intent
a、对intent的封装,不是立即执行某个行为,而是满足某些条件或某些事件后执行。
21、文件锁的 核心和原理(跨进程的文件同步操作)
A、根本原理:依靠系统内核做了统一的资源入口控制
B、首先内核中有个系统进程表,跟系统文件表,进程表中含有各个进程表项,系统文件表中含有各个文件表项,进程表项中每个fd描述符都对应一个文件表项指针。当一个进程中的存在某个fd描述符对应的文件表项指向某个文件表项时,文件表项会被加上一个排他锁,当其他进程尝试获取时会使进程阻塞。
C、跨文件同步操作:a、文件锁 b、创建一个中间server专门进程文件读写操作,其他读写进程专门与该server进程进行通信。
c、CAS的基本思想
22、Android 属性动画
一、初识;
a、属性动画可以对任意对象的属性进行动画不仅仅是View。默认时间间隔300ms,默认帧率10ms/帧。
b、常用动画类:valueAnimator、objectAnimator、AnimatorSet
23、视频浮窗的实现
