Android 面试题

1 说说JVM垃圾回收机制。

http://blog.csdn.net/xiajian2010/article/details/17376453

http://www.jianshu.com/p/8fa373ceb552?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io

http://www.blogjava.net/fancydeepin/archive/2013/09/29/jvm_heep.html

Android 中的Dalvik和ART是什么,有啥区别?

http://www.jianshu.com/p/58f817d176b7

Dalvik VM 和JVM的区别

https://www.zhihu.com/question/20207106

http://gudong.name/2017/04/14/jvm_vs_dalvik.html

2 Activity的启动模式 

http://droidyue.com/blog/2015/08/16/dive-into-android-activity-launchmode/index.html

http://blog.csdn.net/zhangjg_blog/article/details/10923643

3 service和线程的关系  怎么让一个service不死掉,一直运行,service生命周期 service和Intentservice的区别

Service设置成START_STICKY,kill 后会被重启(等待5秒左右),重传Intent,保持与重启前一样

通过 startForeground将进程设置为前台进程,做前台服务,优先级和前台应用一个级别,除非在系统内存非常缺,否则此进程不会被 kill

双进程Service:让2个进程互相保护,其中一个Service被清理后,另外没被清理的进程可以立即重启进程

QQ黑科技:在应用退到后台后,另起一个只有 1 像素的页面停留在桌面上,让自己保持前台状态,保护自己不被后台清理工具杀死

在已经root的设备下,修改相应的权限文件,将App伪装成系统级的应用(Android4.0系列的一个漏洞,已经确认可行)

Android系统中当前进程(Process)fork出来的子进程,被系统认为是两个不同的进程。当父进程被杀死的时候,子进程仍然可以存活,并不受影响。鉴于目前提到的在Android-Service层做双守护都会失败,我们可以fork出c进程,多进程守护。死循环在那检查是否还存在,具体的思路如下(Android5.0以下可行)

用C编写守护进程(即子进程),守护进程做的事情就是循环检查目标进程是否存在,不存在则启动它。

在NDK环境中将1中编写的C代码编译打包成可执行文件(BUILD_EXECUTABLE)。

主进程启动时将守护进程放入私有目录下,赋予可执行权限,启动它即可。

联系厂商,加入白名单

Service两种启动方式的区别

http://www.jianshu.com/p/2fb6eb14fdec

IntentService有以下特点:

(1)  它创建了一个独立的工作线程来处理所有的通过onStartCommand()传递给服务的intents。

(2)  创建了一个工作队列,来逐个发送intent给onHandleIntent()。

(3)  不需要主动调用stopSelft()来结束服务。因为,在所有的intent被处理完后,系统会自动关闭服务。

(4)  默认实现的onBind()返回null

(5)  默认实现的onStartCommand()的目的是将intent插入到工作队列中 

4 Activity生命周期

http://peiquan.blog.51cto.com/7518552/1277373

http://blog.csdn.net/johnsonblog/article/details/7838108

5 handler AsyncTask可能导致内存泄漏 context可能导致的内存泄露

http://droidyue.com/blog/2015/04/12/avoid-memory-leaks-on-context-in-android/index.html

http://droidyue.com/blog/2014/11/08/bad-smell-of-asynctask-in-android/

http://droidyue.com/blog/2014/12/28/in-android-handler-classes-should-be-static-or-leaks-might-occur/

http://gold.xitu.io/entry/56d64b9e816dfa005943a55c

Handler Message obtain()对象池原理

https://www.jianshu.com/p/e271ee639b68

6 自定义view 

http://blog.csdn.net/guolin_blog/article/details/12921889

自定义view四个构造函数详解

http://blog.csdn.net/zhao123h/article/details/52210732

7 设计模式 

8 工作中遇到一次最大困难时什么  你最后是怎么解决的    如果让你再来一次你是否能够解决的更好

9 listview里面的item怎么优化,如果item的layout不同你要怎么优化  listview 多type 复用 convertview 的解决方法

http://www.eoeandroid.com/thread-246995-1-1.html?_dsign=8fb6add2

10 职业规划

11 JAVA 中堆和栈的区别

