Android笔试面试题整理

来源:互联网 发布:java运行jar包命令 编辑:程序博客网 时间:2024/06/05 15:39

Android笔试面试题

一、java基础篇

1)类初始化的顺序,静态块与构造函数的调用顺序

一个类的实例化过程:
1,首先会执行类中static代码块(不管代码块是否在类的开头还是末尾处),如果这个类有父类,同样会优先查找父类中的static代码块,然后是当前类的static。

2,然后会从父类的第一行开始执行,直至代码末尾处,中间不管是有赋值还是method调用,都会按顺序一一执行(method),普通代码块{ }…

3,其次才是父类的构造函数,执行带参数或不带参数的构造函数,依赖于实例化的类的构造函数有没有super父类的带参或不带参的构造函数,上边试验二三已经证明。

4,然后会从子类(当前类)的第一行开始执行,直至代码末尾处,中间不管是有赋值还是method调用,都会按顺序一一执行(method),普通代码块{ }…

5,其次会是子类(当前类)的构造函数,按顺序执行。

6,最后是类方法的调用执行,如果子类覆盖了父类的method,执行时会先执行子类覆盖的method,method内如果有super.method(),才会调用父类的同名method,否则不会。

2)HashMap和HashTable的区别?

  • 父类不同
  • HashTable是线程安全的
  • HashMap可以有存入空置
  • 另外有一个concurrentHashMap跟HashTable效果差不多

ArrayList和LinkedList的区别:
- 前者基于动态数组,后者基于链表
- 在查找的时候,前者的效率要高,因为要移动指针;
- 在插入和删除的时候,后者的效率要高,因为要移动数据。

3)StringBuffer、StringBuider、String的区别?

  • 使用字符数组保存字符串
  • String加入了“final”关键字,不可变,其他的两种都继承自AbstractStringBuilder,是可变的
  • StringBuffer是多线程,是线程安全的,StringBuider是非线程安全的
  • 如果不是多线程,StringBuider的效率高于StringBuffer。

4)线程同步有几种方式?

  • 同步方法
  • 同步代码块
  • 特殊域变量,加入Volatile
  • 使用重入锁实现线程同步
  • 使用局部变量实现线程同步

5)ThreadLocal
加入变量副本

6)ThreadLocal与同步机制

  • ThreadLocal与同步机制都是为了解决多线程中相同变量的访问冲突问题
  • 前者采用以”空间换时间”的方法,后者采用以”时间换空间”的方式

7)线程有多少种状态?各种状态之间怎么切换?

  • 新建、等待、就绪、运行、阻塞、死亡。

8)线程锁有几种?
1、自旋锁

2、自旋锁的其他种类

3、阻塞锁

4、可重入锁

5、读写锁

6、互斥锁

7、悲观锁

8、乐观锁

9、公平锁

10、非公平锁

11、偏向锁

12、对象锁

13、线程锁

14、锁粗化

15、轻量级锁

16、锁消除

17、锁膨胀

18、信号量

9)override和overload的区别
override是重写:主要是继承父类或者实现接口时重写方法
overload是重载,根据参数的不同,选择不同的方法。

10)处理hash冲突的方法:
开放地址法
拉链法
再散列
建立一个公共溢出区

二、android

1)Handler、AsyncTask的原理及其区别?

原理:

1、线程间通信机制
首先,looper、handler、messagequeue三者共同实现了android系统里线程间通信机制。如在A、B两个子线程之间需要传递消息,首先给每个子线程绑定一套handler、looper、messagequeue机制,然后这三个对象都与其所属线程对应。然后A线程通过调用B线程的Handler对象,发送消息。这个消息会被Handler发送到B线程的messagequeue中,而属于B线程的Looper对象一直在for循环里无限遍历MessageQueue, 一旦发现该消息队列里收到了新的消息,就会去对消息进行处理,处理过程中会回调自身Handler的heandleMessage方法。从而实现了不同线程间通信。

2、Looper实现原理
Looper类里包含一个消息队列对象和一个线程对象。当创建Looper时,会自动创建一个消息队列,同时将内部线程对象指向创建Looper的线程。当开启Looper后(looper.loop()),会自动进入无限for循环中,不断去遍历消息队列,如果没有消息则阻塞,有消息则回调handler的handlemessage方法进行处理。

3、Looper.prepare()
首先,要使用Looper机制一般会在当前线程中创建Handler对象,里面会自动创建一个looper对象和消息队列,这里面的消息队列属于当前线程空间。但此时的looper还不会去遍历,也没有绑定到当前线程。其中,looper对象内部也包含一个空消息队列对象和空线程。通过Looper.prepare()方法,先让该消息队列指向当前线程的消息队列,让空线程也指向当前线程。从而实现了绑定。

