Android开发岗面试之常用面试题

Android面试之常用面试题

最近面试了几家公司,总结出一些面试常问的问题,希望能对大家有所帮助

1.请使用java或者C++实现反转单链表,这里使用的是java,主要是面试中可能会经常碰上该类似操作,尤其是稍大点公司,面试官可能并不在乎你能不能搞定该题,但是这类型题目最是能体现程序员的思维状态。
实现代码:
/** 
 * 定义一个单链表 
 */  
class Node {  
    //变量  
    private int record;  
    //指向下一个对象  
    private Node nextNode;  
  
    public Node(int record) {  
        super();  
        this.record = record;  
    }  
    public int getRecord() {  
        return record;  
    }  
    public void setRecord(int record) {  
        this.record = record;  
    }  
    public Node getNextNode() {  
        return nextNode;  
    }  
    public void setNextNode(Node nextNode) {  
        this.nextNode = nextNode;  
    }  
}  
  
/** 
 * @author luochengcheng 
 *  两种方式实现单链表的反转(递归、普通) 
 *  新手强烈建议旁边拿着纸和笔跟着代码画图(便于理解) 
 */  
public class ReverseSingleList {  
    /**  
     * 递归,在反转当前节点之前先反转后续节点  
     */  
    public static Node reverse(Node head) {  
        if (null == head || null == head.getNextNode()) {  
            return head;  
        }  
        Node reversedHead = reverse(head.getNextNode());  
        head.getNextNode().setNextNode(head);  
        head.setNextNode(null);  
        return reversedHead;  
    }  
  
    /**  
     * 遍历,将当前节点的下一个节点缓存后更改当前节点指针  
     *   
     */  
    public static Node reverse2(Node head) {  
        if (null == head) {  
            return head;  
        }  
        Node pre = head;  
        Node cur = head.getNextNode();  
        Node next;  
        while (null != cur) {  
            next = cur.getNextNode();  
            cur.setNextNode(pre);  
            pre = cur;  
            cur = next;  
        }  
        //将原链表的头节点的下一个节点置为null,再将反转后的头节点赋给head     
        head.setNextNode(null);  
        head = pre;  
          
        return head;  
    }  
  
    public static void main(String[] args) {  
        Node head = new Node(0);  
        Node tmp = null;  
        Node cur = null;  
        // 构造一个长度为10的链表,保存头节点对象head     
        for (int i = 1; i < 10; i++) {  
            tmp = new Node(i);  
            if (1 == i) {  
                head.setNextNode(tmp);  
            } else {  
                cur.setNextNode(tmp);  
            }  
            cur = tmp;  
        }  
        //打印反转前的链表  
        Node h = head;  
        while (null != h) {  
            System.out.print(h.getRecord() + " ");  
            h = h.getNextNode();  
        }  
        //调用反转方法  
        head = reverse2(head);  
        System.out.println("\n**************************");  
        //打印反转后的结果  
        while (null != head) {  
            System.out.print(head.getRecord() + " ");  
            head = head.getNextNode();  
        }  
    }  
}  

2.Error与Exception的区别

Error一般是指恢复不是不可能但是很困难的情况下的一张严重问题,比如内存溢出,不可能是指指望程序能处理这样的情况。
Exception是指程序的设计或实现问题,一般是比较容易恢复的,如果程序运行正常是不会出现在这样的错误的。

3.接口与抽象类的区别
接口是公开的,里面不能有私有的方法或变量,是用于让别人使用的,而抽象类是可以有私有方法或私有变量的,另外,实现接口的一定要实现接口里定义的所有方法,而实现抽象类可以有选择地重写需要用到的方法,一般的应用里,最顶级的是接口,然后是抽象类实现接口,最后才到具体类实现。还有,接口可以实现多重继承,而一个类只能继承一个超类,但可以通过继承多个接口实现多重继承,接口还有标识(里面没有任何方法,如Remote接口)和数据共享(里面的变量全是常量)的作用.

3.Get和Post的区别
1.get是从服务器上获取数据,post是向服务器传送数据;
2.对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.From获取提交的数据。
3.get安全性较低,post安全性较好,但是get的执行效率比post方式要好;
4.get传送的数据量较小,而post传送的数据量较大;

