java 面试题1
什么是面向对象?
面向对象和面向过程的区别:
- 面向过程更注重每一个步骤以及其顺序,面向对象更注重哪些对象,他们具有哪些能力
- 面向过程比较直接,而面向对象更易于复用、扩展和维护
三大特性:
封装:内部细节隐藏 只提供对外的接口
javabean属性只能通过set方法赋值,不能使用Classname.filed直接赋值。
继承:子类共性的方法和属性在父类中体现出来,子类只需要做出特性的扩展即可。
多态:继承,方法重写,父类引用指向子类
JVM 虚拟机栈
java 栈 Oracle frame interpretation
每一个方法被调用时,就有一个新的栈帧被创建。当方法调用完成时,不管是抛出异常还是正常返回栈帧都会被销毁。 栈帧由java虚拟机栈中创建该栈帧的线程来分配。每个栈帧都有自己的本地变量,操作数栈,动态链接(返回方法的值或者抛出的异常)。
局部变量表(Local Variables):每个栈帧都有一个局部变量表(一个数组),可以存放类型为boolean, byte, char, short, int, float, reference, or returnAddress。在32位JVM中long,double类型占用连续两个变量位置。 每一个栈中的变量表从0号位开始,0号位为当前方法的调用者(this),任何局部变量都是从变量表 1号位开始。
操作数栈(Operand Stacks):JVM提供指令加载常量或者值从本地方法列表或者属性到操作数栈。其他Java JVM 可以对操作数栈中的值进行操作(计算),然后弹栈返回结果到操作数栈。操作数栈也用作方法参数的传递以及 接收方法的返回值。 任何时候每个操作数栈都有自己的深度,long、double都要占用两个单元深度,其他的类型的值占用一个操作数单元。
动态链接(Dynamic Linking):每个栈帧都会引用一个支持动态链接到当前方法区方法的运行时常量池。被引用到的字节码方法会被调用, 变量将可以通过符号引用进行访问。动态链接将这些符号链接翻译为具体的方法引用,加载还没有符号引用的的类,翻译变量的内存地址与运行时的内存地址将关联。
如何判断对象是否成为垃圾? 引用计数法:当有一个地方使用计数值+1,失效时-1,为0时是不可再被引用的对象 缺点:循环引用时,某些对象将无法被回收掉
final 关键字
- 修饰成员变量 如果final修饰的是类变量,只能在静态初始化块中指定初始化值或者声明该类变量时指定初始值。 如果final修饰的是成员变量,可以在非静态块初始化,声明该变量或者构造器中执行初始化值。
- 修饰局部变量 一定要赋值且只赋值一次,变量地址不能再次赋值
- 为什么内部类只能访问带final的外部变量? 原因一:如果内部类的方法执行完成,但是内部类对象还存在,并且引用了一个无效的成员变量。 原因二:局部变量修改,和内部类的变量值在内部改变,那么也会出问题。 所以只能访问带final的外部变量。
hashCode 和 equals方法
一般对象,如果有排序或者放入HashMap集合中,则需要重写hashCode和equals方法,并且保证两个方法实现的逻辑具有一致性。
泛型extends super
extends 指定了上限 A<? extends T>
super 指定了下限 A<? super T>
== 和 equals
== 基本数据类型比较值,引用类型比较地址
equals方法,要看具体对象的实现Object中equals是比较地址,而String类中是比较内容(地址值不同时才去比较内容)
StringBuilder StringBuffer String 区别
String是final修饰的,不可变,每次操作都会产生新的对象。
StringBuffer 和 StringBuilder 都是在原对象上操作,StringBuffer方法被sychronized加锁,效率降低。StringBuilder从JDK 5 开始,一般推荐使用StringBuilder。
重载和重写
重载:发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法的返回值和访问修饰符可以不同。
重写:发生在父子类中,方法名,(一同两小一大)参数列表必须相同。返回值类型小于父类,抛出异常小于父类,访问修饰符大于父类; 如果附列访问的修饰符位private则子类就不能重写该方法。 静态的方法不能被重写,只能被隐藏。
接口和抽象类的区别
单继承多实现 抽象类可以由具体方法,接口不可以有 接口都是静态类属性public static final.
抽象类可以集中实现公共的方法,这样写子类时只需要扩展特定的方法,提高了代码的复用性。 接口是定义行为,不关心子类怎么实现。
抽象类只能继承一个类,需要写出所有子类的所有共性,难度较高。 而接口在功能上就会弱化很多,他们只是针对一个动作的描述,在设计时会降低难度。
List 和 Set 区别
List: 有序可重复 允许多个null元素对象,可以使用iterator迭代器遍历元素,还可以使用下标遍历。 Set: 无序,不可重复,最多允许一个null元素对象,取元素时只能使用迭代器进行遍历。
HashCode 和 equals
hashcode 的作用是获取哈希码,可以用来确认该对象在哈希表中的索引位置。HashCode()定义在JDK的Object中, Java中的任何类都包含有HashCode()函数。散列表存储的是键值对,能根据键快速检索出对应的值。比较两个对 象是否为同一对象,HashCode相同时,还会调用equals方法。
注意:hashCode是对象 在堆上产生的独特的值,如果没有重写hashCode(),则该class的两个对象始终不会相等。
ArrayList 和 LinkedList
ArrayList 动态数组,连续内存存储,查询快,删除效率较低,但是在初始容量给得够的情况下尾部追加元素的的效率也是极高的。
LinkedList链表,可以分散存储在内存中。适合做数据插入删除操作,不适合查询。 使用for循环遍历,或者indexOf返回索引都是效率极低的,一般使用迭代器iterator进行遍历。
HashMap 和 Hashtable
HashMap 线程不安全,HashTable 线程安全(方法都被sychronized加锁)
HashMap 允许一个null键和多个null 值,而Hashtable则不允许。
底层数据结构 数组+链表
JDK8 开始链表高度为8 数组长度超过64 时链表会扭转为红黑树,元素以内部类Node节点存在。数组长度低于6时红黑树扭转为链表
-
计算key的Hash值,二次hash然后对数组长度取模,对应到数组下标
-
如果没有Hash冲突,创建Node存入数组
-
如果产生Hash冲突,先进行equals比较,相同则取代该元素;不同,则判断链表的高度插入链表。
-
key为null值,存在下标为0的位置。
ConcurrentHashMap jdk7 和 jdk8区别
jdk7
数据结构:ReentrantLock + segment + hashEntry, 一个Segment中包含一个HashEntry数组,每个HashEtry又是一个链表结构
元素查找:二次Hash,第一次Hash定位到Segment位置,第二次Hash定位到元素所在的链表头部
锁:Segment分段锁,Segment继承了Reentrantlock,锁定操作的Segment,其他的Segment 不受影响, 并发度为Segment个数,可以通过构造函数指定,数组扩容不会影响其他的Segment。
get方法无需加锁,volitile保证写都在主内存中。
jdk8
数据结构sychronized+CAS+红黑树 Node的val和next都用volatile修饰,保证对其他线程的可见性
查找替换赋值都是用CAS
锁:锁链表的head节点,不影响其他元素的读写,锁力度更细,效率更高,扩容时,阻塞所有的读写操作,并发扩容。
读操作无锁:
Node的val和next都用volatile修饰,保证对其他线程的可见性。
数组采用volatile修饰是为了保证扩容时,对其他线程可见。
如何实现一个IOC容器
- 配置文件配置、注解配置包扫描路径
- 递归包扫描获取.class文件,将所有被特定注解(@component)标记的类全路径名放到一个set集合中
- 遍历set集合,获取类上有指定注解的类,并将其交给IOC容器,定义一个安全的Map用来存储这些对象
- 遍历这个IOC容器,后去到每一个类的实例,判断里面是否有依赖注入的对象还没有注入,然后进行依赖注入。
双亲委派模型
三种类加载器 BootStrapClassLoader 默认加载%JAVA_HOME%/lib 下jar包和class文件 ExtClassLoader 负责加载%JAVA_HOME%/lib/ext 下jar包和class文件 AppClassLoader 是自定义类加载器的父类(parent属性指向),负责加载classpath下的类文件
向上委派 查找缓存 向下查找 查找加载路径 该路径下有该类则加载 否则向下查找
安全性:双亲委派 保证了类只会被加载一次 ,避免用户编写核心java类被加载。 相同的类被不同的加载器加载就是不同的两个类。
java中的异常体系
Error 异常是程序无法处理的会造成程序停止;Exception则不会造成程序停止 RuntimeException 发生在程序运行过程中,会导致程序当前线程执行失败。 CheckedException 发生在程序编译的过程中,会导致程序编译不通过。 Unchecked Exception 包括Error和 RuntimeException,在运行时发生。