java面试中的各种“区别”(记忆帖)
本文目录为:
- 1、ArrayList、LinkedList
- 2、HashMap、Hashtable
- 3、String、StringBuilder、StringBuffer
- 4、cookie、session
- 5、TCP、UDP
- 6、堆、栈
- 7、jre、jdk
- 8、final、finalize、finally
- 9、synchronized、volatile
- 10、mysql、postgresql
- 11、进程、线程
- 12、重写(Override)和重载(Overload)
- 13、HTTP GET 和 POST
- 14、抽象类和接口
- 15、float和double的区别
1、ArrayList、LinkedList
- 底层不同:
- ArrayList 底层是一个数组
- LinkedList 底层是一个双向链表
- 查询、插入、删除效率不同
- ArrayList查询效率较高,因为数组是能够随机访问的,适合用于查询较多的场景。但是插入、删除效率较低。(注意,ArrayList删除时,被删数字后面的数字要向前移动一位,这一步很耗时。但是我们要注意到,如果只是删除最后一个元素,由于不需要移动数字,所以并不耗时。)
- LinkedList 插入、删除效率较高,但是不能随机访问。(注意,LinkedList在查找时有一个小优化。由于底层是双向循环链表,所以如果index小于LinkedList长度的一半,则从前向后查询;否则从后向前查)
- ArrayList需要扩容
- ArrayList初始化大小为10,当存储空间不够时会自动扩容。由于扩容要使用数组复制操作,比较费时,所以在使用ArrayList前我们最好知道数组的大小。每次扩容后,新容量为扩容前的1.5倍,如果新容量超过了ArrayList的最大容量,那么就只能使用最大容量了(怎么着也得有个上限吧)。
- LinkedList貌似不需要扩容,当插入时,申请结点就可以了。
- 使用场景不同
- 当经常需要执行查询操作时,适合使用ArrayListList
- 当我们不知道数据量的大小时或者经常执行插入删除的操作,适合使用LinkedList
ArrayList 源码分析请见 Java源码阅读之ArrayList LinkedList 源码分析请见 Java源码阅读之LinkedList
2、HashMap、Hashtable
HashMap的源码分析请见:Java源码阅读之HashMap
- 从线程安全角度
- HashMap是线程不安全的,不适用与多线程
- Hashtable是线程安全的,适用与多线程
- 能否为null
- HashMap key 和value都可以为null
- Hashtable 不允许null
- 效率
- 由于HashMap不需要同步,所以效率高一点 。当需要同步时,需要
Map map = Collections.synchronizedMap(new HashMap());
- HashMap和Hashtable继承的父类不同
- HashMap 的父类是AbstractMap
- Hashtable 的父类是Dictionary
3、String、StringBuilder、StringBuffer
- 从是否可以改变的角度
- String 是字符串常量,不能改变。用new会产生新的对象
- StringBuilder和StringBuffer都是字符串变量,可以改变,并且不会产生新的对象
- 从线程安全角度
- StringBuilder 适用于单线程,是线程不安全的
- StringBuffer 适用于多线程,是线程安全的
- 从效率角度
String是不可变的,所以对String的操作,比如拼接("+"),会在内存中产生一个新的字符串对象,当修改频繁时,将会产生大量的对象,这种情况下,String的效率不如StringBuilder。StringBuilder提供了append()方法,用这种方法拼接字符串时不会产生新的对象。
4、cookie、session
由于HTTP协议是无状态的,服务器要想记住用户的状态,就使用了cookie和session机制。
- Cookies是Web服务器发送给客户端的一小段信息,当客户端再次请求时,可以发送该信息到服务器端,这样服务器端就知道该客户端早前访问过我。就相当于街头暗号,我告诉你一个暗号,再次见面时你一说暗号,我就知道是你。这里面的“我”相当于服务器,“你”相当于客户端
- session 用来存取每个访问者的数据, 这些数据在服务器端存储,并对cookie的收发进行了抽象。 Cookies只存储数据的哈希会话ID,而不是数据本身,从而避免了关键信息的泄露。
5、TCP、UDP
- TCP
- TCP是面向连接的
- 基于流模式
- 有流量控制和拥塞控制
- 保证数据正确性和顺序
- UDP
- UDP无连接
- 基于数据报模式
- 可能会发生数据的丢失、不按序到达
- 没有流量控制和拥塞控制
6、堆、栈
- java 虚拟机栈:在创建线程时创建的,用来存储栈帧,因此也是线程私有的。java程序中的方法在执行时,会创建一个栈帧,用于存储方法运行时的临时数据和中间结果,包括局部变量表、操作数栈、动态链接、方法出口等信息。这些栈帧就存储在栈中。如果栈深度大于虚拟机允许的最大深度,则抛出StackOverflowError异常。
- java 堆:java堆被所有线程共享,堆的主要作用就是存储对象。如果堆空间不够,但扩展时又不能申请到足够的内存时,则抛出OutOfMemoryError异常。
StackOverflowError | OutOfMemoryError |
java栈 | java堆 |
栈深度超过范围了(比如:递归层数太多了) | 内存空间不够了(需要及时释放内存) |
7、jre、jdk
jre:java runtime environment
- java 运行时环境,包含java虚拟机,java类库等等
jdk:java development kie
- java开发工具包,jdk包含了jre和javac等
如果要运行java,安装jre就行
如果要开发java,需要安装jdk
最后上图
8、final、finalized、finally
final:
- final修饰变量:该变量不可修改,也就是常量
- final修饰方法:该方法不能被重写(Override)
- final修饰类:该类不能被继承扩展
- 一般接口中的变量默认是final的
finalize:
- Object中的方法,在GC前做必要的清理工作,有点像析构函数
finally:
- try {} catch{} finall{},重要代码执行的保证,例如:关闭文件、数据库连接,释放锁等动作
9、synchronized、volatile
- 意义:
- synchronized:锁住当前对象,不让别人用
- volatile:尽快告诉其他线程,当前变量的值改变了
- 修饰
- synchronized 可以修饰是对象、方法
- volatile 修饰变量
如果不是原子操作,比如 n++,就不能使用volatile了
尽量使用synchronized
10、mysql、postgresql
11、进程、线程
进程是可以独立运行的一段程序。
线程是进程的一个实体,是CPU调度的基本单位,基本上不拥有系统资源。
如果把进程比喻成工厂,那么线程就相当于流水线。
- 二者都能独立相互工作
- 线程 < 进程,一个进程能包含多个线程,就像一个工厂能包含多个流水线
- 进程至少拥有一个线程
- 不同进程间的线程要同步和通信,至于怎么实现,请见:http://www.mamicode.com/info-detail-517008.html
- 进程拥有资源,线程只是访问进程的资源
12、重写(Override)和重载(Overload)
- 重写
- 发生在父类与子类上,子类可以重写父类的方法
- 方法名、参数、返回类型必须相同,只有方法体可以不同
- 访问修饰符要大于重写的方法,比如public > protected
- 重写的方法在抛出异常时,不能比父类的方法更宽泛。比如父类抛出IOException,子类就不能抛出Exception
- 重载
- 发生在类的内部
- 函数名必须相同,参数必须不同,返回类型可以不同
- 访问修饰符可以不同
- 异常可以不同
13、HTTP GET 和 POST
14、抽象类和接口
- 抽象类
- 不能被实例化,也就是说不能被new,但是可以有构造方法
- 可以有普通方法和抽象方法
- 可以有成员变量
- 不能用final修饰抽象类、也不能用final修饰抽象方法,
- 就是说final和abstract不能出现在一起
- 但是final可以修饰抽象类中的普通方法
- 抽象类可以被继承,子类中需要实现抽象方法
- 抽象类可以被抽象类继承
- 接口
- 接口中的方法和常量默认为public final
- public 是为了外部使用者能够访问接口
- 接口中的常量是所有实现接口的类所共有的,因此不能被改变
- 接口没有构造方法,也不能被new
- 接口中的方法都是abstract的
- 在JDK1.8中,可以为接口定义默认方法,用default修饰
14、float和double的区别
- float的精度是7位,double16位
- 但是double消耗内存比float多
(持续补充中)