http://droidyue.com/blog/2014/12/07/differences-between-stack-and-heap-in-java/index.html

12 HandlerThread

http://blog.csdn.net/feiduclear_up/article/details/46840523

13 缓存Cache

http://blog.csdn.net/guolin_blog/article/details/28863651

14 Touch事件传递机制

http://www.open-open.com/lib/view/open1422428386548.html

15 解决屏幕适配

http://blog.csdn.net/lmj623565791/article/details/49990941

16 handler Asynctask内部原理分析

http://blog.csdn.net/lmj623565791/article/details/38377229

http://blog.csdn.net/lmj623565791/article/details/38614699

17 动画

http://blog.csdn.net/guolin_blog/article/details/43536355

18.recyclerView 和 listview 的区别

RecyclerView的ViewHolder规范化

RecyclerView可以实现线性布局效果,网格布局效果,瀑布流布局效果

ListView具有setEmptyView() addHeaderView() addFooterView()

http://blog.csdn.net/lmj623565791/article/details/51854533

RecyclerView支持局部刷新

listview实现局部刷新https://juejin.im/entry/581bdee6570c35006094a30e

RecyclerView轻松实现item动画效果

RecyclerView没有setOnItemClickListener() setOnItemLongClickListener() 而是实现了RecyclerView.OnItemTouchListener()

http://www.voidcn.com/blog/liaoinstan/article/p-5785579.html

RecyclerView自定义分割线

19.View的绘制流程

    从ViewRoot的performTraversals()方法开始依次调用perfromMeasure、performLayout和performDraw这三个方法。这三个方法分别完成顶级View的measure、layout和draw三大流程,其中perfromMeasure会调用measure,measure又会调用onMeasure,在onMeasure方法中则会对所有子元素进行measure,这个时候measure流程就从父容器传递到子元素中了,这样就完成了一次measure过程,接着子元素会重复父容器的measure,如此反复就完成了整个View树的遍历.

    同理,performLayout和performDraw也分别完成perfromMeasure类似的流程。通过这三大流程,分别遍历整棵View树,就实现了Measure,Layout,Draw这一过程,View就绘制出来了。

AsyncTask

1、设置当前AsyncTask的状态为RUNNING,上面的switch也可以看出,每个异步任务在完成前只能执行一次。

2、执行了onPreExecute(),当前依然在UI线程,所以我们可以在其中做一些准备工作。

3、将我们传入的参数赋值给了mWorker.mParams ,mWorker为一个Callable的子类,且在内部的call()方法中,调用了doInBackground(mParams),然后得到的返回值作为postResult的参数进行执行;postResult中通过sHandler发送消息,最终sHandler的handleMessage中完成onPostExecute的调用。

4、exec.execute(mFuture),mFuture为真正的执行任务的单元,将mWorker进行封装,然后由sDefaultExecutor交给线程池进行执行。

如果现在大家去面试,被问到AsyncTask的缺陷,可以分为两个部分说,在3.0以前,最大支持128个线程的并发,10个任务的等待。在3.0以后,无论有多少任务,都会在其内部单线程执行;

Handler源码分析总结

1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。

2、Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回msg.target.dispatchMessage(msg)方法。

3、Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。

4、Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。

5、在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。

webView

Android webView优化

https://mp.weixin.qq.com/s?__biz=MjM5NjQ5MTI5OA==&mid=2651746383&idx=2&sn=9b8f8ec2adf7c13934bfb9891eae4d81&chksm=bd12a9028a652014ab8b89ff996cf7b53e8d40bfbcd64725c7c82df72515669fcf5267272ccf&scene=0&key=8652b956ca1971a40ad6b41493d96b1dec8f3b81a9dc906f9c847f4096f53793bf38273a695ff893f30d3fc5eae8409e0ed72b4fb4de3469ba0f52f101d17460a7f899a398cd880b515f2fea36a1ae19&ascene=0&uin=ODE4NjgzNjgw&devicetype=iMac+MacBookPro12%2C1+OSX+OSX+10.12.1+build(16B2555)&version=12020510&nettype=WIFI&fontScale=100&pass_ticket=UYjezO5sOIUhdToTt7sxrHDotjZd3okvLWNljbwnQR7zFq3dGtrbuuXIzLM5LKTr

