Android面试题汇总(二)

一、Java集合

1、谈谈 Java 中 List、Set 以及 Map 的区别?

List:有序的,数据可以重复。。

Set:无序的,数据不能重复。

Map:键值对存储。键是唯一的,值不是唯一的。

2、谈谈 ArrayList 和 LinkedList 的区别?

ArrayList:底层是基于数组的,数组占用的是一个连续的内存空间。在新增和删除的时候效率低,因为新增的时候需要有扩容判断在新增元素,在删除的时候因为是连续的内存空间除了删除最后一个元素外,删除其他元素都会是数组元素发生移动。查询和修改效率高,可以直接根据index去直接进行定位。

LinkList:底层是基于链表的,占用的是分散的内存空间。在新增和删除的时候效率高。新增的时候不需要考虑扩容问题,删除的时候只需要被删除的后一个节点的指向发生改变。查询和修改的效率低,因为没有index下标

3、请说一下 HashMap 与 HashTable 的区别?

1、父类不同,HashMap是继承于AbstractMap,HashTable是Dictionary的子类

2、HashMap的key和value可以是null,但是HashTab不可以

3、HashMap是线程不安全的,HashTab是线程安全的可以在多线程下操作,但是JAVA后ConcurrentHashMap可以代替,比TashTab的扩展性更好

4、HashMap速度快,因为是线程不安全的,HashTab速度慢

5、HashMap不能保证元素的次序不变,因为每次扩容的时候会重新排序

6、HashMap初始大小16,HashTab初始大小11

4、说一说 ArrayList 的扩容机制?

ArrayLsit的初始容量是10,每次超过的时候都*1.5

5、HashMap 的实现原理?

HashMap底层是数组和链表的形式,只要是为了解决数据和链表的痛点,更好的进行增删改查。

首先是根据K来计算HashCode然后在确定数组的下标,实际上就是Node[] 链表数据,在添加数据的时候判断如果下标位置没有数据直接添加上,如果有数据判断key的hash值和equalus相同则覆盖,否则添加到链表的尾部

6、请简述LinkedHashMap的原理

底层是数据+双链表的形式,使用上和HashMap一样,他是HashMap的子类。只是它是有序的,而HashMap是无需的。因为底层是双链表所以内存占用会大一些

7、ConcurrentHashMap理解

ConcurrentHashMap比起Hashmap,是线程安全的,比起HashTable是高效的使用分段锁。

二、JAVA多线程

1、Java 中使用多线程的方式有哪些?

1、Thread重新run方法创建线程

2、实现Runnable接口,传给Thread使用

3、ExecutorService 线程池来使用线程

4、FutureTask+Executors 实现带有返回值的线程

2、说一下线程的几种状态?

创建状态:线程被创建的时候就是创建窗体

就绪状态:线程执行的了strat方法,调度的线程还没有把此线程设置为当前线程时 还没有执行run中的代码。线程重新启动的时候也会进度就绪状态

执行状态:开始指定run方法中的代码了  就是执行状态

阻塞状态:当调用sleep或者wait方法阻塞线程后,线程会进入阻塞状态

死亡状态:当调用stop方法后,线程会停止运行,进入死亡状态

3、如何实现多线程中的同步?

volatile关键词 -- 某种简单的逻辑下, 是可以的,只能修饰变量。保证变量的可见性

synchronized -- 重量级,会遭成线程阻塞

4、Thread 中 run() 与 start() 方法的区别?

run就是一个普通方法,调用一下执行一次,可以无限调用

start方法只能调用一次,是启动线程的方法,然后会自动执行run方法,执行完毕后线程销毁。

5、说一下 synchronized 和 volatile 关键字的区别?

1、synchronized重量级的可以修饰类、方法、变量。volatile轻量级只能修饰变量,volatile本质就是告诉jvm 寄存器中的值是不准确的,需要在主内存中读取

2、synchronized是具有原子性和可见性的,volatile只具备可见性

3、synchronized会造成线程阻塞,volatile不会

4、synchronized标记的变量会被编译器优化,volatile不会

6、如何保证线程安全?

根据具体的场景进行加锁(volatile或者synchronized),保证原子性,可见性和有序性

7、谈谈 Java 线程中 notify 和 notifyAll 方法有什么区别?

notify:只会唤醒等待该锁的其中一个线程。notifyAll:会唤醒等待该锁的所有线程。

