java面试中的各种“区别”(记忆帖)

来源:互联网 发布:c66140数控车床编程 编辑:程序博客网 时间:2024/05/22 01:09

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
public class HashMap<K,V> extends AbstractMap<K,V>    implements Map<K,V>, Cloneable, Serializable {
public class Hashtable<K,V> extends Dictionary<K,V>    implements Map<K,V>, Cloneable, java.io.Serializable {


3、String、StringBuilder、StringBuffer

  • 从是否可以改变的角度

    • String 是字符串常量,不能改变。用new会产生新的对象
    • StringBuilder和StringBuffer都是字符串变量,可以改变,并且不会产生新的对象
  • 从线程安全角度

    • StringBuilder 适用于单线程,是线程不安全的
    • StringBuffer 适用于多线程,是线程安全的
  • 从效率角度

    String是不可变的,所以对String的操作,比如拼接(”+”),会在内存中产生一个新的字符串对象,当修改频繁时,将会产生大量的对象,这种情况下,String的效率不如StringBuilder。StringBuilder提供了append()方法,用这种方法拼接字符串时不会产生新的对象。

以下引用自《Java程序员面试宝典》 - 但是也不能简单地认为.append()的效率好于“+”,比如   - String result = "a" + "b";   - StringBuilder sb = new String().append("a").append("b");   - 对于上面两句,1的效率好于2JVM在编译时将"a""b"连接成"ab",然后赋值给result。而append()还要花时间处理 


4、cookie、session

由于HTTP协议是无状态的,服务器要想记住用户的状态,就使用了cookie和session机制。

  • Cookies是Web服务器发送给客户端的一小段信息,当客户端再次请求时,可以发送该信息到服务器端,这样服务器端就知道该客户端早前访问过我。就相当于街头暗号,我告诉你一个暗号,再次见面时你一说暗号,我就知道是你。这里面的“我”相当于服务器,“你”相当于客户端

  • session 用来存取每个访问者的数据, 这些数据在服务器端存储,并对cookie的收发进行了抽象。 Cookies只存储数据的哈希会话ID,而不是数据本身,从而避免了关键信息的泄露。

下面的文章很好地解释了cookie和session
http://blog.csdn.net/u010429424/article/details/77394778


5、TCP、UDP

  • TCP

    • TCP是面向连接的
    • 基于流模式
    • 有流量控制和拥塞控制
    • 保证数据正确性和顺序
  • UDP

    • UDP无连接
    • 基于数据报模式
    • 可能会发生数据的丢失、不按序到达
    • 没有流量控制和拥塞控制

关于TCP与UDP的区别,详见这篇文章 面向报文(UDP)和面向字节流(TCP)的区别


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

最后上图

这里写图片描述

图片来自: http://docs.oracle.com/javase/7/docs/


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多

(持续补充中)

这里写图片描述

原创粉丝点击