笔试面试题

…… 最近笔者在面试的历程中被虐千百遍,其中也学到了很多知识点,和大侠分享下(持续到笔者 确定工作为止)。
此文 仅笔者 一些小小记录。


Q 1、 Java线程中sleep()、wait()、notify()、notifyAll()、suspend、resume()、yield()、join()、interrupt()的用法和区别 。

sleep() 使当前线程进入停滞状态;
wait() 调用后,线程会释放掉它所占有的“锁标志”,从而使线程所在对象中的其它synchronized数据可被别的线程使用。
yield() 只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。
notify() 唤醒在此对象监视器上等待的单个线程。当它被一个notify()方法唤醒时,等待池中的线程就被放到了锁池中。该线程将等待从锁池中获得机锁,然后回到wait()前的中断现场。
notifyAll() 唤醒在此对象监视器上等待的所有线程。
interrupt() 中断线程。需要注意的是,InterruptedException是线程自己从内部抛出的,并不是interrupt()方法抛出的。对某一线程调用interrupt()时,如果该线程正在执行普通的代码,那么该线程根本就不会抛出InterruptedException。但是,一旦该线程进入到wait()/sleep()/join()后,就会立刻抛出InterruptedException。

参考:
   http://zheng12tian.iteye.com/blog/1233638

Q2、ArrayList、LinkedList、Vector、HashSet、Treeset、HashMap、TreeMap的区别和适用场景。

偷个懒,请参考: http://bs-yg.iteye.com/blog/2253605

Q3、 Activity的启动方式

standard
      标准启动模式,也是activity的默认启动模式。在这种模式下启动的activity可以被多次实例化,即在同一个任务中可以存在多个activity的实例,每个实例都会处理一个Intent对象。如果Activity A的启动模式为standard,并且A已经启动,在A中再次启动Activity A,即调用startActivity(new Intent(this,A.class)),会在A的上面再次启动一个A的实例,即当前的桟中的状态为A–>A。
singleTop
      如果一个以singleTop模式启动的activity的实例已经存在于任务桟的桟顶,那么再启动这个Activity时,不会创建新的实例,而是重用位于栈顶的那个实例,并且会调用该实例的onNewIntent()方法将Intent对象传递到这个实例中。举例来说,如果A的启动模式为singleTop,并且A的一个实例已经存在于栈顶中,那么再调用startActivity(new Intent(this,A.class))启动A时,不会再次创建A的实例,而是重用原来的实例,并且调用原来实例的onNewIntent()方法。这是任务桟中还是这有一个A的实例。
如果以singleTop模式启动的activity的一个实例已经存在与任务桟中,但是不在桟顶,那么它的行为和standard模式相同,也会创建多个实例。
singleTask
      谷歌的官方文档上称,如果一个activity的启动模式为singleTask,那么系统总会在一个新任务的最底部(root)启动这个activity,并且被这个activity启动的其他activity会和该activity同时存在于这个新任务中。如果系统中已经存在这样的一个activity则会重用这个实例,并且调用他的onNewIntent()方法。即,这样的一个activity在系统中只会存在一个实例。
singleInstance
      总是在新的任务中开启,并且这个新的任务中有且只有这一个实例,也就是说被该实例启动的其他activity会自动运行于另一个任务中。当再次启动该activity的实例时,会重用已存在的任务和实例。并且会调用这个实例的onNewIntent()方法,将Intent实例传递到该实例中。和singleTask相同,同一时刻在系统中只会存在一个这样的Activity实例。

Q4、 性能优化有哪些方式

布局优化(优化布局结构,优化处理逻辑)
内存优化(使用合适的数据对象,避免不必要的对象对象创建,避免内存泄漏)
其他(集中捕获异常,避免频繁的网络请求,优化业务策略)

参考:
    Android性能调优具体技巧 20+条(干货不止一点点)
    http://hukai.me/android-training-performance-tips/
    Android界面性能调优