Android webView与js的交互

http://droidyue.com/blog/2014/09/20/interaction-between-java-and-javascript-in-android/index.html

Android性能优化

布局优化、绘制优化、内存泄露优化、响应速度优化、ListView优化、线程优化以及一些性能优化的建议。

布局优化:尽量减少布局文件的层级,删除布局中无用的控件和层级。合理利用这几大布局,包括Constraintlayout, 提供按需加载的功能

绘制优化:onDraw()方法中不要创建新的局部对象,不要做耗时的任务 GPU过度绘制 HierarchyView来检测 开发者选项 显示开发者过度绘制选项

内存泄露优化:context、handler、bitmap、单例模式、内部类、静态变量、资源对象没有关闭

Apk包大小的优化 : webp,tinypng 开启资源压缩,自动删除无用的资源,代码混淆

图片大小的优化 : 对图片针对屏幕的尺寸做相应的压缩处理

响应速度优化和ANR日志分析:避免在主线程中做耗时操作,系统会在/data/anr目录下创建一个文件traces.txt

线程优化 : 

避免创建过多的对象

不要过多使用枚举,枚举占用的内存空间要比整型大

常量请使用static final 来修饰

使用一些Android特有的数据结构,比如SparseArray和Pair等,他们都具有更好的性能

适当使用软引用和弱引用

采用内存缓存和磁盘缓存

尽量采用静态内部类,这样可以避免潜在的由于内部类而导致的内存泄露

https://academy.realm.io/cn/posts/droidcon-farber-improving-android-app-performance/

http://www.jianshu.com/p/be05874965d4

https://mp.weixin.qq.com/s/SmW2ljasKSXC1zlwTLY-iQ

简单参考:主要是怎么来通过tools来进行性能优化

http://blog.csdn.net/yanbober/article/details/48394201

ViewStub 和 merge 的区别

在动态加载布局时,使用 ViewStub 的性能要比使用设置 View 的可见性高。因为虽然把 View 的初始可见 View.GONE,使其不可见,但是在 Inflate 布局的时候 View 仍然会被 Inflate,也就是说仍然会创建对象,会被实例化,会被设置属性。也就是说,会耗费内存等资源。

内存泄露检测框架-leakcanary原理分析

https://juejin.im/entry/5928f6360ce463006b120c3c

自定义BaseAdapter

http://blog.csdn.net/lmj623565791/article/details/38902805

RelativeLayout和LinearLayout性能分析

http://www.jianshu.com/p/8a7d059da746

1.RelativeLayout会让子View调用2次onMeasure,LinearLayout 在有weight时,也会调用子View2次onMeasure

2.RelativeLayout的子View如果高度和RelativeLayout不同,则会引发效率问题,当子View很复杂时,这个问题会更加严重。如果可以,尽量使用padding代替margin。

3.在不影响层级深度的情况下,使用LinearLayout和FrameLayout而不是RelativeLayout。

为什么Google给开发者默认新建了个RelativeLayout,而自己却在DecorView中用了个LinearLayout。因为DecorView的层级深度是已知而且固定的,上面一个标题栏,下面一个内容栏。采用RelativeLayout并不会降低层级深度,所以此时在根节点上用LinearLayout是效率最高的。而之所以给开发者默认新建了个RelativeLayout是希望开发者能采用尽量少的View层级来表达布局以实现性能最优,因为复杂的View嵌套对性能的影响会更大一些。

19.MVP模式讲解

http://blog.csdn.net/lmj623565791/article/details/46596109

20.多进程通信方法,Binder实现机制

android onSaveInstanceState方法

http://blog.sina.com.cn/s/blog_618199e60101g1k5.html

hashcode() 和 equals() 

http://www.cnblogs.com/skywang12345/p/3324958.html

Android中为啥会65535的限制,解释下原因.

http://blog.csdn.net/u011733020/article/details/71481395

横竖屏切换 Activity生命周期的变化

1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次

2、设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次

3、设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法