缺陷:AsyncTask中维护着一个长度为128的线程池,同时可以执行5个工作线程,还有一个缓冲队列,当线程池中已有128个线程,缓冲队列已满时,如果
此时向线程提交任务,将会抛出RejectedExecutionException。
解决:由一个控制线程来处理AsyncTask的调用判断线程池是否满了,如果满了则线程睡眠否则请求AsyncTask继续处理。

为了正确的使用AsyncTask类,以下是几条必须遵守的准则:

1) Task的实例必须在UI thread中创建

2) execute方法必须在UI thread中调用

3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params…), onProgressUpdate(Progress…)这几个方法

4) 该task只能被执行一次,否则多次调用时将会出现异常

区别:结构清晰,功能明确;代码量较多
简单快捷,过程可控,本质是一个线程池;大量新线程,造成资源浪费

2)BroastcastReceiver的两种注册方式?有什么区别?
在xml中的静态注册,始终处于活动状态,用于监听系统的状态,如手机电量,wifi状态,
在java代码中的动态注册,长用户更新ui,在onReceive中更新控件状态

3) 对NDK的理解?

NDK是一系列工具的集合,NDK提供了一系列的工具,帮助开发者迅速的开发C/C++的动态库,并能自动将so和java 应用打成apk包。
NDK集成了交叉编译器,并提供了相应的mk文件和隔离cpu、平台等的差异,开发人员只需简单的修改mk文件就可以创建出so

4) JSON和XML的区别?
json是轻量级,格式简单,简单,快捷,速度较快
xml格式齐全,较为复杂,xml解析:Dom,Sax

5) Activity有几种启动方式?
4种,standard,singleTop,singleTask,singleInstance

6)Android开发怎么进行调试?
使用第三方框架,在浏览器中调试,stetho;
在模拟器上调试,真机上调试

7)横竖屏切换时候Activity的生命周期。
1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
2、设置Activity的android:configChanges=”orientation”时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
3、设置Activity的android:configChanges=”orientation|keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法

8)dvm的进程和Linux的进程, 应用程序的进程是否为同一个概念?
Dvm的进程是dalivk虚拟机进程,每个android程序都运行在自己的进程里面,每个android程序系统都会给他分配一个单独的liunx uid(user id),
每个dvm都是linux里面的一个进程.所以说这两个进程是一个进程.

9)谈谈Android的IPC(进程间通信)机制?

IPC是内部进程通信的简称,是共享”命名管道”的资源。Android中的IPC机制是为了让Activity和Service之间可以随时的进行交互,故在Android中该机制,只适用于Activity和Service之间的通信,类似于远程方法调用,类似于C/S模式的访问。通过定义AIDL接口文件来定义IPC接口。Servier端实现IPC接口,Client端调用IPC接口本地代理。

10)android的内存管理?
内存泄露,内存溢出(OOM)

什么时候会发生内存泄露?内存泄露的根本原因:长生命周期的对象持有短生命周期的对象。短周期对象就无法及时释放。
原因:1,主要是hashmap,Vector等,如果是静态集合没有及时的set null,一直持有对象
2、数据链接没有及时关闭,数据库,contentprovider,io,sokect等
3、在使用监听器的时候,没有remove或者广播没有unregisterrecevier
4、匿名内部类;
5、单例 是一个全局的静态对象,当持有某个复制的类A是,A无法被释放,内存leak。

当程序需要申请一段“大”内存,但是虚拟机没有办法及时的给到,即使做了GC操作以后,这就会抛出 OutOfMemoryException 也就是OOM;

减少内存对象的占用

I.使用更加轻量级的数据结构,比如使用ArrayMap/SparseArray代替hashmap
(处理hash冲突的方法)

II.避在android里面使用Enum

III.减少bitmap的内存占用

inSampleSize:缩放比例,在把图片载入内存之前,我们需要先计算出一个合适的缩放比例,避免不必要的大图载入。
decode format:解码格式,选择ARGB_8888/RBG_565/ARGB_4444/ALPHA_8,存在很大差异。
IV.减少资源图片的大小,过大的图片可以考虑分段加载

内存对象的重复利用

大多数对象的复用,都是利用对象池的技术。

I.listview/gridview/recycleview contentview的复用

II.inBitmap 属性对于内存对象的复用ARGB_8888/RBG_565/ARGB_4444/ALPHA_8

这个方法在某些条件下非常有用,比如要加载上千张图片的时候。

III.避免在ondraw方法里面 new对象

IV.使用StringBuilder 代替+

三、框架

你都用过什么框架:

volley,retrofit/okhttp
1)Lru缓存

2)图片加载

- Universal Image loader
- Picasso
- Fresco
- Glide

3)图片处理

4)网络请求

volley要画出这个图

5)网络解析

6)数据库

7)依赖注入

8)图标

9)后台处理

10)事件总线

EventBus事件总线

11)响应式编程

12)Log框架

13)测试框架

14)调试框架

15)性能优化

0 0
原创粉丝点击