更新于(2016.05.11)

Q5、 布局优化

优化布局结构
      - 减少UI布局层级
      - 尽量避免在视图层级的顶层使用相对布局 RelativeLayout 。相对布局 RelativeLayout 比较耗资源,因为一个相对布局 RelativeLayout 需要两次度量来确保自己处理了所有的布局关系,而且这个问题会伴随着视图层级中的相对布局 RelativeLayout 的增多,而变得更严重;
       - 布局层级一样的情况建议使用线性布局 LinearLayout 代替相对布局 RelativeLayout,因为线性布局 LinearLayout 性能要更高一些;确实需要对分支进行相对布局 RelativeLayout 的时候,可以考虑更优化的网格布局 GridLayout ,它已经预处理了分支视图的关系,可以避免两次度量的问题;
       - 相对复杂的布局建议采用相对布局 RelativeLayout ,相对布局 RelativeLayout 可以简单实现线性布局 LinearLayout 嵌套才能实现的布局;
      - 不要使用绝对布局 AbsoluteLayout ;
      - 将可重复使用的组件抽取出来并用 标签进行重用。如果应用多个地方的 UI 用到某个布局,就将其写成一个布局部件,便于各个 UI 重用。
      - 使用 merge 标签减少布局的嵌套层次
      - 去掉多余的不可见背景。有多层背景颜色的布局,只留最上层的对用户可见的颜色即可,其他用户不可见的底层颜色可以去掉,减少无效的绘制操作;
      - 尽量避免使用 layoutweight 属性。使用包含 layoutweight 属性的线性布局 LinearLayout 每一个子组件都需要被测量两次,会消耗过多的系统资源。在使用 ListView 标签与 GridView 标签的时候,这个问题显的尤其重要,因为子组件会重复被创建。平分布局可以使用相对布局 RelativeLayout 里一个 0dp 的 view 做分割线来搞定,如果不行,那就……;

优化处理逻辑
      - 按需载入视图。某些不怎么重用的耗资源视图,可以等到需要的时候再加载,提高UI渲染速度;
      - 使用 ViewStub 标签来加载一些不常用的布局;
      - 尽量避免不必要的耗资源操作,节省宝贵的运算时间;
      - 避免在 UI 线程进行繁重的操作。耗资源的操作(比如 IO 操作、网络操作、SQL 操作、列表刷新等)耗资源的操作应用后台进程去实现,不能占用 UI 线程,UI 线程是主线程,主线程是保持程序流畅的关键,应该只操作那些核心的 UI 操作,比如处理视图的属性和绘制;
      - 最小化唤醒机制。我们常用广播来接收那些期望响应的消息和事件,但过多的响应超过本身需求的话,会消耗多余的 Android 设备性能和资源。所以应该最小化唤醒机制,当应用不关心这些消失和事件时,就关闭广播,并慎重选择那些要响应的 Intent 。