Retrofit、Glide、okHttp源码分析

Retrofit

http://www.jianshu.com/p/45cb536be2f4

https://mp.weixin.qq.com/s?__biz=MzIwMzYwMTk1NA==&mid=2247485679&idx=1&sn=cdf5785ae5a63af9b7eec9f068ea4b96&chksm=96cda9a2a1ba20b4f91db6985c24696ec1ad710f06d4d9692e35cec25caf19b2c1bbc76111e6&scene=0&key=31a3a388ed6fa873510429955b564e37579e60b77f2fdd98e765085401d84f3534cb1c4bf0da1da6fd44c60424f647adc8e566fcd1db9461e5a7dd7d8452b6e3dd7d85399f26e5d2d86854d51b74c117&ascene=0&uin=ODE4NjgzNjgw&devicetype=iMac+MacBookPro12%2C1+OSX+OSX+10.12.1+build(16B2555)&version=12020510&nettype=WIFI&fontScale=100&pass_ticket=FIP8laSErajzhVZpQmcOgKDoY4MXjh5XMwvJICLE7vZDkXiofAb6S%2BVDyt47Z4nZ

Retrofit.build()

    new OkHttpClient()

    create callbackExecutor(include main thread handler)

    create CallAdapterFactory List

        创建默认的defaultCallAdapterFactory(callbackExecutor)

    create ConverterFactory List

    new Retrofit

Retrofit.create() 使用动态代理

    create ServiceMethod使用缓存来获取ServiceMethod

        create CallAdapter ExecutorCallAdapterFactory

        create responseConverter

        parseMethodAnnotation

    new OkHttpCall()

    adapter(okHttpCall)

ExecutorCallbackCall(Call<>) callAdapter.adapter(OkHttpCall<>)

ExecutorCallbackCall.equeue(new Callback<>)

    okHttpCall.equeue(new Callback){

        handler.post(new Runnable(){

            callback.onResponse

        })

    }

requestConvertor

okhttp3.Request = okhttpCall.toRequest()

responseConvertor

Retrofit.Response = okhttpcall.toResponse()

Observable<> callAdapter.adapter(OkHttpCall<>)

Okhttp 和volley的比较

volley底层用的是httpclient 跟 HttpUrlConnection OkHttp底层用的是socket

volley不支持同步,不能post大数据,不适合用来上传文件,volley内部有一个开启一个CacheDispatcher和4个默认的NetworkDispatcher 如果一个request需要很耗时的话  适合小的请求

okhttp支持同步,异步请求,实现了spdy http2  wesocket协议 http协议缓存 实现了NIO (估计有些读者不理解 IO 和 NIO 的概念,这里姑且简单提下,这两个都是 Java 中的概念,如果我从硬盘读取数据,第一种方式就是程序一直等,数据读完后才能继续操作,这种是最简单的也叫阻塞式 IO,还有一种就是你读你的,我程序接着往下执行,等数据处理完你再来通知我,然后再处理回调。而第二种就是 NIO 的方式,非阻塞式。 )  

okhttp 虽然不是google开发的 但是已经默认作为Android的请求方式了

- 支持 SPDY ,共享同一个Socket来处理同一个服务器的所有请求,socket自动选择最好路线,并支持自动重连,拥有自动维护的socket连接池,减少握手次数 - 拥有队列线程池,轻松写并发 - 如果SPDY不可用,则通过连接池来减少请求延时 - 拥有Interceptors轻松处理请求与响应(比如透明GZIP压缩,LOGGING),无缝的支持GZIP来减少数据流量 - 基于Headers的缓存策略,缓存响应数据来减少重复的网络请求 -会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP。OkHttp还处理了代理服务器问题和SSL握手失败问题。 -使用 OkHttp 无需重写您程序中的网络代码。OkHttp实现了几乎和java.net.HttpURLConnection一样的API。如果您用了 Apache HttpClient,则OkHttp也提供了一个对应的okhttp-apache 模块

Glide :http://blog.csdn.net/guolin_blog/article/details/53759439

okHttp的工作原理以及缓存机制

https://blog.piasy.com/2016/07/11/Understand-OkHttp/