4.Activity的生命周期

相信不少朋友也已经看过这个流程图了,也基本了解了Activity生命周期的几个过程,我们就来说一说这几个过程。

1.启动Activity:系统会先调用onCreate方法,然后调用onStart方法,最后调用onResume,Activity进入运行状态。

2.当前Activity被其他Activity覆盖其上或被锁屏:系统会调用onPause方法,暂停当前Activity的执行。

3.当前Activity由被覆盖状态回到前台或解锁屏:系统会调用onResume方法,再次进入运行状态。

4.当前Activity转到新的Activity界面或按Home键回到主屏,自身退居后台:系统会先调用onPause方法,然后调用onStop方法,进入停滞状态。

5.用户后退回到此Activity:系统会先调用onRestart方法,然后调用onStart方法,最后调用onResume方法,再次进入运行状态。

6.当前Activity处于被覆盖状态或者后台不可见状态,即第2步和第4步,系统内存不足,杀死当前Activity,而后用户退回当前Activity:再次调用onCreate方法、onStart方法、onResume方法,进入运行状态。

7.用户退出当前Activity:系统先调用onPause方法,然后调用onStop方法,最后调用onDestory方法,结束当前Activity。

但是知道这些还不够,我们必须亲自试验一下才能深刻体会,融会贯通。

下面是一张经典的Activity生命周期图


5.简单描述一下你对service的理解

service与activity的地位是并列的,它代表一个单独的安卓组件。service与activity的区别在与:service通常位于后台运行,它一般不需要与用户交互,因此service组件没有图形用户界面。

与activity组件需要继承Activity基类相似,service组件需要继承service基类。一个service组件被运行起来后,它将拥有自己独立的生命周期,service组件通常用于为其他的组件提供后台服务或监控其他组件的运行状态。

6.  handler机制的原理 
  andriod提供了Handler 和 Looper 来满足线程间的通信。Handler先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(MessageExchange)。

  1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的MessageQueue(消息队列)。 

  2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到MessageQueue里;或者接收Looper从Message Queue取出)所送来的消息。

  3) Message Queue(消息队列):用来存放线程放入的消息。 

  4)线程:UIthread 通常就是main thread,而Android启动程序时会替它建立一个MessageQueue。
 
7.说说mvc模式的原理,它在android中的运用 
 MVC(Model_view_contraller)”模型_视图_控制器”。 MVC应用程序总是由这三个部分组成。Event(事件)导致Controller改变Model或View,或者同时改变两者。只要Controller改变了Models的数据或者属性,所有依赖的View都会自动更新。

8. 请解释下在单线程模型中Message、Handler、MessageQueue、Looper之间的关系。
Handler简介:
一个Handler允许你发送和处理Message和Runable对象,这些对象和一个线程的MessageQueue相关联。每一个线程实例和一个单独的线程以及该线程的MessageQueue相关联。当你创建一个新的Handler时,它就和创建它的线程绑定在一起了。这里,线程我们也可以理解为线程的MessageQueue。从这一点上来看,Handler把Message和Runable对象传递给MessageQueue,而且在这些对象离开MessageQueue时,Handler负责执行他们。

Handler
有两个主要的用途:(1)确定在将来的某个时间点执行一个或者一些Message和Runnable对象。(2)在其他线程(不是Handler绑定线程)中排入一些要执行的动作。

Scheduling Message
,即(1),可以通过以下方法完成:
post(Runnable):Runnable
在handler绑定的线程上执行,也就是说不创建新线程。
postAtTime(Runnable,long):
postDelayed(Runnable,long):
sendEmptyMessage(int):
sendMessage(Message):
sendMessageAtTime(Message,long):
sendMessageDelayed(Message,long):
post
这个动作让你把Runnable对象排入MessageQueue,MessageQueue受到这些消息的时候执行他们,当然以一定的排序。sendMessage这个动作允许你把Message对象排成队列,这些Message对象包含一些信息,Handler的hanlerMessage(Message)会处理这些Message.当然,handlerMessage(Message)必须由Handler的子类来重写。这是编程人员需要作的事。