检测工具
      - Hierarchy View:Hierarchy View 在Android SDK里自带,常用来查看界面的视图结构是否过于复杂,用于了解哪些视图过度绘制,又该如何进行改进。
      - Lint:Lint 是 ADT 自带的静态代码扫描工具,可以给 XML 布局文件和 项目代码中不合理的或存在风险的模块提出改善性建议。
      - Systrace:Systrace 在Android DDMS 里自带,可以用来跟踪 graphics 、view 和 window 的信息,发现一些深层次的问题。很麻烦,限制大,实际调试中我基本用不到。
      - Tracker:Track 在 Android DDMS里自带,是个很棒的用来跟踪构造视图的时候哪些方法费时,精确到每一个函数,无论是应用函数还是系统函数,我们可以很容易地看到掉帧的地方以及那一帧所有函数的调用情况,找出问题点进行优化。
      - OverDraw:通过在 Android 设备的设置 APP 的开发者选项里打开 “ 调试 GPU 过度绘制 ” ,来查看应用所有界面及分支界面下的过度绘制情况,方便进行优化。
      - GPU 呈现模式分析:通过在 Android 设备的设置 APP 的开发者选项里启动 “ GPU 呈现模式分析 ” ,可以得到最近 128 帧 每一帧渲染的时间,分析性能渲染的性能及性能瓶颈。
      - StrictMode:通过在 Android 设备的设置 APP 的开发者选项里启动 “ 严格模式 ” ,来查看应用哪些操作在主线程上执行时间过长。当一些操作违背了严格模式时屏幕的四周边界会闪烁红色,同时输出 StrictMode 的相关信息到 LOGCAT 日志中。
      - Animator duration scale:通过在 Android 设备的设置 APP 的开发者选项里打开 “ 窗口动画缩放 ” / “ 过渡动画缩放 ” / “ 动画程序时长缩放 ”,来加速或减慢动画的时间,以查看加速或减慢状态下的动画是否会有问题。
      - Show hardware layer updates:通过在 Android 设备的设置 APP 的开发者选项里启动 “ 显示硬件层更新 ”,当 Flash 硬件层在进行更新时会显示为绿色。使用这个工具可以让你查看在动画期间哪些不期望更新的布局有更新,方便你进行优化,以获得应用更好的性能。

Q6、 自定义控件必要掌握点有哪些?