线程池 Java内存管理 多态

java内存管理 :http://www.cnblogs.com/vamei/archive/2013/04/28/3048353.html

线程池 :http://blog.csdn.net/lift_class/article/details/70216690

多线程通信

https://blog.csdn.net/u011240877/article/details/72863432

多线程经典问题 : 生产消费者模型

https://blog.csdn.net/MONKEY_D_MENG/article/details/6251879


线程安全

进程和线程的关系

Thread和Runnable的区别

http://www.cnblogs.com/yangdy/p/5274455.html

线程死锁

http://blog.csdn.net/abc006250/article/details/8007233

http://blog.csdn.net/ns_code/article/details/17200937

APP架构设计

工作中遇到最难的问题以及解决方案

单例

http://blog.csdn.net/jason0539/article/details/23297037

强引用 软引用 弱引用 虚引用

http://blog.csdn.net/mazhimazh/article/details/19752475

HTTP

http://blog.csdn.net/coder_pig/article/details/46312153

http://www.cnblogs.com/hanyonglu/archive/2012/02/19/2357842.html

HTTP header

http://www.cnblogs.com/nylcy/p/5474613.html

java线程面试题 

http://www.cnblogs.com/dolphin0520/p/3958019.html

http://blog.csdn.net/jackfrued/article/details/44921941

图片处理

http://blog.csdn.net/guolin_blog/article/details/9316683

缓存

http://blog.csdn.net/guolin_blog/article/details/28863651

http://blog.csdn.net/guolin_blog/article/details/9316683

webview

http://www.jianshu.com/p/3c94ae673e2a

Android多渠道打包

http://tech.meituan.com/android-apk-v2-signature-scheme.html

多进程通信

从头到尾总结一下:

1.Touch事件分发中只有两个主角:ViewGroup和View。ViewGroup包含onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent三个相关事件。View包含dispatchTouchEvent、onTouchEvent两个相关事件。其中ViewGroup又继承于View。

2.ViewGroup和View组成了一个树状结构,根节点为Activity内部包含的一个ViwGroup。

3.触摸事件由Action_Down、Action_Move、Aciton_UP组成,其中一次完整的触摸事件中,Down和Up都只有一个,Move有若干个,可以为0个。

4.当Acitivty接收到Touch事件时,将遍历子View进行Down事件的分发。ViewGroup的遍历可以看成是递归的。分发的目的是为了找到真正要处理本次完整触摸事件的View,这个View会在onTouchEvent结果返回true。

5.当某个子View返回true时,会中止Down事件的分发,同时在ViewGroup中记录该子View。接下去的Move和Up事件将由该子View直接进行处理。由于子View是保存在ViewGroup中的,多层ViewGroup的节点结构时,上级ViewGroup保存的会是真实处理事件的View所在的ViewGroup对象:如ViewGroup0-ViewGroup1-TextView的结构中,TextView返回了true,它将被保存在ViewGroup1中,而ViewGroup1也会返回true,被保存在ViewGroup0中。当Move和UP事件来时,会先从ViewGroup0传递至ViewGroup1,再由ViewGroup1传递至TextView。

6.当ViewGroup中所有子View都不捕获Down事件时,将触发ViewGroup自身的onTouch事件。触发的方式是调用super.dispatchTouchEvent函数,即父类View的dispatchTouchEvent方法。在所有子View都不处理的情况下,触发Acitivity的onTouchEvent方法。

7.onInterceptTouchEvent有两个作用:1.拦截Down事件的分发。2.中止Up和Move事件向目标View传递,使得目标View所在的ViewGroup捕获Up和Move事件。

问:Android中为什么主线程不会因为Looper.loop()里的死循环卡死?

答:线程是一段可执行的代码,当可执行代码执行完成后,线程生命周期便终止,线程退出。对于主线程,我们是绝不希望运行一段时间后自己就退出,那么如何保证能一直存活呢?简单做法就是可执行代码是能一直执行下去的,死循环便能保证不会被退出,例如,Binder线程也是采用死循环的方法,通过循环方式不断与Binder驱动进行读写操作,当然并非简单地死循环,无消息时会休眠。真正会卡死主线程的操作是在回调方法中onCreate()、onStart()、onResume等操作时间过长,导致掉帧,甚至发生ANR,Looper.loop()本身不会导致应用卡死。

