不说废话,我们直接进入正题,看看最近面试官都问了Android程序员哪些问题。
一、Android10新特性及适配
新特性
- 折叠屏
- 5G网络支持
- 智能答复通知
- 暗黑模式
- 手势导航
- 浮动设置面板
- 分享改进
隐私
- 前台访问权限
- 网络扫描需要精确位置权限
- 防止设备跟踪
- 保护外部存储中的用户数据
- 阻止不需要的中断
安全
- 存储加密
- 默认TLS1.3
- 平台优化
- 改进的生物识别
相机和媒体
- 照片动态深度
- 音频播放捕获
- 新的音视频编解码器
- 原生MIDI API
- 定向可缩放的麦克风
- 无处不在的Vulkan
连接优化
- 改进的点对点和互联网连接
- WiFi高性能模式
Android系统基础
- ART优化
- 神经网络API1.2
- 热感API
- 公共API的兼容性
更快的更新速度,更新鲜的代码~
二、get 和 post 请求有哪些区别
- GET 请求的数据会附在 URL 之后(就是把数据放置在 HTTP 协议头中),以?分割 URL 和传输数据,参数之间以&相连,如: login.action?name=zhagnsan&password=123456。POST 把提交的数据则放置在是 HTTP 包的包体中。
- GET 方式提交的数据最多只能是 1024 字节,理论上 POST 没有限制,可传较大量的数据。其实这样说是错误 的,不准确的:
“GET 方式提交的数据最多只能是 1024 字节",因为 GET 是通过 URL 提交数据,那么 GET 可提交的数据量就跟 URL 的长度有直接关系了。而实际上,URL 不存在参数上限的问题,HTTP 协议规范没有对 URL 长度进行限制。这个 限制是特定的浏览器及服务器对它的限制。IE 对 URL 长度的限制是 2083 字节(2K 35)。对于其他浏览器,如 Netscape、 FireFox 等,理论上没有长度限制,其限制取决于操作系统的支持。
- POST 的安全性要比 GET 的 安全性 高。注意: 这里所说的安全性和上面 GET 提到的“安全”不是同个概念。上面“安全”的含义仅仅是不作数据修改,而这里安全的含义是真正的 Security 的含义,比如: 通过 GET 提交数据,用 户名和密码将明文出现在 URL 上,因为(1)登录页面有可能被浏览器缓存,(2)其他人查看浏览器的历史纪录,那么别 人就可以拿到你的账号和密码了,除此之外,使用 GET 提交数据还可能会造成 Cross-site request forgery 攻击。
三、线程和进程的区别? 为什么不仅仅用进程?
进程
进程是具有独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度(若不支持线程机制,进程的系统调度的单位。否则,线程是系统调度的单位)的独立单位。
特点
1、进程是程序的 一次 执行过程。若程序执行两次甚至多次,则需要两个甚至多个进程。
2、进程是正在运行程序的抽象。它代表运行的CPU,也称进程是对CPU的抽象。
3、系统资源(如内存、文件)以进程为单位分配。
4、操作系统为每个进程分配了独立的地址空间。
5、操作系统通过“调度”把控制权交给进程。
进程的弊端:
1、进程切换的代价、开销比较大。 2、在一个进程内也需要并行执行多个程序,实现不同的功能。 3、进程有时候性能比较低。(线程的引入为了解决进程的弊端)。
线程:
1、有标识符ID。 2、有状态及状态转换,所以需要提供一些状态转换操作。 3、不运行时需要保存上下文环境,所以需要程序计数器等寄存器。 4、有自己的栈和栈指针。 5、共享所在进程的地址空间和其它资源。
总结
1、进程是程序在某个数据集合上的一次运行活动;线程是进程中的一个执行路径。(进程可以创建多个线程)。
2、在支持线程机制的系统中,进程是系统资源分配的单位,线程是CPU调度的单位。
3、进程之间不能共享资源,而线程共享所在进程的地址空间和其它资源。同时线程还有自己的栈和栈指针,程序计数器等寄存器。
4、进程有自己独立的地址空间,而线程没有,线程必须依赖于进程而存在。
5、进程切换的开销较大。线程相对较小。(前面也提到过,引入线程也出于了开销的考虑)。
四、Java对象的生命周期
1、创建阶段(Created)
在创建阶段系统通过下面的几个步骤来完成对象的创建过程;
①为对象分配存储空间。
②开始构造对象。
③从超类到子类对static成员进行初始化。
④超类成员变量按顺序初始化,递归调用超类的构造方法。
⑤子类成员变量按顺序初始化,子类构造方法调用。一旦对象被创建,并被分派给某些变量赋值,这个对象的状态就切换到了应用阶段。
2、应用阶段(In Use)
对象至少被一个强引用持有。
3、不可见阶段(Invisible)
当一个对象处于不可见阶段时,说明程序本身不再持有该对象的任何强引用,虽然该这些引用仍然是存在着的。简单说就是程序的执行已经超出了该对象的作用域了。
4、不可达阶段(Unreachable)
对象处于不可达阶段是指该对象不再被任何强引用所持有。与“不可见阶段”相比,“不可见阶段”是指程序不再持有该对象的任何强引用,这种情况下,该对象仍可能被JVM等系统下的某些已装载的静态变量或线程或JNI等强引用持有着,这些特殊的强引用被称为”GC root”。存在着这些GCroot会导致对象的内存泄露情况,无法被回收。
5、收集阶段(Collected)
当垃圾回收器发现该对象已经处于“不可达阶段”并且垃圾回收器已经对该对象的内存空间重新分配做好准备时,则对象进入了“收集阶段”。如果该对象已经重写了finalize()方法,则会去执行该方法的终端操作。
这里要特别说明一下:不要重载finazlie()方法!
原因有两点:
① 会影响JVM的对象分配与回收速度 在分配该对象时,JVM需要在垃圾回收器上注册该对象,以便在回收时能够执行该重载方法;在该方法的执行时需要消耗CPU时间且在执行完该方法后才会重新执行回收操作,即至少需要垃圾回收器对该对象执行两次GC。
② 可能造成该对象的再次“复活”在finalize()方法中,如果有其它的强引用再次持有该对象,则会导致对象的状态由“收集阶段”又重新变为“应用阶段”。这个已经破坏了Java对象的生命周期进程,且“复活”的对象不利用后续的代码管理。
6、终结阶段
当对象执行完finalize()方法后仍然处于不可达状态时,则该对象进入终结阶段。在该阶段是等待垃圾回收器对该对象空间进行回收。
7、对象空间重新分配阶段
垃圾回收器对该对象的所占用的内存空间进行回收或者再分配了,则该对象彻底消失了,称之为“对象空间重新分配阶段”。
五、为什么等待和通知是在 Object 类而不是 Thread 中声明的
一个棘手的 Java 问题,如果 Java编程语言不是你设计的,你怎么能回答这个问题呢?Java编程的常识和深入了解有助于回答这种棘手的 Java 核心方面的面试问题。
为什么 wait,notify 和 notifyAll 是在 Object 类中定义的而不是在 Thread 类中定义
这是有名的 Java 面试问题,招2~4年经验的到高级 Java 开发人员面试都可能碰到。
这个问题的好在它能反映了面试者对等待通知机制的了解,以及他对此主题的理解是否明确。就像为什么 Java 中不支持多继承或者为什么 String 在 Java 中是 final 的问题一样,这个问题也可能有多个答案。
为什么在 Object 类中定义 wait 和 notify 方法,每个人都能说出一些理由。从我的面试经验来看,wait 和 nofity 仍然是大多数Java 程序员最困惑的,特别是2到3年的开发人员,如果他们要求使用 wait 和 notify, 他们会很困惑。因此,如果你去参加 Java 面试,请确保对 wait 和 notify 机制有充分的了解,并且可以轻松地使用 wait 来编写代码,并通过生产者-消费者问题或实现阻塞队列等了解通知的机制。
为什么等待和通知需要从同步块或方法中调用, 以及 Java 中的 wait,sleep 和 yield 方法之间的差异,如果你还没有读过,你会觉得有趣。为何 wait,notify 和 notifyAll 属于 Object 类? 为什么它们不应该在 Thread 类中? 以下是我认为有意义的一些想法:
- wait 和 notify 不仅仅是普通方法或同步工具,更重要的是它们是 Java 中两个线程之间的 通信机制 。对语言设计者而言, 如果不能通过 Java 关键字(例如 synchronized)实现通信此机制,同时又要确保这个机制对每个对象可用, 那么 Object 类则是的正确声明位置。记住同步和等待通知是两个不同的领域,不要把它们看成是相同的或相关的。同步是提供互斥并确保 Java 类的线程安全,而 wait 和 notify 是两个线程之间的通信机制。
- 每个对象都可上锁 ,这是在 Object 类而不是 Thread 类中声明 wait 和 notify 的另一个原因。(大家平等)
- 在 Java 中为了进入代码的临界区,线程需要锁定并等待锁定,他们不知道哪些线程持有锁,而只是知道锁被某个线程持有, 并且他们应该等待取得锁, 而不是去了解哪个线程在同步块内,并请求它们释放锁定。
- Java 是基于 Hoare 的监视器的思想。在Java中,所有对象都有一个监视器。 线程在监视器上等待,为执行等待,我们需要2个参数:
- 一个线程
- 一个监视器(任何对象)
在 Java 设计中,线程不能被指定,它总是运行当前代码的线程。但是,我们可以指定监视器(这是我们称之为等待的对象)。这是一个很好的设计,因为如果我们可以让任何其他线程在所需的监视器上等待,这将导致“入侵”,导致在设计并发程序时会遇到困难。请记住,在 Java 中,所有在另一个线程的执行中侵入的操作都被弃用了(例如 stop 方法)。
最后
感谢大家能耐着性子看完啰里啰嗦的文章,除了文章内的,我还有很多面试题的私藏。
不用多说,相信大家都有一个共识:无论什么行业,最牛逼的人肯定是站在金字塔端的人。所以,想做一个牛逼的程序员,那么就要让自己站的更高,成为技术大牛并不是一朝一夕的事情,需要时间的沉淀和技术的积累。
关于这一点,在我当时确立好Android方向时,就已经开始梳理自己的成长路线了,包括技术要怎么系统地去学习,都列得非常详细。
最后分享耗时一年多整理的一系列Android学习资源:Android源码解析、Android第三方库源码笔记、Android进阶架构师七大专题学习、历年BAT面试题解析包、Android大佬学习笔记等等,这些内容均免费分享给大家,需要完整版的朋友,点这里可以看到全部内容