1. 面向对象:
a.封装:
javaBean\orm 外部无需关心内部实现
b.继承:
继承基类方法,做出自己的扩张/改变
c.多态:
继承、方法重写、父类引用 父类类型 变量名 = new 子类对象; 变量名.方法名(); 无法调用子类方法
2. JDK、JRE、JVM三者区别和联系
a. JDK:
java 开发工具
b. JRE:
环境
c. JVM:
虚拟机
3. == 和 equals
a. == :
对比的是栈中的值,基本数据类型是变量,引用类型是堆中内存对象的地址
b. equals:
object 中默认也是采用==比较 Object
public boolean equals(Object object){
return (this==obj);
}
String
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;
}
4. final
修饰类 修饰方法 修饰变量 内部类/外部类变量问题
5.String、StringBuffer、StringBuilder
String是final修饰的,不可变,每次操作都会产生新的String对象 StringBuffer和StringBuilder都是在原对象上操作 StringBuffer是线程安全的,StringBuilder是线程不安全的 StringBuffer方法是synchronized修饰的 性能:StringBuilder>StringBuffer>String
6. 重载和重写的区别
a. 重载
发生在同一个类中,方法名必须相同,参赛类型不同,个数不同,顺序不同方法返回值和修饰符不同,发生在编译时。
b. 重写
发生在父子类中,方法名和参数列表必须相同,返回值范围小于等于父类,抛出异常范围小于等于父类,访问修饰范围大于父类。如果父类方法修饰词为private,子类不能重写
7. 接口和抽象类的区别
a. 接口:
只能存在public abstract方法 可以实现多个。 接口成员变量只能是public static final类型 bird like aircraft 能做什么
b.抽象类:
可以存在普通成员函数, 抽象类只能继承一个, 成员变量可以是各种类型 不允许实例化 BWM is a 是什么
8. List和Set区别
a.List
有序可重复有下标访问
b.Set
无序不可重复只能通过iterator遍历访问
9.hashCode和equals
a. hashCode
获取哈希吗,散列码,返回int型整数,哈希表索引,java中的任何类都包含hashCode(),散列表存储的是key-value , 快速找到键对应的值 对象加入HashSet,HashSet会计算对应的hashCode是否有值,没有则加入,有则无法加入重新散列其他位置,大大减少equals的次数,大大提高执行速度 HashSet中算法:两个不一样的值会计算出相同hashCode。 (1)如果两个对象相等,则hashcode一定相同
b. equals
要去比较内存地址 两个对象有相同的hashCode值,他们也可能不相等
10. ArrayList和LinkedList区别
a.ArrayList
动态数组,连续内存存储,适合下标访问(随机访问),类型一致,非常快,占有内存长度相同 扩容机制:建一个新的数组 old new[10] --> new [15] ,老数组数据copy到新数组 静态数组 new int[10]
尾部插入指定初始容量可以极大提升性能,甚至超过linkedList (创建item,消耗小)
b.LinkedList
链表 可以存储在分散内存,适合做数据插入和删除,不适合查询; 需要逐一遍历,必须使用iterator不能使用for循环。因为每次for 插入,需要创建大量的node (性能消耗在创建node对象) for循环效率很低,对下标访问不友好,需要重新遍历 不要试图使用indexOf等返回元素索引,需要对list进行遍历,当结果为空时,会遍历整个列表
11. HashMap 和HashTable的区别,底层实现是什么
a. HashMap
没有synchronized修饰 线程不安全 允许key,value为null
b. HashTable
有syn 线程安全的,效率很低 不允许key/value为null
c.HashMap实现
底层原理:
数组+链表实现,数组长度为2的幂 jdk8 :链表高度到8,数组长度超过64,链表转变为红黑树(平衡二叉树),元素以内部类node节点存在 · 计算key hash值,二次hash然后对数组长度取模,对应到数组下标; · 如果没有产生hash冲突(下标位置没有元素),则直接创建node存入数组 · 如果产生冲突,先进行equals比较,相同则取代该元素,不同则判断表高度插入链表,链表高度达到8并且数组长度达到64则会转变为红黑树,长度低于6则将红黑树转回链表 · key为null,放到下标为0的位置
数组扩容:
数组定义静态的,长度固定,hashMap可以一直放值小于定义值,超过定义的范围,根据扩容因子会重新创建新数组,然后copy进新数组,完成扩容。
12.ConcurrentHashMap原理,jdk7和8的区别
a. jdk7:
数据结构:ReentrantLock+Segment+HashEntry数组(里面链表),一个segment包含一个HashEntry,每个HashEntry又是一个链表。 元素查询:二次hash,第一次hash定位到Segment,第二次hash定位到元素所在的链表头部 锁:Segment分段锁 Segment继承了ReentranLock,锁定操作的Segment,其他的Segment不受影响,并发度为segment个数,可以通过构造函数指定,数组扩容不会影响其他的segment。 get方法无需加锁,volatile保证的。
b. jdk8:
数据结构:
synchronized (hash扩容)+ CAS (乐观锁)+ Node + 红黑树,Node的val和next都用volatile修饰,保证可见性查找,替换,赋值操作是CAS。
锁:
锁链表的head节点,不影响其他元素的读写,锁的力度更细,效率更高,扩容时会阻塞所有的读写操作,因为当前为并发扩容
读操作无锁:
Node的val和next使用volatile修饰,读写线程对该变量互相可见 数组用volatile修饰,保证扩容时被读线程感知
13. 如何实现一个IOC容器
a.配置文件配置包扫描路径
b.递归包扫描获取.class文件
c. 反射、确定需要交给IOC管理类
d. 对需要注入的类进行依赖注入
详细描述: 配置文件中指定需要扫描的包路径 定义一些注解,分别表示访问控制层,业务服务层,数据持久化层,依赖注入注解,获取配置文件的注解 从配置文件中获取需要扫描的包路径,获取到当前路径下的文件信息及文件夹信息,我们当前路径下所有以.class结尾的文件添加到一个Set集合中进行存储。 遍历set集合,获取在类上有指定注解类,并将其交给IOC容器,定义一个安全的Map用来存储这些对象 遍历IOC容器,获取每一个类的实例,判断里面是否有依赖其他类的实例,然后进行递归注入