dispatchTouchEvent源码分析总结

触摸控件(View)首先执行dispatchTouchEvent方法。

在dispatchTouchEvent方法中先执行onTouch方法,后执行onClick方法(onClick方法在onTouchEvent中执行,下面会分析)。

如果控件(View)的onTouch返回false或者mOnTouchListener为null(控件没有设置setOnTouchListener方法)或者控件不是enable的情况下会调运onTouchEvent,dispatchTouchEvent返回值与onTouchEvent返回一样。

如果控件不是enable的设置了onTouch方法也不会执行,只能通过重写控件的onTouchEvent方法处理(上面已经处理分析了),dispatchTouchEvent返回值与onTouchEvent返回一样。

如果控件(View)是enable且onTouch返回true情况下,dispatchTouchEvent直接返回true,不会调用onTouchEvent方法。

Volley源码分析总结

    1. 当一个RequestQueue被成功申请后会开启一个CacheDispatcher和4个默认的NetworkDispatcher。

    2. CacheDispatcher缓存调度器最为第一层缓冲,开始工作后阻塞的从缓存序列mCacheQueue中取得请求;对于已经取消的请求,标记为跳过并结束这个请求;新的或者过期的请求,直接放入mNetworkQueue中由N个NetworkDispatcher进行处理;已获得缓存信息(网络应答)却没有过期的请求,由Request的parseNetworkResponse进行解析,从而确定此应答是否成功。然后将请求和应答交由Delivery分发者进行处理,如果需要更新缓存那么该请求还会被放入mNetworkQueue中。

    3. 将请求Request add到RequestQueue后对于不需要缓存的请求(需要额外设置,默认是需要缓存)直接丢入mNetworkQueue交给N个NetworkDispatcher处理;对于需要缓存的,新的请求加到mCacheQueue中给CacheDispatcher处理;需要缓存,但是缓存列表中已经存在了相同URL的请求,放在mWaitingQueue中做暂时处理,等待之前请求完毕后,再重新添加到mCacheQueue中。

    4. 网络请求调度器NetworkDispatcher作为网络请求真实发生的地方,对消息交给BasicNetwork进行处理,同样的,请求和结果都交由Delivery分发者进行处理。

    5. Delivery分发者实际上已经是对网络请求处理的最后一层了,在Delivery对请求处理之前,Request已经对网络应答进行过解析,此时应答成功与否已经设定;而后Delivery根据请求所获得的应答情况做不同处理;若应答成功,则触发deliverResponse方法,最终会触发开发者为Request设定的Listener;若应答失败,则触发deliverError方法,最终会触发开发者为Request设定的ErrorListener;处理完后,一个Request的生命周期就结束了,Delivery会调用Request的finish操作,将其从mRequestQueue中移除,与此同时,如果等待列表中存在相同

URL的请求,则会将剩余的层级请求全部丢入mCacheQueue交由CacheDispatcher进行处理。

接口抽象类的区别

接口中所有的方法隐含的都是抽象的。而抽象类则可以同时包含抽象和非抽象的方法。

类可以实现很多个接口,但是只能继承一个抽象类

类如果要实现一个接口,它必须要实现接口声明的所有方法。但是,类可以不实现抽象类声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。

抽象类可以在不提供接口方法实现的情况下实现接口。

Java接口中声明的变量默认都是final的。抽象类可以包含非final的变量。

Java接口中的成员函数默认是public的。抽象类的成员函数可以是private,protected或者是public。

接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化,但是,如果它包含main方法的话是可以被调用的。

16.什么是死锁(deadlock)?

两个进程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是两个进程都陷入了无限的等待中。

17.如何确保N个线程可以访问N个资源同时又不导致死锁?

使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。

Array和ArrayList的不同点:

Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。

Array大小是固定的,ArrayList的大小是动态变化的。

ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。