invalidate():当view的某些内容发生变化的时候,需要调用invalidate来通知系统对这个view进行redraw ;
requestLayout(:当某些元素变化会引起组件大小变化时,需要调用requestLayout方法;
View的三大绘制流程:onMeasure()、onLayout()、onDraw();
手势辅助类:GestureDetector、ViewDragHelper、Scroller:
http://developer.android.com/intl/zh-cn/reference/android/view/GestureDetector.html
http://www.cnblogs.com/sw926/p/3208158.html
http://blog.csdn.net/pi9nc/article/details/39583377
http://blog.csdn.net/gemmem/article/details/7321910
Android中自定义属性的格式详解;
Paint Canvas

参考:
   自定义View——坑、技巧、调优

Q7、 关于架构?

在设计原则基础上,对系统的各个部分组合,形成架构,架构两大元素:各个组件,组件间的关联
出发点:
    稳定性好
   成本最低
   满足用户需求(或未来需求)
   架构足够灵活(方便编译、部署、以及后期维护;方便扩展)
   支持团队多人 并行开发

参考:
   http://keeganlee.me/post/architecture/20160107
   http://mp.weixin.qq.com/s?__biz=MzA3OTIxNTA0MA==&mid=503318806&idx=1&sn=18bc85e341568762621d8682fda982ec#rd
   http://blog.csdn.net/u014651216/article/details/51093411

Q8、 getCacheDir()、getFilesDir()、getExternalFilesDir()、getExternalCacheDir()的作用?

目录
      getCacheDir():/data/data/< application package>/cache目录
      getFilesDir():/data/data/< application package>/files目录
      Context.getExternalFilesDir(): SDCard/Android/data/你的应用的包名/files/ 目录
      Context.getExternalCacheDir():SDCard/Android/data/你的应用包名/cache/目录

生命周期
      应用被卸载后,与该应用相关的数据也清除掉
      带有“Files”与“Cache”的方法内容 对应 设置->应用->应用详情里面的”清除数据“与”清除缓存“选项

其它
   External存储区域有几个好处:
      可以传到电脑上;
      可以与其他app共享;
      在4.4之后的App路径(Android/data/包名)下读写不需任何权限;

   相应的,也有几个缺点:
      可能不可用;
      会被其他应用读到;
      在非App路径下写、修改文件需要权限。

参考:
   Android存储挖坑记
   http://blog.csdn.net/u011494050/article/details/39671159

更新于(2016.05.17)

Q9、 如何在onCreate()中取到View / ViewGroup 的宽高?

  • 监听Draw/Layout事件:ViewTreeObserver 将一个runnable添加到Layout队列中:
  • View.post()
  • 重写View的onLayout方法
  • 重写Activity的onWindowFocusChanged方法,在该方法中获取

Q10、 SharedPreference

SharedPreference: 一种常用的数据存储方式,其本质就是一个xml文件,常用于存储较简单的参数设置。
只能存储boolean,int,float,long和String五种简单的数据类型

保存方法 apply、commit 区别:
      1、apply没有返回值而commit返回boolean表明修改是否提交成功
      2、apply是将修改数据原子提交到内存,而后异步真正提交到硬件磁盘;而commit是同步的提交到硬件磁盘,因此,在多个并发的提交commit的时候,他们会等待正在处理的commit保存到磁盘后在操作,从而降低了效率。而apply只是原子的提交到内容,后面有调用apply的函数的将会直接覆盖前面的内存数据,这样从一定程度上提高了很多效率。
      3、apply方法不会提示任何失败的提示。
综合上述,由于在一个进程中,sharedPreference是单实例,一般不会出现并发冲突,如果对提交的结果不关心的话,建议使用apply,当然需要确保提交成功且有后续操作的话,还是需要用commit的。
      4、commit将同步的将数据写到preferences;apply立即更改内存中的SharedPreferences,但是开始异步提交到磁盘中。保存失败你也不会得到任何提示信息;
       5、commit 是同步的,会阻塞线程。

OnSharedPreferenceChangeListener
   用途 - 用于监视Shared Preference的变化,用户在设置应用显示、个人偏好等保存在SharedPreference的值之后,

参考:
   SharedPreferences API
   OnSharedPreferenceChangeListener使用说明
   SharedPreferences数据的两种保存方法: apply、commit

Q11、 屏幕适配

布局
   1、相应的 layout 资源目录(分为 layout 默认layout-land 横屏layout-large大屏幕竖屏layout-large-land 大屏幕横屏
   2、百分比布局 (API 地址

图片
   1、文件放入相应的drawable资源目录
   2、采用 .9 图片
   3、采用矢量图

长度单位
    1、dimen.xml文件放入相应的 values 资源目录

更新于(2016.05.19)

Q12、 多线程并发中的单例处理

内部类加载方法:能延迟化加载、多线程安全
    class Foo {
private static class HelperHolder {
public static final MyApplication helper = new MyApplication();
}
public static MyApplication getHelper() {
return HelperHolder.helper;
}
}

参考: 单例模式(懒)写法整理

多线程

好处?
       在多线程程序中,多个线程被并发的执行以提高程序的效率,CPU不会因为某个线程需要等待资源而进入空闲状态。多个线程共享堆内存(heap memory),因此创建多个线程去执行一些任务会比创建多个进程更好。

如何确保线程安全?
      同步,使用原子类(atomic concurrent classes),实现并发锁 synchronized,使用volatile关键字,使用不变类和线程安全类。

参考:
    http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-answers/
   Java多线程和并发性知识点总结

Q13、 Service

用途:它主要用于在后台处理一些耗时的逻辑,或者去执行某些需要长期运行的任务。必要的时候我们甚至可以在程序退出的情况下,让Service在后台继续保持运行状态。

运行在主线程中。
(因为Activity很难对Thread进行控制,当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例。而且在一个Activity中创建的子线程,另一个Activity无法对其进行操作。但是Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。)

生命周期:
   (1)、被启动的服务的生命周期:如果一个Service被某个Activity 调用 Context.startService 方法启动,那么不管是否有Activity使用bindService绑定或unbindService解除绑定到该Service,该Service都在后台运行。如果一个Service被startService 方法多次启动,那么onCreate方法只会调用一次,onStart将会被调用多次(对应调用startService的次数),并且系统只会创建Service的一个实例(因此你应该知道只需要一次stopService调用)。该Service将会一直在后台运行,而不管对应程序的Activity是否在运行,直到被调用stopService,或自身的stopSelf方法。当然如果系统资源不足,android系统也可能结束服务。
   (2)、 被绑定的服务的生命周期:如果一个Service被某个Activity 调用 Context.bindService 方法绑定启动,不管调用 bindService 调用几次,onCreate方法都只会调用一次,同时onStart方法始终不会被调用。当连接建立之后,Service将会一直运行,除非调用Context.unbindService 断开连接或者之前调用bindService 的 Context 不存在了(如Activity被finish的时候),系统将会自动停止Service,对应onDestroy将被调用。
   (3)、 被启动又被绑定的服务的生命周期:如果一个Service又被启动又被绑定,则该Service将会一直在后台运行。并且不管如何调用,onCreate始终只会调用一次,对应startService调用多少次,Service的onStart便会调用多少次。调用unbindService将不会停止Service,而必须调用 stopService 或 Service的 stopSelf 来停止服务。
   (4)、当服务被停止时清除服务:当一个Service被终止(1、调用stopService;2、调用stopSelf;3、不再有绑定的连接(没有被启动))时,onDestroy方法将会被调用,在这里你应当做一些清除工作,如停止在Service中创建并运行的线程。

按运行类型分类:
   (1)、前台Service:表现 类似于天气,会有一个通知栏显示, 前台Service优先级比较高 可以一直保持运行状态,而不会由于系统内存不足的原因导致被回收;
   (2)、后台Service: Service的系统优先级还是比较低的,当系统出现内存不足情况时,就有可能会回收掉正在后台运行的Service;
   (3)、远程Service:本质是跨进程的service。

两种工作状态:
   1、启动状态:主要用于执行后台计算;
   2、绑定状态:主要用于其他组件与Service的交互。

参考:
   Android Service完全解析,关于服务你所需知道的一切
    Android 中的 Service 全面总结

Q14、 Android 通信机制

Q15、 Http

get 和 post 区别?
      GET 提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连,如EditPosts.aspx?name=test1&id=123456。POST 方法是把提交的数据放在HTTP包的Body中。
      GET 提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制.
     GET 方式需要使用Request.QueryString 来取得变量的值,而POST方式通过Request.Form来获取变量的值。
      GET 方式提交数据,会带来安全问题,比如一个登录页面,通过GET方式提交数据时,用户名和密码将出现在URL上,如果页面可以被缓存或者其他人可以访问这台机器,就可以从历史记录获得该用户的账号和密码.

Q16、 基本数据类型

类型名称类型定义类型取值
boolean布尔值,作二元判断true, false
byte8位有符号整数最小值-2^7,最大值2^7-1
short16位有符号整数最小值-2^15,最大值 2^15 - 1
int32位有符号整数最小值(-2^31),最大值(2^31-1)
long64位有符号整数-2^63~(2^63-1)
float32位浮点数1.4E-45~3.4028235E38
double64位浮点数4.9E-324~1.7976931348623157E308
char16位Unicode字符不适用

参考:Java/数据类型

Q17、 敏捷开发核心思想

Q18、 OOP

概述:
      面向对象程序设计(英语:Object-oriented programming,缩写:OOP)是种具有对象概念的程序编程范型,同时也是一种程序开发的方法。它可能包含数据、属性、代码与方法。对象则指的是类的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性,对象里的程序可以访问及经常修改对象相关连的数据。在面向对象程序编程里,计算机程序会被设计成彼此相关的对象。

好处:
       通过封装、继承、多态把程序的耦合度降低,配合设计模式以提高软件的重用性、灵活性和扩展性。

参考:
      面向对象程序设计

Q19、设计模式

更新于(2016.05.22)


附上 JNI开发(1)——概述、环境搭建、必要知识点 该博文评论内承诺过的 笔者真相 ~~~
这里写图片描述

推荐:

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值