8、什么是线程池?

线程池:就是线程的管理工具。

线程是为了执行任务的每个任务都需要重建一个线程,执行完就销毁掉。

线程池会管理所有线程,当某个线程空闲的时候会自动分配任务,如果等待的时间久也能自动回收,线程不够的时候也可以自动创建

9、谈一谈线程 sleep() 和 wait() 方法的区别?

1、sleep是Thread的方法,wait是Object的方法

2、sleep不释放锁,wait会释放锁

3、sleep不需要Synchronized,wait需要Synchronized

4、sleep不需要唤醒,wait需要唤醒

10、什么是悲观锁和乐观锁?

乐观锁:执行任务的时候默认同一时间不会出现其他线程一起处理任务的情况,会处理完任务后看一下数据有没有被修改过

悲观锁:执行任务的时候默认同一时间一定有其他线程一起处理任务,在处理任务的时候会直接上锁

11、谈一谈 Java 线程安全的集合有哪些?各有什么特点?

hashTab:加锁的hashMap,方法上直接加synchronized

concurrentHashMap:会在具体的位置加锁使用分段锁,保证效率,是HashTab的升级

三、Java虚拟机

1、请简要谈一谈 Java 中的垃圾回收机制?

垃圾回收机制:当堆内存中的某块区域没有对象引用的时候,这个内存区域将变成垃圾,等待垃圾回收器的收回

强制垃圾回收:程序中可以控制某个对象不被引用,但是绝对不能控制他的回收。System.gc()和Runtime.getRuntime().gc,可以建议垃圾回收器进行回收,但是可能回收也可能不回收。

finalize:对象的复活可以通过finalize()方法来实现,如果子类覆盖了此方法,垃圾回收器就会将他放入队列中,优先级低的线程来执行此方法,执行完毕垃圾回收器在看此对象是否可达,可达的话就复活否则回收。

2、回答一下什么是强、软、弱、虚引用以及它们之间的区别?

1、强引用:就是最普遍使用的。如果一个对象具有强引用,那么垃圾回收器是不会去回收他的,即使内存溢出了也不会随意的去回收强引用来保证内存。

2、软引用:软引用的对象当内存空间不足的时候,垃圾回收器才会回收,内存空间充足则不回收。软引用一般和RefereceQueue联合使用,如果软引用引用对象被回,JAVA虚拟机就会把软引用加入到与之关联的队列中

3、弱引用:弱引用对象无论内存空间是否充足,只要是垃圾回收器发现弱引用对象就会去回收,垃圾回收器的线程优先级很低因此也不会很快的去执行并回收。弱引用一般和RefereceQueue联合使用,如果弱引用引用对象被回收,JAVA虚拟机就会把弱引用加入到与之关联的队列中

4、虚引用:虚引用对象就是如同虚设的意识,随时可以被回收。虚引用一般是用来跟踪对象被垃圾回收器回收的活动,虚引用是必须和RefereceQueue联合使用的,当垃圾回收器回收虚引用对象前,Java虚拟机就会把虚引用放入与之关联的队列中

3、JVM、Dalvik、ART 三者的原理和区别?

JVM:是java虚拟器,运行java字节码

Dalvik:是google设计的用于Android平台的虚拟机,运行转换为.dex的java程序。

JVM和Dalvik的区别:

1、Dalvik是基于寄存器的,JVM是基于堆和栈的

2、Dalvik有自己的字节码

3、Dalvik在Android2.2后   支持JIT即时编译加载的

ART:ART是现流行的Android虚拟器,与Dalivk的区别

1、ART支持AOT预编译技术,而Dalvik是JIT即时加载技术

2、AOT预编译技术,是在程序安装的时候,把所有的字节码编译成机器码,应用运行的时候就无需实时编译,直接调用

3、JIT即时加载技术,是在程序启动的时候,通过性能分析优化代码执行;在应用运行的时候,实时将字节码编译成机器码

所以,ART 程序运行的时候效率会更高,因为在安装的时候已经全部编译完成。但是安装的时间会变长,会产生很多的机器码,所以占用的内存也会变大

4、请谈谈 Java 的内存回收机制?

在JAVA中内存管理分为2个方面,内存分配和内存回收。所有的内存管理工作都是由JVM负责的,避免了像C/C++那种直接操作内存带来的风险还有就是降低了我们的学习难度。

你可能感兴趣的:(java,开发语言)