美文网首页
面试题集

面试题集

作者: 请叫我财迷 | 来源:发表于2018-11-13 22:23 被阅读23次

    面试题
    一:Java
    1.equals与==的区别:
    ==是判断两个变量或实例是不是指向同一个内存空间 equals是判断两个变量或实例所指向的内存空间的值是不是相同。

    2.String、StringBuffer与StringBuilder的区别:
    String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象,
    StringBuffer和StringBuilder底层是 char[]数组实现的,
    StringBuffer是线程安全的,而StringBuilder是线程不安全的。

    3.Java的四种引用的区别:
    1)强引用:如果一个对象具有强引用,它就不会被垃圾回收器回收。即使当前内存空间不足,JVM 也不会回收它,而是抛出 OutOfMemoryError 错误,使程序异常终止。如果想中断强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象
    2)软引用:在使用软引用时,如果内存的空间足够,软引用就能继续被使用,而不会被垃圾回收器回收,只有在内存不足时,软引用才会被垃圾回收器回收。
    3)弱引用:具有弱引用的对象拥有的生命周期更短暂。因为当 JVM 进行垃圾回收,一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用回收。不过由于垃圾回收器是一个优先级较低的线程,所以并不一定能迅速发现弱引用对象
    4)虚引用:顾名思义,就是形同虚设,如果一个对象仅持有虚引用,那么它相当于没有引用,在任何时候都可能被垃圾回收器回收。

    4.类的加载过程,Person person = new Person();为例进行说明
    1).因为new用到了Person.class,所以会先找到Person.class文件,并加载到内存中;
    2).执行该类中的static代码块,如果有的话,给Person.class类进行初始化;
    3).在堆内存中开辟空间分配内存地址;
    4).在堆内存中建立对象的特有属性,并进行默认初始化;
    5).对属性进行显示初始化;
    6).对对象进行构造代码块初始化;
    7).对对象进行与之对应的构造函数进行初始化;
    8).将内存地址付给栈内存中的p变量

    5.GC机制
    垃圾收集器一般必须完成两件事:检测出垃圾;回收垃圾。怎么检测出垃圾?一般有以下几种方法:
    1)给一个对象添加引用计数器,每当有个地方引用它,计数器就加1;引用失效就减1。好了,问题来了,如果我有两个对象A和B,互相引用,除此之外,没有其他任何对象引用它们,实际上这两个对象已经无法访问,即是我们说的垃圾对象。但是互相引用,计数不为0,导致无法回收,
    2)所以还有另一种方法:以根集对象为起始点进行搜索,如果有对象不可达的话,即是垃圾对象。这里的根集一般包括java栈中引用的对象、方法区常良池中引用的对象、本地方法中引用的对象等。
    总之,JVM在做垃圾回收的时候,会检查堆中的所有对象是否会被这些根集对象引用,不能够被引用的对象就会被垃圾收集器回收。一般回收算法也有如下几种:
    1).标记-清除(Mark-sweep)
    2).复制(Copying
    3).标记-整理(Mark-Compact)
    4).分代收集算法

    6.java中的泛型,泛型擦除以及相关的概念
    1)泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。
    2)泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。

    泛型擦除以及相关的概念:Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除
    

    7.谈谈对Java平台的理解
    Java 本身是一种面向对象的语言,最显著的特性有两个方面,一是所谓的“书写一次,到处运行”(Write once, run anywhere),能够非常容易地获得跨平台能力;另外就是垃圾收集(GC, Garbage Collection),Java 通过垃圾收集器(Garbage Collector)回收分配内存,大部分情况下,程序员不需要自己操心内存的分配和回收。
    我们日常会接触到 JRE(Java Runtime Environment)或者 JDK(Java Development Kit)。 JRE,也就是 Java 运行环境,包含了 JVM 和 Java 类库,以及一些模块等。而 JDK 可以看作是 JRE 的一个超集,提供了更多工具,比如编译器、各种诊断工具等。

    8.“Java 是解释执行”,这个说法正不正确?
    对于“Java 是解释执行”这句话,这个说法不太准确。我们开发的 Java 的源代码,首先通过 Javac 编译成为字节码(bytecode),然后,在运行时,通过 Java 虚拟机(JVM)内嵌的解释器将字节码转换成为最终的机器码。但是常见的 JVM,比如我们大多数情况使用的 Oracle JDK 提供的 Hotspot JVM,都提供了 JIT(Just-In-Time)编译器,也就是通常所说的动态编译器,JIT 能够在运行时将热点代码编译成机器码,这种情况下部分热点代码就属于编译执行,而不是解释执行了。

    9.Exception和 Error的区别?
    Exception 和 Error 都是继承了 Throwable 类,在 Java 中只有 Throwable 类型的实例才可以被抛出(throw)或者捕获(catch),它是异常处理机制的基本组成类型。
    Exception 和 Error 体现了 Java 平台设计者对不同异常情况的分类。Exception 是程序正常运行中,可以预料的意外情况,可能并且应该被捕获,进行相应处理。
    Error 是指在正常情况下,不大可能出现的情况,绝大部分的 Error 都会导致程序(比如 JVM 自身)处于非正常的、不可恢复状态。既然是非正常情况,所以不便于也不需要捕获,常见的比如 OutOfMemoryError 之类,都是 Error 的子类。Exception 又分为可检查(checked)异常和不检查(unchecked)异常,可检查异常在源代码里必须显式地进行捕获处理,这是编译期检查的一部分。前面我介绍的不可查的 Error,是 Throwable 不是 Exception。
    不检查异常就是所谓的运行时异常,类似 NullPointerException、ArrayIndexOutOfBoundsException 之类,通常是可以编码避免的逻辑错误,具体根据需要来判断是否需要捕获,并不会在编译期强制要求。

    10.运行时异常和一般异常的区别?
    两种异常同属于Exception父类。
    运行时异常都是RuntimeException类及其子类异常,如NullPointerException、IndexOutOfBoundsException等。
    一般异常是RuntimeException以外的异常,类型上都属于Exception类及其子类。
    运行时异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的。
    一般异常包括IOException、SQLException等以及用户自定义的Exception异常。对于这种异常,Java编译器强制要求我们必需对出现的这些异常进行catch并处理,否则程序就不能编译通过。

    11.你知道有哪些错误吗?
    Error:OutOfMemoryError、NoClassDefFoundError
    Exception:IOException
    RuntimeException:NullPointerException、ClassCastException;

    12.NoClassDefFoundError和ClassNOtFoundException的区别?
    NoClassDefFoundError是一个错误(Error),而ClassNOtFoundException是一个异常,在Java中对于错误和异常的处理是不同的,我们可以从异常中恢复程序但却不应该尝试从错误中恢复程序。
    ClassNotFoundException的产生原因主要是:
    Java支持使用反射方式在运行时动态加载类,例如使用Class.forName方法来动态地加载类时,可以将类名作为参数传递给上述方法从而将指定类加载到JVM内存中,如果这个类在类路径中没有被找到,那么此时就会在运行时抛出ClassNotFoundException异常。
    解决该问题需要确保所需的类连同它依赖的包存在于类路径中,常见问题在于类名书写错误。
    另外还有一个导致ClassNotFoundException的原因就是:当一个类已经某个类加载器加载到内存中了,此时另一个类加载器又尝试着动态地从同一个包中加载这个类。通过控制动态类加载过程,可以避免上述情况发生。
    NoClassDefFoundError产生的原因在于:
    如果JVM或者ClassLoader实例尝试加载(可以通过正常的方法调用,也可能是使用new来创建新的对象)类的时候却找不到类的定义。要查找的类在编译的时候是存在的,运行的时候却找不到了。这个时候就会导致NoClassDefFoundError.
    造成该问题的原因可能是打包过程漏掉了部分类,或者jar包出现损坏或者篡改。解决这个问题的办法是查找那些在开发期间存在于类路径下但在运行期间却不在类路径下的类。

    13.final、finally、finalize的区别?
    1.final 可以用来修饰类、方法、变量,分别有不同的意义,final 修饰的 class 代表不可以继承扩展,final 的变量是不可以修改的,而 final 的方法也是不可以重写的(override)。

    1. finally 则是 Java 保证重点代码一定要被执行的一种机制。我们可以使用 try-finally 或者 try-catch-finally 来进行类似关闭 JDBC 连接、保证 unlock 锁等动作。
    2. finalize,是基础类java.lang.Object的一个方法,它的设计目的是保证对象在被垃圾收集前完成特定资源的回收。finalize 现在已经不推荐使用,因为不可预测、不能保证,还是拖慢垃圾收集。

    14.String为什么要声明为final
    1.在java.lang包下面的很多类,相当一部分都被声明成为final class,这可以有效防止API使用者更改基础功能,一定程度上,这是保证平台安全的必要手段。
    2.JDK为String做了很多优化,节省内存空间,提高效率。

    二:集合数据框架
    1.你用过哪些集合类?数据结构中用于存储数据的有哪些?
    数组:数组存储区间是连续的,占用内存严重,故空间复杂的很大。但数组的二分查找时间复杂度小,为O(1);数组的特点是:寻址容易,插入和删除困难;

    链表:链表存储区间离散,占用内存比较宽松,故空间复杂度很小,但时间复杂度很大,达O(N)。链表的特点是:寻址困难,插入和删除容易。
    

    2.哈希表:由数组+链表组成的:
    当我们往HashMap中put元素的时候,先根据key的hashCode重新计算hash值,根据hash值得到这个元素在数组中的位置(即下标),
    如果数组该位置上已经存放有其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。
    如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。

    3.ArrayList,LinkedList的区别
    ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
    对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
    对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

    4.ArrayList和Vector的主要区别是什么?
    Vector:线程同步;当Vector中的元素超过它的初始大小时,Vector会将它的容量翻倍,
    ArrayList:线程不同步,但性能很好;当ArrayList中的元素超过它的初始大小时,ArrayList只增加50%的大小

    5.HashMap和 HashTable 的区别:
    HashTable比较老,是基于Dictionary 类实现的,HashTable 则是基于 Map接口实现的,
    HashTable 是线程安全的, HashMap 则是线程不安全的,
    HashMap可以让你将空值作为一个表的条目的key或value。

    6.list,map,set都有哪些具体的实现类,区别都是什么?
    1)List,Set都是继承自Collection接口,Map则不是;
    2)List特点:元素有放入顺序,元素可重复;
    Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉,(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法;
    另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值)。
    3)Set和List对比:
    Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。
    List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。
    4)Map适合储存键值对的数据

    7.线程安全集合类与非线程安全集合类
    LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的;
    HashMap是非线程安全的,HashTable是线程安全的;
    StringBuilder是非线程安全的,StringBuffer是线程安全的。

    8.ArrayList与LinkedList的区别和适用场景
    优点:ArrayList是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高(在内存里是连着放的)。
    缺点:因为地址连续, ArrayList要移动数据,所以插入和删除操作效率比较低。
    优点:LinkedList基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,对于新增和删除操作add和remove,LinedList比较占优势。LinkedList 适用于要头尾操作或插入指定位置的场景。
    缺点:因为LinkedList要移动指针,所以查询操作性能比较低。
    当需要对数据进行对此访问的情况下选用ArrayList,当需要对数据进行多次增加删除修改时采用LinkedList。

    9.HashSet与Treeset的适用场景
    1)TreeSet 是二叉树(红黑树的树据结构)实现的,Treeset中的数据是自动排好序的,不允许放入null值。
    2)HashSet是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束。
    3)HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的String对象,hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例。

    适用场景分析:HashSet是基于Hash算法实现的,其性能通常都优于TreeSet。为快速查找而设计的Set,我们通常都应该使用HashSet,在我们需要排序的功能时,我们才使用TreeSet
    

    10.HashMap与TreeMap、HashTable的区别及适用场景
    1)HashMap:基于哈希表(散列表)实现。HashMap的实现中采用的是链表法。适用于Map中插入、删除和定位元素。
    2)TreeMap:非线程安全基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。适用于按自然顺序或自定义顺序遍历键(key)
    3)HashTable同步的,而HashMap是非同步的,效率上比HashTable要高。HashMap允许空键值,而HashTable不允许。

    三。Thread、AsynTask相关
    1.wait()和sleep()的区别:
    1)sleep来自Thread类,和wait来自Object类
    2)调用sleep()方法的过程中,线程不会释放对象锁。而 调用 wait 方法线程会释放对象锁
    3)sleep睡眠后不出让系统资源,wait让出系统资源其他线程可以占用CPU
    4)sleep(milliseconds)需要指定一个睡眠时间,时间一到会自动唤醒

    2.若Activity已经销毁,此时AsynTask执行完并且返回结果,会报异常吗?
    1)当一个App旋转时,整个Activity会被销毁和重建。当Activity重启时,AsyncTask中对该Activity的引用是无效的,因此onPostExecute()就不会起作用,若AsynTask正在执行,折会报 view not attached to window manager 异常
    2)同样也是生命周期的问题,在 Activity 的onDestory()方法中调用Asyntask.cancal方法,让二者的生命周期同步

    3.Activity销毁但Task如果没有销毁掉,当Activity重启时这个AsyncTask该如何解决?
    还是屏幕旋转这个例子,在重建Activity的时候,会回掉Activity.onRetainNonConfigurationInstance()重新传递一个新的对象给AsyncTask,完成引用的更新

    4.Android 线程间通信有哪几种方式(重要)?(更新UI也是同样原理)
    1)runOnUiThread:Runnable
    2)Handler + Message或者Handler + Thread + Message
    //3)Broadcast
    4)AsyncTask
    5)View.post(Runnable r)

    5.Android进程间通信有哪几种?
    1)Bundle/Intent传递数据
    2)文件共享
    3)Messenger
    4)AIDL
    5)ContentProvider
    6)Socket
    7)Broadcast

    6.请介绍下 AsyncTask的内部实现,适用的场景是:
    AsyncTask 内部也是 Handler 机制来完成的,只不过 Android 提供了执行框架来提供线程池来
    执行相应地任务,因为线程池的大小问题,所以 AsyncTask 只应该用来执行耗时时间较短的任务,
    比如 HTTP 请求,大规模的下载和数据库的更改不适用于 AsyncTask,因为会导致线程池堵塞,没有
    线程来执行其他的任务,导致的情形是会发生 AsyncTask 根本执行不了的问题。

    7.handler机制的原理:
    andriod提供了 Handler 和 Looper 来满足线程间的通信。Handler 先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(Message Exchange)
    Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。
    Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的消息。
    Message Queue(消息队列):用来存放线程放入的消息。
    线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。

    8.请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系
    Message Queue(消息队列):用来存放通过Handler发布的消息,通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到当前线程的消息队列。
    Handler:可以发布或者处理一个消息或者操作一个Runnable,通过Handler发布消息,消息将只会发送到与它关联的消息队列,然也只能处理该消息队列中的消息。
    Looper:是Handler和消息队列之间通讯桥梁,程序组件首先通过Handler把消息传递给Looper,Looper把消息放入队列。Looper也把消息队列里的消息广播给所有的。
    Handler,Handler接受到消息后调用handleMessage进行处理。
    Message:消息的类型,在Handler类中的handleMessage方法中得到单个的消息进行处理。

    Android 的消息机制也就是 handler 机制,创建 handler 的时候会创建一个 looper ( 通过 looper.prepare() 来创建 ),looper 一般为主线程 looper.
    handler 通过 send 发送消息 (sendMessage) ,当然 post 一系列方法最终也是通过 send 来实现的,在 send 方法中handler 会通过 enqueueMessage() 方法中的 enqueueMessage(msg,millis )向消息队列 MessageQueue 插入一条消息,同时会把本身的 handler 通过 msg.target = this 传入.
    Looper 是一个死循环,不断的读取MessageQueue中的消息,loop 方法会调用 MessageQueue 的 next 方法来获取新的消息,next 操作是一个阻塞操作,当没有消息的时候 next 方法会一直阻塞,进而导致 loop 一直阻塞,当有消息的时候,Looper 就会处理消息 Looper 收到消息之后就开始处理消息: msg.target.dispatchMessage(msg),当然这里的 msg.target 就是上面传过来的发送这条消息的 handler 对象,这样 handler 发送的消息最终又交给他的dispatchMessage方法来处理了,这里不同的是,handler 的 dispatchMessage 方法是在创建 Handler时所使用的 Looper 中执行的,这样就成功的将代码逻辑切换到了主线程了.
    Handler 处理消息的过程是:首先,检查Message 的 callback 是否为 null,不为 null 就通过 handleCallBack 来处理消息,Message 的 callback 是一个 Runnable 对象,实际上是 handler 的 post 方法所传递的 Runnable 参数.其次是检查 mCallback 是 否为 null,不为 null 就调用 mCallback 的handleMessage 方法来处理消息.
    

    9.请解释什么是进程(Process)与线程(Thread)?
    ①进程是操作系统结构的基础,是计算机中正在运行的程序实例,它可以被分配给处理机并被处理机执行。通俗地说,就是一个正在运行的应用程序实体。
    ②线程是进程中某个单一顺序的控制流,它也被称为轻量级进程(Lightweight Process),它是处理机调度的基本单位。

    10。请分析说明进程与线程的四点区别:
    ①地址空间和数据资源:进程间相互独立;同一进程的各线程间共享,但某进程内的线程在其它进程不可见。
    ②通信:进程间通信需要专门的机制;线程间可以直接读写全局变量来进行通信,不过需要同步和互斥手段的辅助,以保证数据的一致性。
    ③调度和切换:线程上下文切换比进程上下文切换要快得多。
    ④在多线程OS中,进程不是一个可执行的实体。

    11.Session就是一种保存上下文信息的机制,它通过SessionID来区分不同的客户。请简单描述它的三种保存Session ID的方式:
    ①使用Cookie:保存session id的方式可以采用Cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。
    ②URL重写:由于Cookie可以被人为的禁止,必须有其它的机制以便在Cookie被禁止时仍然能够把Session ID传递回服务器,经常采用的一种技术叫做URL重写,就是把Session ID附加在URL路径的后面,附加的方式也有两种,一种是作为URL路径的附加信息,另一种是作为查询字符串附加在URL后面。网络在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个Session ID。
    ③表单隐藏字段:另一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把Session ID传递回服务器。

    12.请解释什么叫TCP和UDP:
    ①TCP叫传输控制协议,它是一种可靠的连接,即有服务器和客户端,只有当双方建立好连接后,才能互相发送数据。(TCP---传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。)
    ②UDP叫用户数据报协议,它是一种不可靠的连接,即发送发在没有建立好连接的情况下,就可以直接向目标主机发送数据。(UDP---用户数据报协议,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。)

    四。网络相关
    1.为什么TCP是可靠的,UDP早不可靠的?为什么UDP比TCP快?
    TCP/IP协议高,因为其拥有三次握手双向机制,这一机制保证校验了数据,保证了他的可靠性。
    UDP就没有了,udp信息发出后,不验证是否到达对方,所以不可靠。
    但是就速度来说,还是UDP协议更高,毕竟其无需重复返回验证,只是一次性的。

    2.http协议了解多少,说说里面的协议头部有哪些字段?
    http(超文本传输协议)是一个基于请求与响应模式的、无状态的、应用层的协议;http请求由三部分组成,分别是:请求行、消息报头、请求正文。
    HTTP消息报头包括普通报头、请求报头、响应报头、实体报头

    3.https了解多少
    HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。

    4.谈谈 HTTP 中Get 和 Post 方法的区别
    GET - 从指定的服务器中获取数据,明文发送内容
    POST - 提交数据给指定的服务器处理,POST请求不能被缓存下来,POST请求不会保存在浏览器浏览记录中,以POST请求的URL无法保存为浏览器书签,POST请求没有长度限制

    ①POST请求可以向服务器传送数据,而且数据放在HTML HEADER内一起传送到服务端URL地址,数据对用户不可见。而GET是把参数数据队列加到提交的URL中,值和表单内各个字段一一对应,例如(http://www.baidu.com/s?w=�&inputT=2710)。
    ②GET传送的数据量较小,不能大于2KB。POST传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KB,IIS5中为100KB。
    ③GET安全性非常低,POST安全性较高
    

    5.HTTPS和HTTP的区别主要为以下五点:
    1)https 用的 443 端口, http 用的 80 端口
    2)https协议需要到ca申请证书,一般免费证书很少,需要交费。
    3)http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。
    4)http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
    5)http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

    五。Fragment相关
    1.Fragment 如何实现类似 Activity 栈的压栈和出栈效果的?
    Fragment 的事物管理器内部维持了一个双向链表结构,该结构可以记录我们每次 add 的Fragment 和 replace 的 Fragment,然后当我们点击 back 按钮的时候会自动帮我们实现退栈操作。

    2.Fragment 的好处:
    1)Fragment 可以使你能够将 activity 分离成多个可重用的组件,每个都有它自己的生命周期和UI。
    2)Fragment 可以轻松得创建动态灵活的 UI 设计,可以适应于不同的屏幕尺寸。从手机到平板电脑。
    3)Fragment 是一个独立的模块,紧紧地与 activity 绑定在一起。可以运行中动态地移除、加入、交换等
    4)Fragment 提供一个新的方式让你在不同的安卓设备上统一你的 UI
    5)Fragment 解决 Activity 间的切换不流畅,轻量切换。
    6)Fragment 替代 TabActivity 做导航,性能更好。
    7)Fragment 在 4.2.版本中新增嵌套 fragment 使用方法,能够生成更好的界面效果

    3.如何切换 fragement,不重新实例化
    正确的切换方式是 add(),切换时 hide(),add()另一个 Fragment;再次切换时,只需 hide()当前, show()另一个

    4.Activity 与 Fragment 通信:handler,广播,EvnetBus,接口

    六:性能
    1.为什么会产生内存泄漏?
    当一个对象已经不需要再使用了,本该被回收时,而有另外一个正在使用的对象持有它的引用从而导致它不能被回收,这导致本该被回收的对象不能被回收而停留在堆内存中,这就产生了内存泄漏。

    2.产生内存泄露的原因。
    1)单例的不恰当引用:改进:对单例中的context需引用application的context。这样activity销毁是就不会因为单例的生命周期与application一样而销毁失败。
    2)非静态内部类创建静态实例:改进:该创建静态内部类或将内部类抽取出来创建单例。这样在activity销毁时就不会因为非静态类持有activity对象而无法销毁。(静态实例的生命周期与应用生命周期一样长。成员变量:public static XXclass = null;)
    3)Handler造成的内存泄漏:改进:(1)创建静态自定义handler内部类继承handler,并在构造函数中对Handler持有的对象使用弱引用。(2)在Activity的Destroy时或者Stop时应该移除消息队列中的消息。mHandler.removeCallbacksAndMessages(null) ,或mHandler.removeCallbacks();或mHandler.removeMessages()。(泄露原因:activity退出,但消息还未处理完成。而非静态匿名内部类handler又持有activity的实例,导致activity销毁失败。)
    4)线程造成的内存泄漏:改进方法和内部类相似:(2)ondestory方法里AsyncTask::cancel()(异步任务和Runnable都是一个匿名内部类,因此它们对当前Activity都有一个隐式引用。)
    5)资源未关闭造成的内存泄漏:对于使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏
    6)构造Adapter时,没有使用缓存的convertView。集合中对象没清理造成的内存泄漏;
    查找内存泄漏:查找内存泄漏可以使用Android Stdio 自带的Android Profiler工具,也可以使用Square产品的LeadCanary.

    3.避免产生泄漏的一些建议
    1)对于生命周期比Activity长的对象如果需要应该使用ApplicationContext
    2)对于需要在静态内部类中使用非静态外部成员变量(如:Context、View),可以在静态内部类中使用弱引用来引用外部类的变量来避免内存泄漏;
    3)对于不再需要使用的对象,显示的将其赋值为null,比如使用完Bitmap后先调用recycle(),再赋为null
    4)保持对对象生命周期的敏感,特别注意单例、静态对象、全局性集合等的生命周期
    5)对于生命周期比Activity长的内部类对象,并且内部类中使用了外部类的成员变量,可以这样做避免内存泄漏:
    (1)将内部类改为静态内部类;(2)静态内部类中使用弱引用来引用外部类的成员变量

    4.性能优化的一些建议:
    1)如何避免 Activity 泄漏?
    (1)移除掉所有的静态引用;
    (2)考虑用 EventBus 来解耦 Listener;
    (3)记着在不需要的时候,解除 Listener 的绑定。
    (4)尽量用静态内部类
    (5)做 Code Review。个人经验:Code Review 能很早的发现内存泄漏
    (6)了解你程序的结构
    (7)用类似 MAT,Eclipse Analyzer,LeakCanary 这样的工具分析内存
    (8)在 Callback 里打印 Log
    2)避免滑动卡顿:
    (1)UI 线程只做 UI 更新。不要在UI上做下面事情:载入图片、网络请求、解析 JSON、读取数据库
    (2)理解并发 API; IntentService,AsyncTask,Executors,Handler 和 Loopers。开始使用优秀的第三方库。使用 Loader 加载数据库数据
    3)图片框架选择: Glide, Picasso, Fresco
    4)内存:LRUCache
    5)网络:Retrofit
    6)大 JSON:Jackson 以及 ig-json-parser
    7)避免Overdraw就是过度绘制:theme去掉window的默认背景
    8)重用布局文件layout、仅在需要时才加载布局ViewStub
    9)在没有特殊原因的情况下,尽量使用基本数据类型来代替封装数据类型;避免创建不必要的对象;对常量使用static final修饰符

    七:Android知识点
    1.请一一简述Android中的五类进程
    ①前台进程(Foreground process):用来处理用户正在进行的工作的进程。
    ②可见进程( Visible process):这种进程并不包含任何前台组件,但是包含仍然被用户可见的组件。如widget、输入法等,都属于visible
    ③服务进程(Service process):一个包含已启动服务的进程就是服务进程,服务没有用户界面,不与用户直接交互,但能够在后台长期运行,提供用户所关心的重要功能,其中运行着使用startService()方法启动的Service,并且没有变为更高的两个级别的进程。如联系人内部存储。
    ④后台进程(Background process):处理后台事务的进程,比如其中运行着执行了onStop()方法而处于停止态的Activity等。如浏览器器打开后按home键。
    ⑤空进程(Empty process):不包含任何活动的应用程序组件的进程。

    2.Android:四大架构的优缺点

    MVC 架构的缺陷:View、Controller、Model 相互依赖,造成代码耦合。
    难以分工,难以将 View、Controller、Model 分给不同的人写。
    难以维护,没有中间件接口做缓冲,难以替换底层的实现。Activity重,很难单元测试

    MVP 架构的特点与局限:MVP 数据、View、Presenter,View将操作给Presenter,Presenter去获取数据,数据获取好了返回给Presenter,Presenter去刷新View。PV,PM双向依赖。此外,MVP 的 View 和 Model 并不产生依赖,因此可以说是对 View 和 Model 做了代码解耦。

    3.Android常用数据结构
    答:队列、
    树、
    堆、
    数组、
    栈、
    链表、
    图、
    散列表

    4.Android动画可以归纳为哪几类
    答:视图动画(View 动画)、
    帧动画(Frame 动画、Drawable 动画)、
    属性动画、
    触摸反馈动画(Ripple Effect)、
    揭露动画(Reveal Effect)、
    转场动画 & 共享元素(Activity 切换动画)、
    视图状态动画(Animate View State Changes)、
    矢量图动画(Vector 动画)、
    约束布局实现的关键帧动画(ConstraintSet 动画)

    5、Android常用算法
    答:插入排序算法、
    快速排序算法、
    选择排序算法、
    冒泡排序算法、
    合并排序算法、
    希尔排序算法

    6、Android常用设计模式
    答:单例模式
    建造者模式、可以分步地构造每一部分。
    观察者模式、
    策略模式、多态,比如list -> arraylist, linkedlist
    代理模式、
    模板方法模式、
    原型模式、clone
    工厂模式、
    迭代器模式、提供一个方法顺序访问数据集合中的所有数据而又不暴露对象的内部表示

    7.View的绘制流程:OnMeasure()——>OnLayout()——>OnDraw()
    OnMeasure:测量视图大小。从顶层父View到子View递归调用measure方法,measure方法又回调OnMeasure。
    OnLayout:确定View位置,进行页面布局。从顶层父View向子View的递归调用view.layout方法的过程,即父View根据上一步measure子View所得到的布局大小和布局参数,将子View放在合适的位置上。
    OnDraw:绘制视图:ViewRoot创建一个Canvas对象,然后调用OnDraw(:①、绘制视图的背景;②、保存画布的图层(Layer);③、绘制View的内容;④、绘制View子视图,如果没有就不用;⑤、还原图层(Layer);⑥、绘制滚动条。

    8.事件传递机制
    1).Android事件分发机制的本质是要解决:点击事件由哪个对象发出,经过哪些对象,最终达到哪个对象并最终得到处理。这里的对象是指Activity、ViewGroup、View.
    2).Android中事件分发顺序:Activity(Window) -> ViewGroup -> View.
    3).事件分发过程由dispatchTouchEvent() 、onInterceptTouchEvent()和onTouchEvent()三个方法协助完成

    9.线程池的相关知识
    Android中最常见的四类具有不同特性的线程池分别为FixThreadPool、CachedThreadPool、SingleThreadPool、ScheduleThreadExecutor
    1).FixThreadPool:只有核心线程,并且数量固定的,也不会被回收(一个任务创建一个新线程,直到最大线程数,如果线程因为异常结束会创建一个新的替代),所有线程都活动时,因为队列没有限制大小,新任务会等待执行.优点:更快的响应外界请求;
    2)SingleThreadPool:只有一个核心线程,确保所有的任务都在同一线程中按顺序完成.因此不需要处理线程同步的问题.(如果这个唯一线程异常结束会重新创建一个新线程替代它)
    3)CachedThreadPool:可缓存,只有非核心线程,最大线程数非常大,所有线程都活动时,会为新任务创建新线程,否则会利用空闲线程(60s空闲时间,过了就会被回收,所以线程池中有0个线程的可能)处理任务.优点:任何任务都会被立即执行(任务队列SynchronousQueue相当于一个空集合);比较适合执行大量的耗时较少的任务;
    4)ScheduledThreadPool:核心线程数固定,非核心线程(闲着没活干会被立即回收)数没有限制.优点:执行定时任务以及有固定周期的重复任务

    10.怎样计算一张图片的大小,加载bitmap过程(怎样保证不产生内存溢出),二级缓存,LRUCache算法
    1)计算一张图片的大小:图片占用内存的计算公式:图片高度 图片宽度 一个像素占用的内存大小.所以,计算图片占用内存大小的时候,要考虑图片所在的目录跟设备密度,这两个因素其实影响的是图片的高宽,android会对图片进行拉升跟压缩。
    2)加载bitmap过程:Bitmap会将图片的所有像素(即长x宽)加载到内存中,如果图片分辨率过大,会直接导致内存OOM,只有在BitmapFactory加载图片时使用BitmapFactory.Options对相关参数进行配置来减少加载的像素。
    3)BitmapFactory.Options相关参数详解:Options.inPreferredConfig值来降低内存消耗。
    比如:默认值ARGB_8888改为RGB_565,节约一半内存;设置Options.inSampleSize 缩放比例,对大图片进行压缩;设置Options.inPurgeable和inInputShareable:让系统能及时回 收内存,(A:inPurgeable:设置为True时,表示系统内存不足时可以被回 收,设置为False时,表示不能被回收。B:inInputShareable:设置是否深拷贝,与inPurgeable结合使用,inPurgeable为false时,该参数无意义。);使用decodeStream代替其他方法。decodeResource,setImageResource,setImageBitmap等方法

    11.LRUCache算法是怎样实现的

    12.ANR的形成,各个组件上出现ARN的时间限制是多少
    1)只要是主线程耗时的操作就会ARN 如io
    2)broadcast超时时间为10秒 按键无响应的超时时间为5秒 前台service无响应的超时时间为20秒,后台service为200秒

    13.service的两种启动方式:
    startService:主要用于启动一个服务执行后台任务,不进行通信。停止服务使用stopService;生命周期--》onCreate(1次)--onStartCommand(多次startService会多次)--stopService--onDestroy
    bindService:该方法启动的服务可以进行通信。停止服务使用unbindService;onCreate(1次)--onBind(多次bindService只执行一次)--onUnBind (如果还有对象持有service对象,点击不起作用)--onDestroy

    14.ANR的形成,各个组件上出现ARN的时间限制是多少
    1)只要是主线程耗时的操作就会ARN 如io
    2)broadcast超时时间为10秒 按键无响应的超时时间为5秒 前台service无响应的超时时间为20秒,后台service为200秒

    15.Serializable和Parcelable 的区别
    1).P 消耗内存小
    2)网络传输用S 程序内使用P
    3)S将数据持久化方便
    4)S使用了反射 容易触发垃圾回收 比较慢

    16、Activity生命周期?
    onCreate() -> onStart() -> onResume() -> onPause() -> onStop() -> onDetroy()

    17.Broadcast注册方式与区别
    1)静态注册,也可成为常驻型广播,这种广播需要在Androidmanifest.xml中进行注册,这中方式注册的广播,不受页面生命周期的影响,即使退出了页面,也可以收到广播这种广播一般用于想开机自启动啊等等,由于这种注册的方式的广播是常驻型广播,所以会占用CPU的资源。
    2)动态注册,而动态注册的话,是在代码中注册的,这种注册方式也叫非常驻型广播,收到生命周期的影响,退出页面后,就不会收到广播,我们通常运用在更新UI方面。这种注册方式优先级较高。最后需要解绑,否会会内存泄露

    18.栈与队列的区别
    1)队列先进先出,栈先进后出
    2)对插入和删除操作的”限定”。 栈是限定只能在表的一端进行插入和删除操作的线性表。 队列是限定只能在表的一端进行插入和在另一端进行删除操作的线性表。
    3)遍历数据速度不同

    19.activity的启动模式
    1)standard:这是默认模式,每次激活Activity时都会创建Activity实例,并放入任务栈中。使用场景:大多数Activity。
    2)singleTop:如果在任务的栈顶正好存在该Activity的实例,就重用该实例( 会调用实例的 onNewIntent() ),否则就会创建新的实例并放入栈顶,即使栈中已经存在该Activity的实例,只要不在栈顶,都会创建新的实例。使用场景如新闻类或者阅读类App的内容页面
    3)singleTask:如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的 onNewIntent() )。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移出栈。如果栈中不存在该实例,将会创建新的实例放入栈中。使用场景如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,并且会清空主界面上面的其他页面。
    4)singleInstance:只存在一个实例

    八:设计模式
    1.观察者模式:发布订阅模式,发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息。它是为了定义对象间的一种一对多的依赖关系,即当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

    2.工厂模式:降低耦合度;
    静态工厂模式: 它是一个具体的类,非接口 抽象类。有一个重要的create()方法,利用if或者 switch创建产品并返回。
    create()方法通常是静态的,所以也称之为静态工厂。
    缺点:1) 扩展性差(我想增加一种面条,除了新增一个面条产品类,还需要修改工厂类方法)
    2) 不同的产品需要不同额外参数的时候 不支持。

    工厂方法模式:提供一个用于创建对象的接口(工厂接口),让其实现类(工厂实现类)决定实例化哪一个类(产品类),并且由该实现类创建对应类的实例。可以一定程度上解耦,消费者和产品实现类隔离开,只依赖产品接口(抽象产品),产品实现类如何改动与消费者完全无关。
    
    抽象工厂模式:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类;优点:抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。缺点:产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。
    

    1.ArrayList 和 Hashmap 简单说一些,区别,底层的数据结构.

    2.Handler 消息机制

    3.引起内存泄漏的场景

    4.多线程的使用场景?

    5.常用的线程池有哪几种?

    6.在公司做了什么?团队规模?为什么离职?

    1.知道哪些单例模式,写一个线程安全的单例,并分析为什么是线程安全的?

    2.Java中的集合有哪些?解释一下HashMap?底部的数据结构?散列表冲突的处理方法,散列表是一个什么样的数据结构?HashMap是采用什么方法处理冲突的?

    3.解释一下什么是MVP架构,画出图解,一句话解释MVP和MVC的区别?

    4.Handle消息机制?在使用Handler的时候要注意哪些东西,是否会引起内存泄漏?画一下Handler机制的图解?

    5.是否做过性能优化?已经采取了哪些措施进行优化?

    6.引起内存泄漏的原因是什么?以及你是怎么解决的?

    1.关于并发理解多少?说几个并发的集合?

    2.Handler 消息机制图解?

    3.在项目中做了哪些东西?

    4.画图说明View 事件传递机制?并举一个例子阐述

    5.类加载机制,如何换肤,换肤插件中存在的问题?hotfix是否用过,原理是否了解?

    6.说说项目中用到了哪些设计模式,说了一下策略模式和观察者模式?

    7.会JS么?有Hybid开发经验么?

    8.说一下快排的思想?手写代码

    9.堆有哪些数据结构?

    1.介绍一下在项目中的角色?

    2.遇到困难是怎么解决的?

    3.如何与人相处,与别人意见相左的时候是怎么解决的,并举生活中的一个例子.

    4.有没有压力特别大的时候?
    String是不是基本类型?String 为什么要设为 final
    抽象类和接口的区别
    说说面向对象编程(封装、继承)
    说说面向接口编程
    说说注解与反射
    说说拆箱和装箱
    数组和ArrayList。什么时候用数组,什么时候用ArrayList
    ArrayList和LinkedList的区别
    HashMap是怎么实现的
    栈和队列的区别
    什么是二叉树
    Android的四大组件
    Activity的生命周期
    Activity的加载模式
    Service:1.先bind再start,先start再bind呢? 2.先bindService,再调用stopService,Service会不会停止 3.IntentService
    能否在子线程中new Handler
    为什么不能在子线程更新UI
    View的事件传递
    View的绘制流程
    滑动冲突解决
    Android性能优化
    Android适配
    Android 动态权限处理

    相关文章

      网友评论

          本文标题:面试题集

          本文链接:https://www.haomeiwen.com/subject/wpyrfqtx.html