对于基本类型数据,集合使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数据类型的时候,这种方式相对比较慢。

20.什么是迭代器(Iterator)?

Iterator接口提供了很多对集合元素进行迭代的方法。每一个集合类都包含了可以返回迭代器实例的

迭代方法。迭代器可以在迭代的过程中删除底层集合的元素。

克隆(cloning)或者是序列化(serialization)的语义和含义是跟具体的实现相关的。因此,应该由集合类的具体实现来决定如何被克隆或者是序列化。

21.Iterator和ListIterator的区别是什么?

下面列出了他们的区别:

Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。

Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。

ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。

Comparable和Comparator接口是干什么的?列出它们的区别。

Java提供了只包含一个compareTo()方法的Comparable接口。这个方法可以个给两个对象排序。具体来说,它返回负数,0,正数来表明输入对象小于,等于,大于已经存在的对象。

Java提供了包含compare()和equals()两个方法的Comparator接口。compare()方法用来给两个输入参数排序,返回负数,0,正数表明第一个参数是小于,等于,大于第二个参数。equals()方法需要一个对象作为参数,它用来决定输入参数是否和comparator相等。只有当输入参数也是一个comparator并且输入参数和当前comparator的排序结果是相同的时候,这个方法才返回true。

thread runnable

字符串常量池

http://droidyue.com/blog/2014/12/21/string-literal-pool-in-java/index.html

字符串拼接

http://droidyue.com/blog/2014/08/30/java-details-string-concatenation/

并发

volatile的原理

http://www.cnblogs.com/dolphin0520/p/3920373.html

synchronized的原理

http://www.cnblogs.com/paddix/p/5367116.html

https://blog.csdn.net/xiao__gui/article/details/8188833

java.util.concurrent包详解

http://blog.csdn.net/chenfengdejuanlian/article/details/54969339

synchronized与Lock的区别

wait()和sleep()区别

https://www.cnblogs.com/DreamSea/archive/2012/01/16/SleepAndWaitDifferent.html

数据结构与算法

list map set 以及实现类的原理

HashMap 

http://www.cnblogs.com/ITtangtang/p/3948406.html

LinkedList 

http://www.cnblogs.com/ITtangtang/p/3948610.html

ArrayList 

http://www.cnblogs.com/ITtangtang/p/3948555.html

ConcurrentHashMap 

http://www.cnblogs.com/dolphin0520/p/3932905.html

List Map Set 的区别

http://developer.51cto.com/art/201309/410205_all.htm

快速排序 : 

http://www.cnblogs.com/MOBIN/p/4681369.html

publicstaticvoidquickSort(intarr[],int_left,int_right){

       intleft =_left;

       intright =_right;

       inttemp = 0;

       if(left <=right){  //待排序的元素至少有两个的情况

            temp=arr[left]; //待排序的第一个元素作为基准元素

           while(left !=right){  //从左右两边交替扫描,直到left = right

               while(right > left && arr[right] >=temp) 

                     right--;      //从右往左扫描,找到第一个比基准元素小的元素

                  arr[left]=arr[right]; //找到这种元素arr[right]后与arr[left]交换

               while(left < right && arr[left] <=temp)

                     left++;       //从左往右扫描,找到第一个比基准元素大的元素

                  arr[right]=arr[left]; //找到这种元素arr[left]后,与arr[right]交换

            }

            arr[right]=temp;  //基准元素归位

            quickSort(arr,_left,left-1); //对基准元素左边的元素进行递归排序

            quickSort(arr, right+1,_right); //对基准元素右边的进行递归排序

        }       

    }

二分查找:

http://blog.csdn.net/lovesummerforever/article/details/24588989

/** 

     * 二分查找递归实现。 

     * @param srcArray  有序数组 

     * @param start 数组低地址下标 

     * @param end   数组高地址下标 

     * @param key  查找元素 

     * @return 查找元素不存在返回-1 

     */  

    public static int binSearch(int srcArray[], int start, int end, int key) {  

        int mid = (end - start) / 2 + start;  


\      if (srcArray[mid] == key) {  

            return mid;  

        }  

        if (start >= end) {  

            return -1;  

        } else if (key > srcArray[mid]) {  

            return binSearch(srcArray, mid + 1, end, key);  

        } else if (key < srcArray[mid]) {  

            return binSearch(srcArray, start, mid - 1, key);  

        }  

        return -1;  

    }  

