大数据面试准备——java篇
java中的数据类型
- java中的数据 类型分为基本数据类行和引用数据类型
- 基本数据类型有:byte,short,int,long,char,float,double,boolen
- 注意和scala中的数据类型做区别,scala中的数据类型首字母是大写的。
- 引用数据类型有:类,对象,数组等
- 包装类型:Byte,Short,Integer,Long ,Character,Float,Double,Boolean
java中的集合
- 单列集合:顶层接口是Collection
- list体系
- 特点:有序,可重复,元素有索引
- 常用子类:
- ArrayList:底层数据结构采用数组实现,所以查询,修改较快,增删较慢
- LinkedList::底层数据结构是链表实现,所以查询,修改比较慢,增删比较快
- set体系
- 特点:无序,唯一,元素有索引
- 常用子类:
- HashSet:底层采用哈希表(数组+链表)的方式实现,所以查询比较快,增删比较慢,底层依赖HashMap
- 双列集合:顶层接口是Map
- 特点:建具有唯一性,值可以重复,数据结构之针对于键有效
- 常用子类:
- HashMap:底层采用的是哈希表(数组+链表)的方式实现,增删改查相对都比较快、
HashMap底层实现
- HashMap的底层结构在jdk1.8之前使用的是数组+链表的方式实现的,在jdk1.8之后是由数组+链表+红黑树的结构实现的。
HashMap和HashTable的区别
- 线程的安全性不同
- HashMap是线程不安全的,HashTable是线程安全的,其中的方法是Synchromize修饰的,在多线程并发的情况下,可以直接使用HashTable,也可以使用HashMap,但是必须自己增加同步处理的方法
- 是否提供contains方法:
- HashMap 只有 containsValue 和 containsKey 方法;HashTable 有 contains、containsKey 和 containsValue 三个方法,其中contains和containsValue 方法的功能相同。
- boolean containsKey(Object key):如果此映射包含指定键的映射关系,则返回 true。
- boolean containsValue(Object value):如果此映射将一个或多个键映射到指定值,则返回 true。
- Hash_table.contains(Object value):该方法接受对象类型的一个参数值,表示要验证其映射的哈希表的值。
- key和value是否允许null值
- HashTable的key和value都是不允许出现null值的,HashMap中key是可以为null的,但是这样的key只能有一个,可以有多个为null的value。
- 数组的初始化和扩容机制
- HashTable在不指定容量的情况下,默认的容量为11,而HashMap的默认容量为16,HashTable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。
- HashTable扩容时,将容量变为原来的2倍加1,而HashMap扩容时,将容量变为原来的2倍。
HashSet集合保证元素唯一性的原理是什么
- HashSet集合保证元素唯一性依赖的是HashCode( )方法和equals( )方法
StringBuffer和StringBuilder的区别
- StringBuffer和StringBuilder中的方法和功能都是等价的。
- StringBuffer中的方法大都采用了synchronize方法的修饰,所以是线程安全的,而StringBuilder没有这个修饰,所以被认为是线程不安全的。
- 在单线程的程序中,StringBuilder效率更高,因为她不需要枷锁,不具备多线程安全,而StringBuffer每次都需要判断锁,效率相对更低。
final,finally,finalize这三个关键字的区别是什么
- final:修饰符有三种用法,修饰类,变量和方法
- final修饰类时,意味着他不能在派生出新的子类,也就是不能被继承
- final修饰变量时:该变量的值不能被改变,必须实在声明的时候给定初始值,在引用的时候只能读取。
- final修饰方法时:只能使用,不能在子类中重写
- finally:通常放在 try…catch的后面,构造最终习性的代码块,这就意味着程序无论是否正常退出,这里的代码只要 JVM 不关闭就都能执行,可以经释放外部资源的代码写着finally块中。
- finalize:Object类中提供的一个方法,在GC准备释放对象所占用的内存空间之前,它将首先调用finalize()方法。
==和equals的区别
= =
:如果比较的是基本数据类型,则比较的是变量的值是否相等
如果比较的是引用数据类型,则比较的是地址值是否相等(两个对象是够指向同一块内存)equals
:如果没有重写equals方法就比较的是两个对象的地址值,如果重写了equals方法,比较的就是对象中的属性内容。- equals方法是从object类中继承的,默认实现就是使用 ==
equals 源码:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
java中继承的特点是什么
- 类与类之间只能单继承,不能多继承,但是可以多层继承
- 接口与接口之间可以单继承也可以多继承
接口中的变量和方法默认修饰符是什么
- 变量:public static final
- 方法:public abstract
不能和abstract共存的关键字有哪些
- static: 因为static修饰符的方法可以被 类名. 的方式调用, 而抽象方法是没有方法体的, 假设 类名.抽象方法(), 这 样做是: 无意义的.
- final: 被final修饰的方法子类无法重写, 但是抽象方法要求子类必须重写, 它们不能共存是因为: 设计理念冲突.
- private: 被private修饰的内容子类无法继承, 但是抽象方法要求子类必须重写, 它们不能共存是因为: 设计理念冲突.
方法的重载和方法的重写有什么区别
- 方法重载(Overload): 同一个类中出现方法名相同, 但是参数列表不同的两个或者以上的方法时, 称为方法重载. 方法重载与返回值的数据类型无关.
- 方法重写(Override): 子父类间, 子类出现和父类一模一样的方法时, 称为方法重写, 方法重写要求返回值的数据类 型也必须一致或者有子父类关系
Synchronized与Lock的区别
- Synchronized能实现的功能Lock都可以实现,而且Lock比Synchronized更好用,更灵活。
- Synchronized可以自动上锁和解锁;Lock需要手动上锁和解锁
Runable 和 Callable 的区别
- Runnable接口中的方法没有返回值;Callable接口中的方法有返回值
- Runnable接口中的方法没有抛出异常;Callable接口中的方法抛出了异常
- Runnable接口中的落地方法是call方法;Callable接口中的落地方法是run方法
什么是分布式锁
- 当在分布式模型下,数据只有一份(或有限制),此时需要利用锁的技术控制某一时刻修改数据的进程数。分布式锁可以将标记存在内存,只是该内存不是某个进程分配的内存而是公共内存,如 Redis,通过set (key,value,nx,px,timeout)方法添加分布式锁。
什么是分布式事务
- 分布式事务指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不 同节点之上。简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不 同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。
Writer, 字节缓冲流, 字符缓冲流的默认缓冲区的大小是多少
2KB, 8KB, 16KB
多线程并行和多线程并发的区别是什么
- 多线程并行是指两个或者两个以上的线程共同执行(前提是需要多核CPU)
- 多线程并发是指两个或者两个以上的线程同时请求执行,但是同一瞬间,CPU只能运行一个,于是就安排他们交替执行,因为时间的间隔非常短暂,看起来是同时执行的,但其实不是。
JVM 分为那几个区,每个区有什么作用
java虚拟机主要分为以下几个区:
- 方法区:
- a. 有时候也成为永久代,在该区内很少发生垃圾回收,但是并不代表不发生GC,在这里进行的GC主要是对方法区里的常量池和对类型的卸载
- b. 方法区主要用来存储已被虚拟机加载的类的信息、常量、静态变量和即时编译器编译后的代码等数据。
- c. 该区域是被线程共享的。
- d. 方法区里有一个运行时常量池,用于存放静态编译产生的字面量和符号引用。该常量池具有动态性,也就是说常量并不一定是编译时确定,运行时生成的常量也会存在这个常量池中。
- 虚拟机栈:
- a. 虚拟机栈也就是我们平常所称的栈内存,它为java方法服务,每个方法在执行的时候都会创建一个栈帧,用于 存储局部变量表、操作数栈、动态链接和方法出口等信息。
- b. 虚拟机栈是线程私有的,它的生命周期与线程相同。
- c. 局部变量表里存储的是基本数据类型、returnAddress类型(指向一条字节码指令的地址)和对象引用,这个 对象引用有可能是指向对象起始地址的一个指针,也有可能是代表对象的句柄或者与对象相关联的位置。局部 变量所需的内存空间在编译器间确定
- d. 操作数栈的作用主要用来存储运算结果以及运算的操作数,它不同于局部变量表通过索引来访问,而是压栈和 出栈的方式
- e. 每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的 动态连接.动态链接就是将常量池中的符号引用在运行期转化为直接引用。
- 本地方法栈:
- 本地方法栈和虚拟机栈类似,只不过本地方法栈为Native方法服务。
- 堆:
- java堆是所有线程所共享的一块内存,在虚拟机启动时创建,几乎所有的对象实例都在这里创建,因此该区域经常 发生垃圾回收操作。
- 程序计数器:
- 内存空间小,字节码解释器工作时通过改变这个计数值可以选取下一条需要执行的字节码指令,分支、循环、跳转、 异常处理和线程恢复等功能都需要依赖这个计数器完成。该内存区域是唯一一个java虚拟机规范没有规定任何OOM 情况的区域。
什么是类加载器,常见的类加载器有哪些
- 实现通过类的权限定名获取该类的二进制字节流的代码块叫做类加载器。
- 主要有一下四种类加载器:
- 启动类加载器(Bootstrap ClassLoader)用来加载java核心类库,无法被java程序直接引用。
- 扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目 录。该类加载器在此目录里面查找并加载 Java 类。
- 系统类加载器(system class loader)也叫应用类加载器:它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader() 来获取它。
- 用户自定义类加载器,通过继承 java.lang.ClassLoader类的方式实现
类加载器的加载机制有哪些
- 全盘加载:就是当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器 负责载入,除非显示使用另外一个类加载器来载入
- 父类委托:就是当一个类加载器负责加载某个Class时,先让父类加载器试图加载该Class,只有在父类加载器 无法加载该类时才尝试从自己的类路径中加载该类
- 缓存机制:保证所有加载过的Class都会被缓存,当程序需要使用某个Class对象时,类加载器先从缓存区中搜 索该Class,只有当缓存区中不存在该Class对象时,系统才会读取该类对应的二进制数据,并将其转换成Class 对象,存储到缓存区。
……
- java基础知识点表较多,这里就不在细述了,面试之前好好看一遍。