面试官:我面Android程序员,经常遇到背题的,一问原理就露馅了

2021-01-21 17:46:39 浏览数 (1)

不说废话,我们直接进入正题,看看最近面试官都问了Android程序员哪些问题。

一、Android10新特性及适配

新特性
  1. 折叠屏
  2. 5G网络支持
  3. 智能答复通知
  4. 暗黑模式
  5. 手势导航
  6. 浮动设置面板
  7. 分享改进
隐私
  1. 前台访问权限
  2. 网络扫描需要精确位置权限
  3. 防止设备跟踪
  4. 保护外部存储中的用户数据
  5. 阻止不需要的中断
安全
  1. 存储加密
  2. 默认TLS1.3
  3. 平台优化
  4. 改进的生物识别
相机和媒体
  1. 照片动态深度
  2. 音频播放捕获
  3. 新的音视频编解码器
  4. 原生MIDI API
  5. 定向可缩放的麦克风
  6. 无处不在的Vulkan
连接优化
  1. 改进的点对点和互联网连接
  2. WiFi高性能模式
Android系统基础
  1. ART优化
  2. 神经网络API1.2
  3. 热感API
  4. 公共API的兼容性

更快的更新速度,更新鲜的代码~

二、get 和 post 请求有哪些区别

  1. GET 请求的数据会附在 URL 之后(就是把数据放置在 HTTP 协议头中),以?分割 URL 和传输数据,参数之间以&相连,如: login.action?name=zhagnsan&password=123456。POST 把提交的数据则放置在是 HTTP 包的包体中。
  2. GET 方式提交的数据最多只能是 1024 字节,理论上 POST 没有限制,可传较大量的数据。其实这样说是错误 的,不准确的:

“GET 方式提交的数据最多只能是 1024 字节",因为 GET 是通过 URL 提交数据,那么 GET 可提交的数据量就跟 URL 的长度有直接关系了。而实际上,URL 不存在参数上限的问题,HTTP 协议规范没有对 URL 长度进行限制。这个 限制是特定的浏览器及服务器对它的限制。IE 对 URL 长度的限制是 2083 字节(2K 35)。对于其他浏览器,如 Netscape、 FireFox 等,理论上没有长度限制,其限制取决于操作系统的支持。

  1. 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 类中? 以下是我认为有意义的一些想法:

  1. wait 和 notify 不仅仅是普通方法或同步工具,更重要的是它们是 Java 中两个线程之间的 通信机制 。对语言设计者而言, 如果不能通过 Java 关键字(例如 synchronized)实现通信此机制,同时又要确保这个机制对每个对象可用, 那么 Object 类则是的正确声明位置。记住同步和等待通知是两个不同的领域,不要把它们看成是相同的或相关的。同步是提供互斥并确保 Java 类的线程安全,而 wait 和 notify 是两个线程之间的通信机制。
  2. 每个对象都可上锁 ,这是在 Object 类而不是 Thread 类中声明 wait 和 notify 的另一个原因。(大家平等)
  3. 在 Java 中为了进入代码的临界区,线程需要锁定并等待锁定,他们不知道哪些线程持有锁,而只是知道锁被某个线程持有, 并且他们应该等待取得锁, 而不是去了解哪个线程在同步块内,并请求它们释放锁定。
  4. Java 是基于 Hoare 的监视器的思想。在Java中,所有对象都有一个监视器。 线程在监视器上等待,为执行等待,我们需要2个参数:
  5. 一个线程
  6. 一个监视器(任何对象)

在 Java 设计中,线程不能被指定,它总是运行当前代码的线程。但是,我们可以指定监视器(这是我们称之为等待的对象)。这是一个很好的设计,因为如果我们可以让任何其他线程在所需的监视器上等待,这将导致“入侵”,导致在设计并发程序时会遇到困难。请记住,在 Java 中,所有在另一个线程的执行中侵入的操作都被弃用了(例如 stop 方法)。

最后

感谢大家能耐着性子看完啰里啰嗦的文章,除了文章内的,我还有很多面试题的私藏。

不用多说,相信大家都有一个共识:无论什么行业,最牛逼的人肯定是站在金字塔端的人。所以,想做一个牛逼的程序员,那么就要让自己站的更高,成为技术大牛并不是一朝一夕的事情,需要时间的沉淀和技术的积累。

关于这一点,在我当时确立好Android方向时,就已经开始梳理自己的成长路线了,包括技术要怎么系统地去学习,都列得非常详细。

最后分享耗时一年多整理的一系列Android学习资源:Android源码解析、Android第三方库源码笔记、Android进阶架构师七大专题学习、历年BAT面试题解析包、Android大佬学习笔记等等,这些内容均免费分享给大家,需要完整版的朋友,点这里可以看到全部内容

0 人点赞