当posting或者sending到一个Hanler时,你可以有三种行为:当MessageQueue准备好就处理,定义一个延迟时间,定义一个精确的时间去处理。后两者允许你实现timeout,tick,和基于时间的行为。

当你的应用创建一个新的进程时,主线程(也就是UI线程)自带一个MessageQueue,这个MessageQueue管理顶层的应用对象(像activities,broadcast receivers等)和主线程创建的窗体。你可以创建自己的线程,并通过一个Handler和主线程进行通信。这和之前一样,通过post和sendmessage来完成,差别在于在哪一个线程中执行这么方法。在恰当的时候,给定的Runnable和Message将在Handler的MessageQueue中被Scheduled。


Message
简介:
Message
类就是定义了一个信息,这个信息中包含一个描述符和任意的数据对象,这个信息被用来传递给Handler.Message对象提供额外的两个int域和一个Object域,这可以让你在大多数情况下不用作分配的动作。
尽管Message的构造函数是public的,但是获取Message实例的最好方法是调用Message.obtain(),或者Handler.obtainMessage()方法,这些方法会从回收对象池中获取一个。


MessageQueue
简介:
这是一个包含message列表的底层类。Looper负责分发这些message。Messages并不是直接加到一个MessageQueue中,而是通过MessageQueue.IdleHandler关联到Looper。
你可以通过Looper.myQueue()从当前线程中获取MessageQueue。


Looper
简介:
Looper
类被用来执行一个线程中的message循环。默认情况,没有一个消息循环关联到线程。在线程中调用prepare()创建一个Looper,然后用loop()来处理messages,直到循环终止。

大多数和message loop的交互是通过Handler。

下面是一个典型的带有Looper的线程实现。
  class LooperThread extends Thread {
      public Handler mHandler;
      
      public void run() {
          Looper.prepare();
          
          mHandler = new Handler() {
              public voidhandleMessage(Message msg) {
                  // process incomingmessages here
              }
          };
          
          Looper.loop();
      }
  }


9. 简要解释一下activity、 intent 、intent filter、service、Broadcase、BroadcaseReceiver
  答:一个activity呈现了一个用户可以操作的可视化用户界面 

  一个service不包含可见的用户界面,而是在后台无限地运行 

  可以连接到一个正在运行的服务中,连接后,可以通过服务中暴露出来的借口与其进行通信 

  一个broadcast receiver是一个接收广播消息并作出回应的component,broadcastreceiver没有界面 

  intent:content provider在接收到ContentResolver的请求时被激活。 

  activity, service和broadcast receiver是被称为intents的异步消息激活的。 

一个intent是一个Intent对象,它保存了消息的内容。对于activity和service来说,它指定了请求的操作名称和待操作数据的URI 

  Intent对象可以显式的指定一个目标component。如果这样的话,android会找到这个component(基于manifest文件中的声明)并激活它。但如果一个目标不是显式指定的,android必须找到响应intent的最佳component。

  它是通过将Intent对象和目标的intent filter相比较来完成这一工作的。一个component的intent filter告诉android该component能处理的intent。intent filter也是在manifest文件中声明的。

10.handler机制的原理 
  andriod提供了Handler 和 Looper 来满足线程间的通信。Handler先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(MessageExchange)。

  1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的MessageQueue(消息队列)。 

  2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到MessageQueue里;或者接收Looper从Message Queue取出)所送来的消息。

  3) Message Queue(消息队列):用来存放线程放入的消息。 

  4)线程:UIthread 通常就是main thread,而Android启动程序时会替它建立一个MessageQueue。 

11.简述Android应用程序的组成
(1) Activites  应用程序的表示层。

应用程序的每个界面都将是Activity类的扩展。Acitvities用视图(View)构成GUI来显示信息、响应用户操作。就桌面开发而言,一个活动(Activity)相当于一个窗体(Form)。

(2)Services  应用程序中的隐形工作者。

Service组件在后台运行,更新你的数据源和可见的Activities,触发通知(Notification)。在应用程序的Activities不激活或不可见时,用于执行依然需要继续的长期处理。

(3)Content Providers  可共享的数据存储。

