一、java
熟练掌握java是很关键的,大公司不仅仅要求你会使用几个api,更多的是要你熟悉源码实现原理,甚至要你知道有哪些不足,怎么改进,还有一些java有关的一些算法,设计模式等等。
(一)java基础面试知识点
== 在用关系操作符 == 比较的是值本身;equals 比较两个对象的引用是否相等,即 是否指向同一个对象;hashCode 用来鉴定两个对象是否相等,Object类中的hashCode方法返回对象在内存中地址转换成的一个int值,所以如果没有重写hashCode方法,任何对象的hashCode方法是不相等的。
4、1或2或4、8
int 是我们常说的整形数字,是 Java 的 8 个原始数据类型之一。Integer 是 int 对应的包装类,它有一个 int 类型的字段存储数据,并且提供了基本操作,比如数学运算、int 和字符串之间转换等。
所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用变量调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。实现形式 在Java中有两种形式可以实现多态。继承和接口。
String 是 Java 语言非常基础和重要的类,提供了构造和管理字符串的各种基本逻辑。它是典型的 Immutable 类,被声明成为 final class,所有属性也都是 final 的。也由于它的不可变性,类似拼接、裁剪字符串等动作,都会产生新的 String 对象。由于字符串操作的普遍性,所以相关操作的效率往往对应用性能有明显影响。StringBuffer 是为解决上面提到拼接产生太多中间对象的问题而提供的一个类,我们可以用 append 或者 add 方法,把字符串添加到已有序列的末尾或者指定位置。StringBuffer 本质是一个线程安全的可修改字符序列,它保证了线程安全,也随之带来了额外的性能开销,所以除非有线程安全的需要,不然还是推荐使用它的后继者,也就是 StringBuilder。StringBuilder 是 Java 1.5 中新增的,在能力上和 StringBuffer 没有本质区别,但是它去掉了线程安全的部分,有效减小了开销,是绝大部分情况下进行字符串拼接的首选。
接口是对行为的抽象,他是抽象方法的集合,利用接口可以达到API定义和实现分离的目的。接口,不能实例化;不能包含任何非常量成员,任何field都是隐含着public static final的意义;同时没有非静态方法实现,也就是说要么是抽象方法,要么是静态方法。
抽象类是不能实例化的类,有abstract关键字修饰class,其目的主要是代码重用。除了不能实例化,形式上和一般的Java类并没有太大区别,可以有一个和多个抽象方法,也可以没有抽象方法。抽象类大多用于抽取相关Java类的共用方法实现或者是共同成员变量,然后通过继承的方式达到代码重用的目的。
泛型中extends的主要作用是设定类型通配符的上限, extends Fruit>代表的是上界通配符,也就是说这个List中存放的对象都是Fruit以及其子类的对象,这样我们就不用因为输入的List中类型的不同而改变代码了。
super与extends是完全相反的,其定义的是下界通配符。List super Fruit>也就是说List中存放的都是Fruit和它的父类的对象
不能,父类的静态方法能够被子类继承,但是不能够被子类重写,即使子类中的静态方法与父类中的静态方法完全一样,也是两个完全不同的方法。
final 可以用来修饰类、方法、变量,分别有不同的意义,final 修饰的 class 代表不可以继承扩展,final 的变量是不可以修改的,而 final 的方法也是不可以重写的(override)。finally 则是 Java 保证重点代码一定要被执行的一种机制。我们可以使用 try-finally 或者 try-catch-finally 来进行类似关闭 JDBC 连接、保证 unlock 锁等动作。finalize 是基础类 java.lang.Object 的一个方法,它的设计目的是保证对象在被垃圾收集前完成特定资源的回收。
Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流等以方便数据传输,Android的Parcelable的设计初衷是因为Serializable效率过慢。
内存间数据传输时推荐使用Parcelable,如activity间传输数据,而Serializable可将数据持久化方便保存,因为android不同版本Parcelable可能不同,所以不推荐使用Parcelable进行数据持久化。
父类的静态属性和方法可以被子类继承
不可以被子类重写
因为静态方法从程序开始运行后就已经分配了内存,也就是说已经写死了。所有引用到该方法的对象(父类的对象也好子类的对象也好)所指向的都是同一块内存中的数据,也就是该静态方法。子类中如果定义了相同名称的静态方法,并不会重写,而应该是在内存中又分配了一块给子类的静态方法,没有重写这一说。
非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围类,但是静态内部类却没有。没有这个引用就意味着:它的创建是不需要依赖于外围类的。它不能使用任何外围类的非static成员变量和方法。
https://www.cnblogs.com/ldl326308/p/9477566.html
https://blog.csdn.net/nobody_1/article/details/90886330
默认转成十进制
(二)java深入源码级的面试题(有难度)
哪些情况下的对象会被垃圾回收机制处理掉?
讲一下常见编码方式?
数字占1个字节,英文字母占1个字节,少数是汉字每个占用3个字节,多数占用4个字节。
动态代理是一种方便运行时动态构建代理、动态处理代理方法调用的机制,很多场景都是利用类似机制做到的,比如用来包装 RPC 调用、面向切面的编程(AOP)。实现动态代理的方式很多,比如 JDK 自身提供的动态代理,就是主要利用了上面提到的反射机制。还有其他的实现方式,比如利用传说中更高性能的字节码操作机制,类似 ASM、cglib(基于 ASM)、Javassist 等。通过代理可以让调用者与实现者之间解耦。
Exception 和 Error 都是继承了 Throwable 类,在 Java 中只有 Throwable 类型的实例才可以被抛出(throw)或者捕获(catch),它是异常处理机制的基本组成类型。Exception 和 Error 体现了 Java 平台设计者对不同异常情况的分类。Exception 是程序正常运行中,可以预料的意外情况,可能并且应该被捕获,进行相应处理。Error 是指在正常情况下,不大可能出现的情况,绝大部分的 Error 都会导致程序(比如 JVM 自身)处于非正常的、不可恢复状态。既然是非正常情况,所以不便于也不需要捕获,常见的比如 OutOfMemoryError 之类,都是 Error 的子类。Exception 又分为可检查(checked)异常和不检查(unchecked)异常,可检查异常在源代码里必须显式地进行捕获处理,这是编译期检查的一部分。前面我介绍的不可查的 Error,是 Throwable 不是 Exception。不检查异常就是所谓的运行时异常,类似 NullPointerException、ArrayIndexOutOfBoundsException 之类,通常是可以编码避免的逻辑错误,具体根据需要来判断是否需要捕获,并不会在编译期强制要求。
谈谈你对解析与分派的认识。
修改对象A的equals方法的签名,那么使用HashMap存放这个对象实例的时候,会调用哪个equals方法?
Java中实现多态的机制是什么?
如何将一个Java对象序列化到文件里?
说说你对Java反射的理解
反射机制是 Java 语言提供的一种基础功能,赋予程序在运行时自省(introspect,官方用语)的能力。通过反射我们可以直接操作类或者对象,比如获取某个对象的类定义,获取类声明的属性和方法,调用方法或者构造对象,甚至可以运行时修改类定义。
// 用法
Class bluetoothDeviceClass = BluetoothDevice.class;
bluetoothDeviceClass.getMethod("setPin", byte[].class).invoke(device, "1234".getBytes());
bluetoothDeviceClass.getMethod("createBond").invoke(device);
bluetoothDeviceClass.getMethod("setPairingConfirmation", boolean.class).invoke(device, true);
bluetoothDeviceClass.getMethod("cancelPairingUserInput").invoke(device);
// 常用方法
getDeclaredMethods() //获取这个类中的所有方法
getReturnType() //获取方法的返回类型
getParameterTypes() //获取方法的传入参数类型
getDeclaredConstructors() //获取所有的构造方法
getFields() //获取这个类中所有被public修饰的成员变量
反射不仅可以让我们获得隐藏的方法和属性,还可以让对象的实例化从编译时转化为运行时,因为我们可以通过Class.forName(“cc.abto.demo.Book”).newInstance()的方法来生成新的实例
注解,也叫元数据。一种代码级别的说明,在JDK1.5之后引入的特性,与类、接口、枚举同一层次。可以声明在包、类、字段、方法、局部变量、方法参数等前面,来对这些元素进行说明,注释等。
作用分类:
依赖注入设计原则允许我们移除硬编码依赖和让我们的应用低耦合,可扩展和可维护。我们可以通过在Java中实现依赖注入将依赖关系从编译时移到运行时来解析。
类型安全, 泛型的主要目标是实现java的类型安全。 泛型可以使编译器知道一个对象的限定类型是什么,这样编译器就可以在一个高的程度上验证这个类型
消除了强制类型转换, 使得代码可读性好,减少了很多出错的机会
Java语言引入泛型的好处是安全简单。泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
泛型的实现是靠类型擦除技术, 类型擦除是在编译期完成的, 也就是在编译期, 编译器会将泛型的类型参数都擦除成它的限定类型,如果没有则擦除为object类型之后在获取的时候再强制类型转换为对应的类型。 在运行期间并没有泛型的任何信息,因此也没有优化。
字符串常量池(String pool, String intern pool, String保留池) 是Java堆内存中一个特殊的存储区域, 当创建一个String对象时,假如此字符串值已经存在于常量池中,则不会创建一个新的对象,而是引用已经存在的对象。假若字符串对象允许改变,那么将会导致各种逻辑错误,比如改变一个对象会影响到另一个独立对象. 严格来说,这种常量池的思想,是一种优化手段.
16)Java8新特性
(三) 数据结构
常用数据结构简介
并发集合了解哪些?
列举java的集合以及集合之间的继承关系
集合类以及集合框架
容器类介绍以及之间的区别(容器类估计很多人没听这个词,Java容器主要可以划分为4个部分:List列表、Set集合、Map映射、工具类(Iterator迭代器、Enumeration枚举类、Arrays和Collections),具体的可以看看这篇博文 Java容器类)
List,Set,Map的区别
List和Map的实现方式以及存储方式
HashMap的实现原理
HashMap数据结构?
HashMap源码理解
HashMap如何put数据(从HashMap源码角度讲解)?
HashMap怎么手写实现?
ConcurrentHashMap的实现原理
ArrayMap和HashMap的对比
HashTable实现原理
TreeMap、HashMap和HashTable的区别
Hashtable、HashMap、TreeMap 都是最常见的一些 Map 实现,是以键值对的形式存储和操作数据的容器类型。Hashtable 是早期 Java 类库提供的一个哈希表实现,本身是同步的,不支持 null 键和值,由于同步导致的性能开销,所以已经很少被推荐使用。HashMap 是应用更加广泛的哈希表实现,行为上大致上与 HashTable 一致,主要区别在于 HashMap 不是同步的,支持 null 键和值等。通常情况下,HashMap 进行 put 或者 get 操作,可以达到常数时间的性能,所以它是绝大部分利用键值对存取场景的首选,比如,实现一个用户 ID 和用户信息对应的运行时存储结构。TreeMap 则是基于红黑树的一种提供顺序访问的 Map,和 HashMap 不同,它的 get、put、remove 之类操作都是 O(log(n))的时间复杂度,具体顺序可以由指定的 Comparator 来决定,或者根据键的自然顺序来判断
HashMap与HashSet的区别
HashSet与HashMap怎么判断集合元素重复?
集合Set实现Hash怎么防止碰撞
Vector、ArrayList和LinkedList的区别,以及应用场景
这三者都是实现集合框架中的 List,也就是所谓的有序集合,因此具体功能也比较近似,比如都提供按照位置进行定位、添加或者删除的操作,都提供迭代器以遍历其内容等。但因为具体的设计区别,在行为、性能、线程安全等方面,表现又有很大不同。Vector 是 Java 早期提供的线程安全的动态数组,如果不需要线程安全,并不建议选择,毕竟同步是有额外开销的。Vector 内部是使用对象数组来保存数据,可以根据需要自动的增加容量,当数组已满时,会创建新的数组,并拷贝原有数组数据。ArrayList 是应用更加广泛的动态数组实现,它本身不是线程安全的,所以性能要好很多。与 Vector 近似,ArrayList 也是可以根据需要调整容量,不过两者的调整逻辑有所区别,Vector 在扩容时会提高 1 倍,而 ArrayList 则是增加 50%。LinkedList 顾名思义是 Java 提供的双向链表,所以它不需要像上面两种那样调整容量,它也不是线程安全的。
数组是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据。最大的特点就是支持随机访问,但插入、删除操作也因此变得比较低效,平均情况时间复杂度为O(n)。
链表它并不需要一块连续的内存空间,它通过“指针”将一组零散的内存,空间可扩容,比较常用的是单链表,双链表和循环链表。和数组相比,链表更适合插入、删除操作频繁的场景,查询的时间复杂度较高。
二叉树的深度优先遍历和广度优先遍历的具体实现
堆的结构
堆和树的区别
堆和栈在内存中的区别是什么(解答提示:可以从数据结构方面以及实际实现方面两个方面去回答)?
什么是深拷贝和浅拷贝
手写链表逆序代码
讲一下对树,B+树的理解
讲一下对图的理解
判断单链表成环与否?
链表翻转(即:翻转一个单项链表)
合并多个单有序链表(假设都是递增的)
(四) 线程、多线程和线程池
继承Thread类、实现Runnable接口、实现Callable接口
start()方法来启动线程,真正实现了多线程运行,这时无需等待。run()方法当作普通方法的方式调用,程序还是要顺序执行,还是要等待run方法体执行完毕。
sleep()方法是属于Thread类中的。而wait()方法,则是属于Object类中的。
sleep()方法导致了程序暂停执行指定的时间,让出cpu给其他线程,线程不会释放对象锁。而当调用wait()方法的时候,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
基类 Object 提供了一些基础的 wait/notify/notifyAll 方法。如果我们持有某个对象的 Monitor 锁,调用 wait 会让当前线程处于等待状态,直到其他线程 notify 或者 notifyAll。
讲一下java中的同步的方法
数据一致性如何保证?
如何保证线程安全?
如何实现线程同步?
两个进程同时要求写或者读,能不能实现?如何防止进程的同步?
线程间操作List
Java中对象的生命周期
Synchronized用法
synchronize的原理
synchronized 代码块是由一对儿 monitorenter/monitorexit 指令实现的,Monitor 对象是同步的基本实现单元。
三种不同的锁:偏斜锁(Biased Locking)、轻量级锁和重量级锁。
所谓锁的升级、降级,就是 JVM 优化 synchronized 运行的机制,当 JVM 检测到不同的竞争状况时,会自动切换到适合的锁实现,这种切换就是锁的升级、降级。当没有竞争出现时,默认会使用偏斜锁。
谈谈对Synchronized关键字,类锁,方法锁,重入锁的理解
static synchronized 方法的多线程访问和作用
同一个类里面两个synchronized方法,两个线程同时访问的问题
多个线程访问同一个类的synchronized方法时, 都是串行执行的 ! 就算有多个cpu也不例外 ! synchronized方法使用了类java的内置锁, 即锁住的是方法所属对象本身. 同一个锁某个时刻只能被一个执行线程所获取, 因此其他线程都得等待锁的释放. 因此就算你有多余的cpu可以执行, 但是你没有锁, 所以你还是不能进入synchronized方法执行
轻量级的synchronized,只能用来修饰变量
保证了可见性和有序性(不保证原子性),如果一个共享变量被volatile关键字修饰,那么如果一个线程修改了这个共享变量后,其他线程是立马可知的。
当对volatile变量进行写操作的时候,JVM会向处理器发送一条lock前缀的指令,将这个缓存中的变量回写到系统主存中。用到了缓存一致性协议。
谈谈volatile关键字的用法
谈谈volatile关键字的作用
synchronized 和volatile 关键字的区别
synchronized提供了同步锁的概念,被synchronized修饰的代码段可以防止被多个线程同时执行,必须一个线程把synchronized修饰的代码段都执行完毕了,其他的线程才能开始执行这段代码。因为synchronized保证了在同一时刻,只能有一个线程执行同步代码块,所以执行同步代码块的时候相当于是单线程操作了,那么线程的可见性、原子性、有序性(线程之间的执行顺序)它都能保证了。
区别:
ReentrantLock 、synchronized和volatile比较
ReentrantLock的内部实现
lock原理
死锁的四个必要条件?
怎么避免死锁?
对象锁和类锁是否会互相影响?
类锁和对象锁不是同1个东西,一个是类的Class对象的锁,一个是类的实例的锁。也就是说:1个线程访问静态synchronized的时候,允许另一个线程访问对象的实例synchronized方法。反过来也是成立的,因为他们需要的锁是不同的。
一个线程池包括以下四个基本组成部分:
1、线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;
2、工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;
3、任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;
4、任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。
常见线程池有:newSingleThreadExecutor(单线程串行)、newFixedThreadExecutor(固定数量)、newCacheThreadExecutor(可缓存、推荐)、newScheduleThreadExecutor(大小无限制)
Java的并发、多线程、线程模型
谈谈对多线程的理解
线程是由一个主线程和很多个子线程组成的,主线程消失,子线程也会消失,但是子线程消失其中一个主线程不会消失
线程的生命周期分为5个步骤像人的一生一样,这5个步骤分别对应了5个方法
新生–>启动–>运行–>阻塞–>销毁
线程之间共用进程所有资源,当多线程操作同一个变量的时候,可能会使得结果不正确。
因此要特别注意线程安全的问题。
通常保证线程安全有很多种方式
线程同步是为了确保线程安全,所谓线程安全指的是多个线程对同一资源进行访问时,有可能产生数据不一致问题,导致线程访问的资源并不是安全的。如果多线程程序运行结果和单线程运行的结果是一样的,且相关变量的值与预期值一样,则是线程安全的。
如何保证多线程读写文件的安全?
多线程断点续传原理
多线程下载文件时,文件是被分成多个部分,是被不同的线程同时下载的,此时就需要每一条线程都分别需要一个记录点,和每个线程完成状态的记录。只有将所有线程的下载状态都处于完成状态时,才能表示文件下载完成。
1、首先获取要下载文件的长度,用来设置RomdomAccessFile(本地文件)的长度
2、实时保存文件的下载进度(此功能可以用数据库来实现)
3、中断后再次下载,读取进度,再从上次的下载进度继续下载,并在本地的文件续续写如。
获取文件长度:fileLength = HttpUrlConnection.getContentLength()
每条线程需要下载的大小 = fileLength / Thread_Num
二、Android
Android面试题包括Android基础,还有一些源码级别的、原理这些等。所以想去大公司面试,一定要多看看源码和实现方式,常用框架可以试试自己能不能手写实现一下,锻炼一下自己。
(一)Android基础知识点
Activity/Service/BroadCast Recevicer/Content provider
四大组件的生命周期和简单用法
Activity之间的通信方式
Activity未配置configChanges属性,切到横屏后,再切回竖屏时,会走两遍onPause——onSaveInstanceState——onStop——onDestroy——onCreate——onStart——onRestoreInstanceState——onResume 生命周期方法
只要随意配置了configChanges属性,切到横屏和再切到竖屏,生命周期调用顺序都表现为onConfigurationChanged
Activity与Fragment之间生命周期比较
Activity上有Dialog的时候按Home键时的生命周期
onPause() -> onStop()
对话框的出现并没有使Activity进入后台。而是点击Home键才使Activity进入后台工作
当在A 里面激活B 组件的时候, A会调用onPause()方法,然后B调用onCreate() ,onStart(), onResume()。
这个时候B覆盖了A的窗体, A会调用onStop()方法。
如果B是个透明的窗口,或者是对话框的样式, 就不会调用A的onStop()方法。
如果B已经存在于Activity栈中,B就不会调用onCreate()方法。
临时性数据
onSaveInstanceState调用的原则是系统有未经你的许可销毁Activity的可能。那么onSaveInstanceState有下面几种情况会调用:
按下HOME键、长按HOME键切换到了其他APP、横竖屏切换、Activity的导航、锁定屏幕
onRestoreInstanceState被调用的原则是Activity被销毁了,而不是可能被销毁了。
持久性数据
在onResume和onPause方法中做,可以把数据保存在数据库或者SharedPreference中。然而在生命周期函数中不适合做耗时的操作
如何实现Fragment的滑动?ViewPager+Fragment
fragment之间传递数据的方式?
定义数据接口,在Activity中实现该接口,并实现接口中定义的方法,在Fragment A中声明接口对象,并调用接口中的方法,Activity中的接口回调中,向Fragment B传递数据
EventBus传值
Activity 通过 bindService(Intent service, ServiceConnection conn, int flags) 跟服务 进行绑定, 当绑定成功的时候服务会将代理对象通过 onBind() 方法传给 conn, 这样我们就拿到了服务提供的服务代理对象
怎么在Activity 中启动自己对应的Service?
service和activity怎么进行数据交互?
Activity和Service的交互方式主要有以下几种:通过广播进行交互、通过共享文件、Messenger、AIDL
Service的开启方式
请描述一下Service 的生命周期
请描述一下广播BroadcastReceiver的理解
广播的分类
广播使用的方式和场景
BroadcastReceiver,LocalBroadcastReceiver 区别
BroadcastReceiver用于应用之间的传递消息;而LocalBroadcastManager用于应用内部传递消息,比broadcastReceiver更加高效。
BroadcastReceiver使用的Content API,所以本质上它是跨应用的,所以在使用它时必须要考虑到不要被别的应用滥用;LocalBroadcastManager不需要考虑安全问题,因为它只在应用内部有效。
AlertDialog 是非阻塞式对话框;而PopupWindow 是阻塞式对话框。
两者最根本的区别在于有没有新建一个 window,PopupWindow 没有新建,而是通过 WMS 将 View 加到 DecorView;Dialog 是新建了一个 window (PhoneWindow),相当于走了一遍 Activity 中创建 window 的流程。
Acitiivity 继承自ContextThemeWrapper—>再继承ContextWrapper—>Context。
Appliction 、Service继承自ContextWrapper—>再继承Context。
Application、Service 和 Activity 最终都是继承自Context,所以它们是同一个上下文。
属性动画可以对任何对象的属性做动画而不仅仅是View,甚至可以没有对象。除了作用对象进行扩展外,属性动画的效果也加强了,不仅能实现View动画的4中效果,还能实现其它多种效果,这些效果都是通过ValuAnimator或ObjectAnimator、AnimatorSet等来实现的。
如何导入外部数据库?
LinearLayout、RelativeLayout、FrameLayout的特性及对比,并介绍使用场景。
RelativeLayout会让子View调用2次onMeasure,LinearLayout 在有weight时,也会调用子View2次onMeasure
RelativeLayout的子View如果高度和RelativeLayout不同,则会引发效率问题,当子View很复杂时,这个问题会更加严重。如果可以,尽量使用padding代替margin
谈谈对接口与回调的理解
回调的原理
回调是一段可执行的代码通过参数传递给别一段代码,以期望在一个合适的时间调用这个参数
写一个回调demo
Callback.java
public interface Callback {
void printFinished(String msg);
}
Printer.java
public class Printer {
public void print(Callback callback) {
System.out.println("正在打印 . . . ");
try {
Thread.currentThread();
Thread.sleep(3000);// 毫秒
} catch (Exception e) {
e.printStackTrace();
}
callback.printFinished(“打印完成”);
}
}
People.java
public class People {
Printer printer = new Printer();
// 同步回调
public void goToPrintSyn(Callback callback) {
printer.print(callback);
}
// 异步回调
public void goToPrintASyn(Callback callback) {
new Thread(new Runnable() {
public void run() {
printer.print(callback);
}
}).start();
}
}
介绍下SurfView
RecycleView的使用
序列化的作用,以及Android两种序列化的区别
差值器
Interpolator设置 属性值 从初始值过渡到结束值 的变化规律的一个接口,如匀速、加速 & 减速 等等,即确定了 动画效果变化的模式,如匀速变化、加速变化 等等
应用场景:实现非线性运动的动画效果
TypeEvaluator设置 属性值 从初始值过渡到结束值 的变化具体数值的接口
插值器(Interpolator)决定 值 的变化规律(匀速、加速blabla),即决定的是变化趋势;而接下来的具体变化数值则交给估值器
属性动画特有的属性,协助插值器 实现非线性运动的动画效果
五种数据存储 :SharePreferences、SQLite、Contert Provider、File、网络存储
(二)Android源码相关分析
Android 动画就是通过 ParentView 来不断调整 ChildView 的画布坐标系来实现的
这其中又涉及到两个重要的类型,Animation 和 Transformation,这两个类是实现动画的主要的类,Animation 中主要定义了动画的一些属性比如开始时间、持续时间、是否重复播放等,这个类主要有两个重要的函数:getTransformation 和 applyTransformation,在 getTransformation 中 Animation 会根据动画的属性来产生一系列的差值点,然后将这些差值点传给 applyTransformation,这个函数将根据这些点来生成不同的 Transformation,Transformation 中包含一个矩阵和 alpha 值
Android各个版本API的区别
//V9.0:刘海屏的适配、电源管理、开发的应用默认不支持Http
//V8.0:通知栏适配(Notifcation)、广播限制、后台服务限制 8.0以上创建的前台Service需要发送一个Notification,否则Service会Anr
//V7.0:多窗口支持、文件读写权限适配、引入一项新的应用签名方案 :APK Signature Scheme v2、需要适配FileProvider,否则应用会崩溃。app之间的私有文件共享只能用FileProvider这种方式.
//V6.0:Android 动态权限申请、指纹识别、移除HttpClient库
//V5.0:虚拟机由Dalvik替换为Art虚拟机,Dalvik 使用JIT编译器,Art是AOT编译器、Materil Design设计规范、WebView cookie 存储问题
//V4.0:沉浸式状态栏、WebView webview调试功能、WebView 增加对 https请求限制需要去验证https证书
Requestlayout,onlayout,onDraw,DrawChild区别与联系
requestLayout()方法对View树进行重新布局,过程包括了measure()和layout()过程,但不会调用draw()过程,即不会发生重新绘制视图过程。
onLayout()的调用时机是:View需要给自己设置大小和位置了或者ViewGroup需要给子View和ViewGroup自身时调用。
View的绘制流程一共包括三步:①测量measure;②布局layout;③绘制draw;onDraw()方法就是在第三布绘制时发生,开发者已经测量好View的大小,设置好View的布局,剩下最后一步就是,具体画出这个布局。画的方法就是onDraw(),每个View都需要利用这个方法画出自己,ViewGroup除非设置了背景,否则不用调用该方法。
drawChild()去重新回调每个子视图的draw()方法
当Invalidate()被调用的时候,View的OnDraw()就会被调用;Invalidate()是刷新UI,UI更新必须在主线程,所以invalidate必须在UI线程中被调用,如果在子线程中更新视图的就调用postInvalidate()。
postInvalidate()实际调用的方法,mHandler.sendMessageDelayed,在子线程中用handler发送消息,所以才能在子线程中使用。
Activity 是四大组件之一,也是我们的界面载体,可以展示页面;而 View 实际上就是一个一个的视图,这些视图可以搭载在一个 Layout 文件上,通过 Activity 的 setContentView() 方法传递给 Activity;Window 是一个窗体,每个 Activity 对应一个 Window,通常我们在代码中用 getWindow() 来获取它。
每个 Activity 包含了一个 Window 对象,这个对象是由 PhoneWindow 做的实现。而 PhoneWindow 将 DecorView 作为了一个应用窗口的根 View,这个 DecorView 又把屏幕划分为了两个区域:一个是 TitleView,一个是 ContentView,而我们平时在 Xml 文件中写的布局正好是展示在 ContentView 中的。
谈谈对Volley的理解
如何优化自定义View
低版本SDK如何实现高版本api?
描述一次网络请求的流程
HttpUrlConnection 和 okhttp关系
Bitmap对象的理解
looper架构
ActivityThread,AMS,WMS的工作原理
自定义View如何考虑机型适配
自定义View的事件
AstncTask+HttpClient 与 AsyncHttpClient有什么区别?
LaunchMode应用场景
AsyncTask 如何使用?
SpareArray原理
请介绍下ContentProvider 是如何实现数据共享的?
AndroidService与Activity之间通信的几种方式
IntentService原理及作用是什么?
说说Activity、Intent、Service 是什么关系
ApplicationContext和ActivityContext的区别
SP是进程同步的吗?有什么方法做到同步?
谈谈多线程在Android中的使用
进程和 Application 的生命周期
封装View的时候怎么知道view的大小
RecycleView原理
RecyclerView是谷歌官方出的一个用于大量数据展示的新控件,可以用来代替传统的ListView,更加强大和灵活。支持RecyclerView高效运行的主要六大类:
RecyclerView拥有四级缓存:
Recyclerview在获取ViewHolder时按四级缓存的顺序查找,如果没找到就创建。通过了解RecyclerView的四级缓存,我们可以知道,RecyclerView最多可以缓存N(屏幕最多可显示的item数)+ 2 (屏幕外的缓存) + 5*M (M代表M个ViewType,缓存池的缓存)。
归根结底就是Android系统的app需要通过文本方式直接告诉系统的信息太多了
save():保存当前的绘图状态。restore():恢复之前保存的绘图状态。
onMeasure():这个函数最终目的是设置尺寸,如果“自己”是 ViewGroup 则必须在测量自己的同时,测量所有“子View”的 “尺寸”
必须调用 void setMeasuredDimension(int measuredWidth, int measuredHeight) 来设置“尺寸”,不调用会抛出异常 IllegalStateException
参数 widthMeasureSpec heightMeasureSpec 是“父View”分配给“自己”的 measure spec,可以看做是“父View”对“自己”的要求,MeasureSpec是由一个32位 int 值来表示的。其中该 int 值对应的二进制的高2位代表SpecMode,低30位代表SpecSize
onLayout():安排自己的子View的位置。调用childView的layout(l, t, r, b)方法。
onDraw():
第一步,对视图的背景进行绘制。
第三步,对视图的内容进行绘制。
第四步,对当前视图的所有子视图进行绘制。
第六步,对视图的滚动条进行绘制。
建议不要在onDraw方法体里创建对象,因为onDraw方法会被频繁调用,减少垃圾回收对绘图性能的影响。
canvas.save canvas.restore
(三)常见的一些原理性问题
Handler机制和底层实现
Handler、Thread和HandlerThread的差别
Handler:在android中负责发送和处理消息,通过它可以实现其他支线线程与主线程之间的消息通讯。
Thread:Java进程中执行运算的最小单位,亦即执行处理机调度的基本单位。某一进程中一路单独运行的程序。
HandlerThread:一个继承自Thread的类HandlerThread,Android中没有对Java中的Thread进行任何封装,而是提供了一个继承自Thread的类HandlerThread类,这个类对Java的Thread做了很多便利的封装。
HandlerThread对象start后可以获得其Looper对象,并且使用这个Looper对象实例Handler,之后Handler就可以运行在其他线程中了。
handler发消息给子线程,looper怎么启动?
关于Handler,在任何地方new Handler 都是什么线程下?
当前线程如果是主线程的话,Handler handler = new Handler();不是主线程的话,Looper.prepare(); Handler handler = new Handler();Looper.loop();或者Handler handler = new Handler(Looper.getMainLooper());
ThreadLocal原理,实现及如何保证Local属性?
请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系
Message: 消息对象
MessageQueen: 存储消息对象的队列
Looper:负责循环读取MessageQueen中的消息,读到消息之后就把消息交给Handler去处理。
Handler:发送消息和处理消息
Activity -> PhoneWindow -> DecorView -> ViewGroup -> … -> View
onTouchEvent方法是专门用来处理事件分发的,它一定存在Activity、View和ViewGroup这三者中。onTouch方法是View设置了触摸监听事件后,需要重写的方法,是OnTouchListener接口中的方法。
View和ViewGroup分别有哪些事件分发相关的回调方法
View刷新机制
在Android的View刷新机制中,父View负责刷新(invalidateChild)、布局(layoutChild)显示子View。而当子View需要刷新时,则是通知父View刷新子view来完成。
View的绘制基本分为measure、layout、draw 过程
测量一个比较重要的概念是,MeasureSpec一共有三种模式
https://www.jianshu.com/p/5a71014e7b1b
自定义控件原理
自定义View如何提供获取View属性的接口?
Android代码中实现WAP方式联网
AsyncTask机制
AsyncTask原理及不足
如何取消AsyncTask?
为什么不能在子线程更新UI?
ANR产生的原因是什么?
在Android里,应用程序的响应性是由Activity Manager和WindowManager系统服务监视的 。当它监测到以下情况中的一个时,Android就会针对特定的应用程序显示ANR:
造成以上两点的原因有很多,比如在主线程中做了非常耗时的操作,比如说是下载,io异常等。
ANR定位和修正
oom是什么?
什么情况导致oom?
有什么解决方法可以避免OOM?
Oom 是否可以try catch?为什么?
内存泄漏是什么?
什么情况导致内存泄漏?
检查、监控、优化
内存泄露场景的解决方法
内存泄漏和内存溢出区别?
LruCache默认缓存大小。基本上设置为手机内存的1/8
ContentProvider的权限管理(解答:读写分离,权限控制-精确到表级,URL控制)
如何通过广播拦截和abort一条短信?
在清单文件中注册广播接收器,设置该广播接收器优先级,尽量设高一点
创建一个BroadcastReceiver来实现广播的处理,并设置拦截器abortBroadcast();
广播是否可以请求网络?子线程可以
广播引起anr的时间限制是多少?10s
计算一个view的嵌套层级
while(view.getParent() != null) {
count++;
View = view.getParents();
}
Activity栈
Android线程有没有上限?
线程池有没有上限?
ListView重用的是什么?
Android为什么引入Parcelable?
Serializable 会使用反射,序列化和反序列化过程需要大量 I/O 操作, Parcelable 自已实现封送和解封(marshalled &unmarshalled)操作不需要用反射,数据也存放在 Native 内存中,效率要快很多。
(四)开发中常见的一些问题
ListView 中图片错位的问题是如何产生的?
混合开发有了解吗?
知道哪些混合开发的方式?说出它们的优缺点和各自使用场景?(解答:比如:RN,weex,H5,小程序,WPA等。做Android的了解一些前- 端js等还是很有好处的);
屏幕适配的处理技巧都有哪些?
服务器只提供数据接收接口,在多线程或多进程条件下,如何保证数据的有序到达?
动态布局的理解
怎么去除重复代码?
画出 Android 的大体架构图
RecyclerView比ListView多两级缓存,支持多个离ItemView缓存,支持开发者自定义缓存处理逻辑,支持所有RecyclerView共用同一个RecyclerViewPool(缓存池)。
RecyclerView更大的亮点在于提供了局部刷新的接口,通过局部刷新,就能避免调用许多无用的bindView。ListView和RecyclerView最大的区别在于数据源改变时的缓存的处理逻辑,ListView是"一锅端",将所有的mActiveViews都移入了二级缓存mScrapViews,而RecyclerView则是更加灵活地对每个View修改标志位,区分是否重新bindView.
https://www.jianshu.com/p/257c279a3493
Android新增的Recyclerview主要用于代替ListView。Recyclerview可扩展性强。
1>:某一个位置的元素刚进入屏幕开始请求图片,图片没有下载完成,就被移出屏幕,根据ListView工作原理可知,被移出屏幕的控件会很快的被重复利用起来,如果在这个时候之前发起图片的请求有了响应,会将刚才位置的图片显示到当前位置,虽然他们位置不同,却共用着同一个ImageView实例,这个时候会出现图片乱序;
2>:新进入屏幕的元素也会去请求图片,等图片下载完的时候会设置到同样的ImageView,因此就出现先显示一张图片,然后又变为另一张图片,就造成图片变来变去;
解决方案:
1>:在getView()方法中用url地址给ImageView设置tag标记;
2>:在onPostExecute()方法中调用 mListView.findViewWithTag(imageUrl) 获取ImageView实例,然后判断如果不为null,就把drawable图片设置到该ImageView控件上即可;
动态权限适配方案,权限组的概念
Android系统为什么会设计ContentProvider?谈谈你对ContentProvider的理解
ContentProvider应用程序间非常通用的共享数据的一种方式,也是Android官方推荐的方式。Android中许多系统应用都使用该方式实现数据共享,比如通讯录、短信等。
设计用意在于:
封装。对数据进行封装,提供统一的接口,使用者完全不必关心这些数据是在DB,XML、Preferences或者网络请求来的。当项目需求要改变数据来源时,使用我们的地方完全不需要修改。
提供一种跨进程数据共享的方式。
就是数据更新通知机制了。因为数据是在多个应用程序中共享的,当其中一个应用程序改变了这些共享数据的时候,它有责任通知其它应用程序,让它们知道共享数据被修改了,这样它们就可以作相应的处理。
ContentResolver接口的notifyChange函数来通知那些注册了监控特定URI的ContentObserver对象,使得它们可以相应地执行一些处理。ContentObserver可以通过registerContentObserver进行注册。
ContentProvider和调用者在同一个进程,ContentProvider的方法(query/insert/update/delete等)和调用者在同一线程中;
ContentProvider和调用者在不同的进程,ContentProvider的方法会运行在它自身所在进程的一个Binder线程中。
不会
如果在onStop的时候做了网络请求,onResume的时候怎么恢复?
Bitmap 使用时候注意什么?
Bitmap的recycler()
Android中开启摄像头的主要步骤
ViewPager使用细节,如何设置成每次只初始化当前的Fragment,其他的不初始化?
点击事件被拦截,但是想传到下面的View,如何操作?
微信主页面的实现方式
微信上消息小红点的原理
三、高级开发技术面试题
这里讲的是大公司需要用到的一些高端Android技术,这里专门整理了一个文档,希望大家都可以看看。这些题目有点技术含量,需要好点时间去研究一下的。
(一)图片
图片库的源码分析
图片框架缓存实现
LRUCache原理
LruCache的核心思想很好理解,就是要维护一个缓存对象列表,其中对象列表的排列方式是按照访问顺序实现的,即一直没访问的对象,将放在队尾,即将被淘汰。而最近访问的对象将放在队头,最后被淘汰。这个队列由LinkedHashMap来维护
图片加载原理
自己去实现图片库,怎么做?
Glide源码解析
Glide使用什么缓存?
Glide内存缓存如何控制大小?
(二)网络和安全机制
网络框架对比和源码分析
自己去设计网络请求框架,怎么做?
okhttp源码
五个拦截器
RetryAndFollowUpInterceptor:负责请求的重试和重定向
BridgeInterceptor:给请求添加对应的 header 信息,处理响应结果的header信息
CacheInterceptor:根据当前获取的状态选择 网络请求 、读取缓存、更新缓存。
ConnectInterceptor:建立 http 连接。
CallServerInterceptor:读写网络数据。
拦截器顺序: Interceptors -> RetryAndFollowUpInterceptor -> BridgeInterceptor -> CacheInterceptor -> ConnectInterceptor -> CallServerIntercepter
请求流程: newCall(RealCall)->enqueue->Dispatcher->enqueue->getResponseWithInterceptorChain()->interceptors->response
RetryAndFollowUpInterceptor:负责请求的重试和重定向 BridgeInterceptor:给请求添加对应的 header 信息,处理响应结果的header信息 CacheInterceptor:根据当前获取的状态选择 网络请求 、读取缓存、更新缓存。 ConnectInterceptor:建立 http 连接。 CallServerInterceptor:读写网络数据。 拦截器顺序: Interceptors -> RetryAndFollowUpInterceptor -> BridgeInterceptor -> CacheInterceptor -> ConnectInterceptor -> CallServerIntercepter 请求流程: newCall(RealCall)->enqueue->Dispatcher->enqueue->getResponseWithInterceptorChain()->interceptors->response
网络请求缓存处理,okhttp如何处理网络缓存的
从网络加载一个10M的图片,说下注意事项
TCP的3次握手和四次挥手
UDP使用场景:需要资源少,在网络情况比较好的内网,或者对于丢包不敏感的应用。不需要一对一沟通,建立连接,而是可以广播的应用。需要处理速度快,时延低,可以容忍少数丢包,但是要求即便网络拥塞,也毫不退缩,一往无前的时候。
HTTP协议
HTTP1.0与2.0的区别
HTTP 的报文大概分为三大部分。第一部分是请求行,第二部分是请求的首部,第三部分才是请求的正文实体。
HTTP与HTTPS的区别以及如何实现安全性
如何验证证书的合法性?
https中哪里用了对称加密,哪里用了非对称加密,对加密算法(如RSA)等是否有了解?
client如何确定自己发送的消息被server收到?
谈谈你对WebSocket的理解
WebSocket与socket的区别
谈谈你对安卓签名的理解。
V1:Android 应用的签名工具有两种:jarsigner 和 apksigner。它们的签名算法没什么区别,主要是签名使用的文件不同。在 META-INF 文件夹下有三个文件:MANIFEST.MF、CERT.SF、CERT.RSA。它们就是签名过程中生成的文件
签名验证是发生在 APK 的安装过程中,一共分为三步:
V2:是一种全文件签名方案,该方案能够发现对 APK 的受保护部分进行的所有更改,从而有助于加快验证速度并增强完整性保证。v2 签名将验证归档中的所有字节,而不是单个 ZIP 条目
在安装 APK 时,需要确保 APK 来源的真实性,以及 APK 没有被第三方篡改。
视频加密传输
App 是如何沙箱化,为什么要这么做?
权限管理系统(底层的权限是如何进行 grant 的)?
(三)数据库
sqlite升级,增加字段的语句
数据库框架对比和源码分析
数据库的优化
数据库数据迁移问题
(四)插件化、模块化、组件化、热修复、增量更新、Gradle
模块化、组件化、插件化区别?
模块化:将一个复杂业务实现,根据功能、页面或者其他进行不同粒度的划分程不同的模块,模块之间解耦,分别进行实现,特点:模块之间解耦,可以独立管理。
组件化:将一个app的代码拆分成几份独立的组件,组件之间是低耦合的,可以独立编译打包;也可以将组件打包到一个apk中。是解耦与加快编译,隔离不需要关注的部分
(1)每个模块可独立编译,提高了编译速度;
(2)开发只负责自己的模块,还可以再做的隔离一些,每个业务线只可见自己业务模块的代码,避免了误修改和版本管理问题。
(3)公共的Lib依然是个独立模块
与模块化的区别:是每个模块的角色的转换,一个组件可以独立编译打包,也可以作为lib集成到整个apk中
插件化:插件化是将一个apk根据业务功能拆分成不同的子apk,主流实现方式是通过Hook技术实现。
主要问题:如何加载类、如何加载资源、如何管理组件生命周期。
主流的热修复框架类型
主要利用 Java ClassLoader 、反射及动态代理等的原理,如 Android 的 DexClassLoader,可动态加载的内容包括 apk、dex、jar 等。
1.宿主apk和插件apk都是使用PathClassLoader加载,合并宿主和插件的ClassLoader
2.宿主apk资源和插件apk资源是隔离的,重写Activity的getResources和getAssets
3.Hook IActivityManager.startActivity和ActivityThread.mH.mCallback来骗过AMS对Activity的检测
模块化实现(好处,原因)
热修复,插件化
项目组件化的理解
描述清点击 Android Studio 的 build 按钮后发生了什么
(五)架构设计和设计模式
谈谈你对Android设计模式的理解
MVC MVP MVVM原理和区别
MVC: 视图层(View) 对应于xml布局文件和java代码动态view部分 控制层(Controller) MVC中Android的控制层是由Activity来承担的 模型层(Model) 针对业务模型,建立的数据结构和相关的类,它主要负责网络请求,数据库处理,I/O的操作。
问题:因为activity扮演了controller和view的工作,所以controller和view不太好彻底解耦
MVP: Presenter为Model和View之间交互的桥梁。Presenter跟View相互持有 MVP彻底解决了MVC中View和Controller傻傻分不清楚的问题,
但是随着业务逻辑的增加,一个页面可能会非常复杂,UI的改变是非常多,会有非常多的case,这样就会造成View的接口会很庞大。
MVVM: 通过双向绑定的机制,实现数据和UI内容,只要想改其中一方,另一方都能够及时更新的一种设计理念,只需要改变数据就行。 但是由于数据和视图的双向绑定,导致出现问题时不太好定位来源
你所知道的设计模式有哪些?
项目中常用的设计模式
手写生产者/消费者模式
写出观察者模式的代码
适配器模式,装饰者模式,外观模式的异同?
用到的一些开源框架,介绍一个看过源码的,内部实现过程。
谈谈对RxJava的理解
RxJava的功能与原理实现
RxJava的作用,与平时使用的异步操作来比的优缺点
说说EventBus作用,实现方式,代替EventBus的方式
从0设计一款App整体架构,如何去做?
说一款你认为当前比较火的应用并设计(比如:直播APP,P2P金融,小视频等)
谈谈对java状态机理解
Fragment如果在Adapter中使用应该如何解耦?
Binder机制及底层实现
对于应用更新这块是如何做的?(解答:灰度,强制更新,分区域更新)?
实现一个Json解析器(可以通过正则提高速度)
统计启动时长,标准
(六)性能优化
如何对Android 应用进行性能分析以及优化?
ddms 和 traceView
性能优化如何分析systrace?
用IDE如何分析内存泄漏?
Java多线程引发的性能问题,怎么解决?
启动页白屏及黑屏解决?
启动太慢怎么解决?
怎么保证应用启动不卡顿?
App启动崩溃异常捕捉
自定义View注意事项
现在下载速度很慢,试从网络协议的角度分析原因,并优化(提示:网络的5层都可以涉及)。
Https请求慢的解决办法(提示:DNS,携带数据,直接访问IP)
如何保持应用的稳定性
RecyclerView和ListView的性能对比
ListView的优化
RecycleView优化
View渲染
Bitmap如何处理大图,如一张30M的大图,如何预防OOM
java中的四种引用的区别以及使用场景
强引用置为null,会不会被回收?
(七)NDK、jni、Binder、AIDL、进程通信有关
请介绍一下NDK
什么是NDK库?
jni用过吗?
如何在jni中注册native函数,有几种注册方式?
Java如何调用c、c++语言?
jni如何调用java层代码?
进程间通信的方式?
Binder机制
简述IPC?
什么是AIDL?
AIDL解决了什么问题?
AIDL如何使用?
Android 上的 Inter-Process-Communication 跨进程通信时如何工作的?
多进程场景遇见过么?
Android进程分类?
进程和 Application 的生命周期?
进程调度
谈谈对进程共享和线程安全的认识
谈谈对多进程开发的理解以及多进程应用场景
什么是协程?
(八)framework层、ROM定制、Ubuntu、Linux之类的问题
java虚拟机的特性
谈谈对jvm的理解
JVM内存区域,开线程影响哪块内存
对Dalvik、ART虚拟机有什么了解?
Art和Dalvik对比
Dalvik中采用的是jit来做及时翻译,将dex或odex中并排的dalvik code(或者叫smali指令集)运行态翻译成native code去执行. 而在ART中,完全抛弃了Dalvik的jit,使用了aot直接在安装时用dex2oat将其完全翻译成native code.
Dalvik的gc的过程.主要有有四个过程:
1、当gc被触发时候,其会去查找所有活动的对象,整个程序与虚拟机内部的所有线程就会挂起,这样目的是在较少的堆栈里找到所引用的对象.需要注意的是这个回收动作是和应用程序同时执行(非并发).
2、gc对符合条件的对象进行标记
3、gc对标记的对象进行回收
4、恢复所有线程的执行现场继续运行
这么做的好处是,当pause了之后,gc势必是相当快速的.但是如果出现gc频繁并且内存吃紧势必会导致ui卡顿,掉帧.操作不流畅等.
ART改善了这种gc方式,主要的改善点在将其非并发过程改变成了部分并发.还有就是对内存的重新分配管理
当art gc发生时:
1、gc将会锁住java堆,扫描并进行标记
2、标记完毕释放掉java堆的锁,并且挂起所有线程
3、gc对标记的对象进行回收
4、恢复所有线程的执行现场继续运行
5、重复2-4直到结束
可以看出整个过程做到了部分并发使得时间缩短.据官方测试数据说gc效率提高2倍
dalvik.他的内存管理特点是:内存碎片化严重
在art中,它将java分了一块空间命名为Large-Object-Space,这块内存空间的引入用来专门存放large object.同时art又引入了moving collector的技术,即将不连续的物理内存块进行对齐.
虚拟机原理,如何自己设计一个虚拟机(内存管理,类加载,双亲委派)
谈谈你对双亲委派模型理解
JVM内存模型,内存区域
类加载机制
谈谈对ClassLoader(类加载器)的理解
谈谈对动态加载(OSGI)的理解
内存对象的循环引用及避免
内存回收机制、GC回收策略、GC原理时机以及GC对象
垃圾回收机制与调用System.gc()区别
Ubuntu编译安卓系统
系统启动流程是什么?(提示:Zygote进程 –> SystemServer进程 –> 各种系统服务 –> 应用进程)
大体说清一个应用程序安装到手机上时发生了什么
简述Activity启动全部过程
App启动流程,从点击桌面开始
逻辑地址与物理地址,为什么使用逻辑地址?
Android为每个应用程序分配的内存大小是多少?
Android中进程内存的分配,能不能自己分配定额内存?
进程保活的方式
如何保证一个后台服务不被杀死?(相同问题:如何保证service在后台不被kill?)比较省电的方式是什么?
App中唤醒其他进程的实现方式
(九)算法
排序算法有哪些?
最快的排序算法是哪个?
手写一个冒泡排序
手写快速排序代码
快速排序的过程、时间复杂度、空间复杂度
手写堆排序
堆排序过程、时间复杂度及空间复杂度
写出你所知道的排序算法及时空复杂度,稳定性
二叉树给出根节点和目标节点,找出从根节点到目标节点的路径
给阿里2万多名员工按年龄排序应该选择哪个算法?
GC算法(各种算法的优缺点以及应用场景)
蚁群算法与蒙特卡洛算法
子串包含问题(KMP 算法)写代码实现
一个无序,不重复数组,输出N个元素,使得N个元素的和相加为M,给出时间复杂度、空间复杂度。手写算法
万亿级别的两个URL文件A和B,如何求出A和B的差集C(提示:Bit映射->hash分组->多文件读写效率->磁盘寻址以及应用层面对寻址的优化)
百度POI中如何试下查找最近的商家功能(提示:坐标镜像+R树)。
两个不重复的数组集合中,求共同的元素。
两个不重复的数组集合中,这两个集合都是海量数据,内存中放不下,怎么求共同的元素?
一个文件中有100万个整数,由空格分开,在程序中判断用户输入的整数是否在此文件中。说出最优的方法
一张Bitmap所占内存以及内存占用的计算
2000万个整数,找出第五十大的数字?
烧一根不均匀的绳,从头烧到尾总共需要1个小时。现在有若干条材质相同的绳子,问如何用烧绳的方法来计时一个小时十五分钟呢?
求1000以内的水仙花数以及40亿以内的水仙花数
5枚硬币,2正3反如何划分为两堆然后通过翻转让两堆中正面向上的硬8币和反面向上的硬币个数相同
时针走一圈,时针分针重合几次
N*N的方格纸,里面有多少个正方形
x个苹果,一天只能吃一个、两个、或者三个,问多少天可以吃完?
(十)其他
在上家公司的技术成长?
做过最有成就感?有技术难度的点?
项目架构是怎么设计的?
Glide原理
OkHttp、Retrofit
另外,网上一般都推荐RxJava+Retrofit+OkHttp框架,Retrofit负责请求的数据和请求的结果,使用接口的方式呈现,OkHttp负责请求的过程,RxJava负责异步,各种线程之间的切换,用起来炒鸡爽。
热修复原理
日志回捞原理
HttpDNS原理
AOP