数组去重:

http://www.gjnote.com/archives/459.html

自己实现一个Stack 实现单链表 数的深度遍历 广度遍历

面经

https://mp.weixin.qq.com/s?__biz=MzI2OTQxMTM4OQ==&mid=2247485000&idx=1&sn=2d74c597c62c9c4229f79cce9587b6bf&chksm=eae1f31add967a0cddf98dd3bbf529b50420bbf7a9cb6b238e6e6fe993c8bd8ba5cca728e0da#rd

美团面试

http://www.jianshu.com/p/ab4d0c6e9481

国内一线互联网公司内部面试题库

https://github.com/JackyAndroid/AndroidInterview-Q-A/blob/master/README-CN.md#%E6%8E%A5%E5%8F%A3%E7%9A%84%E6%84%8F%E4%B9%89-%E7%99%BE%E5%BA%A6

美团面试:

猫扑素数;1到n,求1的个数;单词反转

算法实现下如何统计出Activity中view树的深度。

public int findDeep1(BiTree root)  

  {  


      if(root == null)  

      {  

          return 0;  

      }  

      else  

      {  

       int lchilddeep = findDeep1(root.left);//求左子树的深度  

       int rchilddeep = findDeep1(root.right);//求右子树的深度  

       return lchilddeep > rchilddeep ? lchilddeep + 1 : rchilddeep + 1;//左子树和右子树深度较大的那个加一等于整个树的深度  

      }  

  } 

java内存优化方案

释放连接

优化逻辑,释放不必要的对象 尽量使用局部变量

减少循环逻辑里的对象的创建

基本类型代替对象类型

使用stringBuffer和stringBuilder替代多次String对象  

单线程尽量使用hashmap和ArrayList

提前分配stringBuffer,数组,array,vector等容量

合适的场所使用单例

尽量不要随意使用静态变量

处理内存泄露

HTTP和HTTPS的区别:

1、HTTP协议使用默认80端口,HTTPS协议使用443端口

2、HTTPS协议需要到CA申请证书,一般免费的证书较少,需要交费

3、HTTP信息是明文传输,HTTPS使用具有安全性的SSL加密传输信息

http1和http2的区别:

1.http2可以同时发多个请求

2.http2会压缩,体积小

3.http2服务器会推送

加密算法有哪些?对称加密和非对称加密的区别? 

MD5,SHA1,Base64,RSA,AES,DES 

非对称密钥加密的使用过程:

1. A要向B发送信息,A和B都要产生一对用于加密和解密的公钥和私钥。

2. A的私钥保密,A的公钥告诉B;B的私钥保密,B的公钥告诉A。

3. A要给B发送信息时,A用B的公钥加密信息,因为A知道B的公钥。

4. A将这个消息发给B(已经用B的公钥加密消息)。

5. B收到这个消息后,B用自己的私钥解密A的消息,其他所有收到这个报文的人都无法解密,因为只有B才有B的私钥。

6. 反过来,B向A发送消息也是一样。

(1) 对称加密加密与解密使用的是同样的密钥,所以速度快,但由于需要将密钥在网络传输,所以安全性不高。

(2) 非对称加密使用了一对密钥,公钥与私钥,所以安全性高,但加密与解密速度慢。

(3) 解决的办法是将对称加密的密钥使用非对称加密的公钥进行加密,然后发送出去,接收方使用私钥进行解密得到对称加密的密钥,然后双方可以使用对称加密来进行沟通。

TCP的三次握手?两次行不行?为什么?TCP攻击知道吗?如何进行攻击?

gradle中buildToolsVersion和TargetSdkVersion的区别是什么

http://chinagdg.org/2016/01/picking-your-compilesdkversion-minsdkversion-targetsdkversion/

手机适配一些方案

静态方法是否能被重写

http://xm-king.iteye.com/blog/745787

你可能感兴趣的:(Android 面试题)