Content Providers用于管理和共享应用程序数据库。是跨应用程序边界数据共享的优先方式。

(4)Intents  一个应用程序间(inter-application)的消息传递框架。

使用Intents你可以在系统范围内广播消息或者对一个目标Activity或Service发送消息,来表示你要执行一个动作。

(5)Widgets  可以添加到主屏幕界面(home screen)的可视应用程序组件。

作为Broadcase Receiver的特殊变种,widgets让你可以为用户创建可嵌入到主屏幕界面的动态的、交互的应用程序组件。


12.基础变量与引用变量的存放

1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 
2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。) 
3. 堆:存放所有new出来的对象。 
4. 静态域:存放静态成员(static定义的) 
5. 常量池:存放字符串常量和基本类型常量(public static final)。 
6. 非RAM存储:硬盘等永久存储空间 

13.Android中listview出现卡顿的原因

1..Adapter的getView方法里面convertView没有使用setTag和getTag方式;
2.在getView方法里面ViewHolder初始化后的赋值或者是多个控件的显示状态和背景的显示没有优化好,抑或是里面含有复杂的计算和耗时操作;
3.在getView方法里面 inflate的row 嵌套太深(布局过于复杂)或者是布局里面有大图片或者背景所致;
4.Adapter多余或者不合理的notifySetDataChanged;
5.listview 被多层嵌套,多次的onMessure导致卡顿,如果多层嵌套无法避免,建议把listview的高和宽设置为fill_parent. 如果是代码继承的listview,那么也请你别忘记为你的继承类添加上LayoutPrams,注意高和宽都是fill_parent的;

14.左连接与右连接的区别

左连接是已左边表中的数据为基准,若左表有数据右表没有数据,则显示左表中的数据右表中的数据显示为空。
左联接的结果集包括 LEFT 子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值。
右联接是左向外联接的反向联接。将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。


例子:

A表(a1,b1,c1) B表(a2,b2) 
a1 b1 c1 a2 b2 
01 数学 95 01 张三 
02 语文 90 02 李四 
03 英语 80 04 王五 

select A.*,B.* from A 
left outer join B on(A.a1=B.a2) 
结果是: 
a1 b1 c1 a2 b2 
01 数学 95 01 张三 
02 语文 90 02 李四 
03 英语 80 NULL NULL 

select A.*,B.* from A 
right outer join B on(A.a1=B.a2) 
结果是: 
a1 b1 c1 a2 b2 
01 数学 95 01 张三 
02 语文 90 02 李四 
NULL NULL NULL 04 王五

15.HashMap和Hashtable的区别是什么?

HashMap:非线程安全,高效,支持null;Hashtable:线程安全,低效,不支持null;

16.List set map的区别是什么?

list、set继承collection接口,而map不是;

Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同key,每个key只能映射一个value。Map接口提供3种集合的视图,Map的内容可以被当做一组key集合,一组value集合,或者一组key-value映射。(Map接口有三个实现类:HashMap,HashTable,LinkeHashMap 

List接口有三个实现类:LinkedList,ArrayList,Vector 

ArrayList和Vector的区别:ArrayList是非线程安全的,效率高;Vector是基于线程安全的,效率低 


list:有放入顺序,元素可重复;

set :无放入顺序,元素不可重复;

map:无放入顺序,元素按键值对存储;

17.什么是嵌入式系统?

嵌入式系统是指当外部数据或事件产生时能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统作出快速响应,并且控制所有实时任务协调一致运行的系统。

18.MVC模式是什么,有何优缺点?

MVC指的是模型、视图、控制器,一般MVC应用程序都是由这三个部分组成,事件导致控制器改变模型或视图,或者同时改变两者,控制器改变模型的数据或属性后,所有依赖的视图都会自动更新数据,同样,控制器改变视图,视图也会从隐藏的模型中获取最新的数据。


优点:

1、开发人员可以只关注整个结构中的其中某一层;
2、可以很容易的用新的实现来替换原有层次的实现;
3、可以降低层与层之间的依赖;
4、有利于标准化;
5、利于各层逻辑的复用。

缺点:

1.降低了整体的性能;

2.有时会导致级联的修改;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值