一、包装类和基本数据类型的区别
1、存储位置不同 基本数据类型 是存储到栈当中,尔包装类为对象存储到堆中
2、声明方式不同 包装类初始化需要使用 new 关键字进行声明
3、初始值不同 基本数据类型比如 int 初始为0 但是Integer 则为 null
二、== 和equals区别
1、 == 是运算符 如果是基本数据类型 比较的是两个存储的值 ,若果是对象 则比较的是两个对象的在队中的地址值,即是否是一个对象
2、equals 是object 方法 不能用于基本数据类型比较,对象比较的是两个对象在堆中的地址值
一般情况下如果对象如果不进行重写equals 原始object中的equals则与 == 一样 都是用来比较对象当前的地址值
但是在常用类中 都进行了equals 的重写 重写之后用来比较两个对象的内容是否相等
比如 常用的String 类 就是进行 equals 的重写
三、String类 常用方法 有哪些
1、append 、 split、 concat 、compareto、indexof 等等
四、hashcode 和 equals
1、所谓hashcode 就是 hash表中的位置,也就是说将对象的物理地址转换成一个整数 在将此整数通过一定的算法 得到hashcode
2、hashcode作用:其实hashcode 就是为了更快的查找到对象的存储地址的
3、hashcode 与equals 关系
比如说我现在有4个对象 A B C A如果通过算法得到 A 和B 和最后一个A的hashcode值相等都为1 ,hash表中现在有位置 1 2 3 三个位置, 那么 A和B 和第四个A对象则同时指向1位置,则 第一个A 和 第四个A hashcode 于B 都相同,同时指向hash表中1位置 , 那么通过equals 对比第一个A对象和第四个A对像值相等,由此可得出结论
1)hashcode 相等的两个对象 ,equals 不一定相等
2)equals相等的两个对象hashcode 值一定相同
所以我们在重写equals 时候一定要重写 hashcode 若果不重写hashcode 就会造成hashset、或者hashmap中出现多个一模一样的对象
五、String、 Stringbuffer、 StringBuilder 区别
String 声明的变量是不可变的,每一次操作都会生成新的对象
尔StringBuffer和 StringBuilder 都继承了AbstractStringBuilder抽象类 区别在于StringBuffer是线程安全的StringBuffer类里面所有方法都是通过synchronized关键字进行的加锁操作
StringBuilder 线程 是不安全的速度比StringBuffer操作速度快
六、抽象类 和接口的区别
1、抽象类是对于整体事务的一种抽象包扩属性、行为等等,接口只是对于行为的一种抽象
2、抽象类的存在就是为了继承,抽象类是一种模板式设计,而接口属于行为设计
3、抽象类可以包含抽象方法和普通方法,接口中只能存在抽象方法
七、Collections 和Collection
Collection是一个集合类
Collections 是一个工具类 包含排序方法等等
八、java集合
java中集合分为两种体系 Collection 和Map
Collection 接口
1、List 接口
1)ArrayList
2)LinkList
3) Vector
2、Set
1)HashSet
2) SortedSet
Map 接口
1)HashMap
2) SortMap
3) HashTable
各集合之间的区别
1、ArrayList 和LinkList、Vector
二者都属于现成不安全的而Vector 底层使用了 synchronized 所以是线程安全的
而ArrayList底层使用数组 相比直线查询速率较快
而LinkList 底层才用的事链表方式 所以增删速度较快
二者都是可重复的
2、set 和list
set 相比list 是不可重复的
3、hashset 和treeset
hashset 是无序的 TreeSet 采用自然排序
4、hashmap和 hashtable 的区别
hashtable 月hashmap底层都采用 数组 + 链表的模式 ,区别在于 hashtable 是线程安全的
但是hashtable 已经不建议使用,如果需要使用线程安全的Map 可以使用 CurrentHashMap
九、HashMap底层为什么使用数组+链表的模式
我看大部分说都是为了数组查询快,而链表增删块,结合两部分的优点,所以才使用数组+链表的模式,但是我感觉更多是为了减少hash冲突,如果使用数组不使用链表的情况下 每当hash冲突时就要对数组就行扩容处理,这种开销会非常大,所以我觉得当初设计者可能只是为了减少 因为hash冲突问题而导致频繁扩容的开销,所以才使用了 数组+ 链表模式
十、java实现多线程的几种方式
1、 实现runnable 接口
2、继承 Thread类 实现run方法
3、实现callable接口
其中runnable 和 callable 实现多线程的区别在于 callable 是可以有返回值的 而runnable 是没有的
十一、线程中run() 和 start() 方法有什么区别
run()方法 用来启动但不执行,可重复调用 ,start()方法用来执行线程代码,只能运行一次
十二、线程中sleep() 和 wait() 区别
1、方法来源不同 sleep()方法来源于Thread类 而 wait()来源于 object
2、sleep()不会释放锁,wait()会释放锁
3、sleep() 时间到了会自动唤醒 , wait() 可使用notify() 方法唤醒
十三、ThreadLocal
ThreadLocal 叫做线程变量 意思就是每个线程中得变量是线程独有的,与其他线程互不干涉
ThreadLocalMap ThreadLocalMap 是ThreadLocal得一个内部静态类,每个线程内都有一个ThreadLocalMap 变量, 以便又来让用户维护当前线程多个ThreadLocal
public class ThreadLocal<T> {
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
}
通过set 方法可以看出来 ThreadLocal得set 方法 原理 就是先获取到当前线程得引用,在获取到当前线程得ThreadLocalMap ,最终以当前ThreadLocal 实例作为key,value 则是实际要设置得值
偷了一张图 ,以便能更好得理解
十四、JMM
JMM 就是Java 内容模式 Java语言为了屏蔽掉各种硬件或者操作系统之间对内存访问得差异,而制定得一种对内存访问得规范,从而达到Java 程序在个平台并发访问都达到一致得效果
Java 规定所有变量都存到主内存中,而每个线程也有自己得内存工作空间,每个线程使用得变量都是在主内存拷贝过来自己,在到自己得工作内存中对变量副本进行计算,每个线程独立而互不影响,计算完毕后,需要把最后结果在刷回主内存,
整个JMM得建立围绕得就是 可见性,原子性,和有序性三个特性
-
原子性
所谓原子性,可以以事务处理去理解 就是当线程执行一个动作得时候,要么这个动作全部执行成功,要么不被执行,中间操作时不能被打断 -
可见性
当前线程修改变量后,保证其他线程立马可以观察到当前变量得变化 -
有序性
我们知道在使用单线程得时候 每一步执行命令都是按照顺序执行,但是当多线程同步操作的时候,我们在外面得角度观察线程得 执行顺序,他并不一定是按照我们预期得顺序进行执行,就保证不了所谓得有序性,因为编译器会优化相应得代码执行顺序以提高代码执行效率,这就是所谓得指令重排。
所以多线程得时候要保证有序性 ,和可见性,我们可以使用锁进行操作(synchronized 或者 lock)
多线程操作还会有另一个比较常见得问题 内存延迟同步(就是当前线程工作内存与主内存延迟同步)得问题同样利用锁得机制也可以解决 -
happen-before原则(先行发生)
就是当两个操作 A和B 如过A 操作先行执行 而B 操作执行之前能够感知到A 操作得结果 那么,就不需要进行指令重排的操作 ,JVM能够保证相应得执行顺序
十四、synchronized 和 ReentrantLock 的区别
- 应用层面synchronized 适用于类、方法、代码块加锁,ReentrantLock 使用于代码块
- 底层实现来说 synchronized 是jvm层面的锁 而ReentrantLock 实现lock类 属于api层面的锁
- 实现机制上面来说 synchronized 锁设计到 无锁、偏向锁、轻量级锁 、和重量级锁,而则是通过CAS自璇和AQS机制保证线程的原子性 通过volatile 配合 保证数据的可见性 以实现锁的机制
- synchronized 可以自动释放锁 而ReentrantLock 必须手动释放
- synchronized 唤醒 只能通过object wait()、notify()、notifyall() 要么随机唤醒一个线程 要么全部唤醒 而 lock 则可以通过await()、singal()进行精确唤醒
- synchronized 为非公平锁 而 ReentrantLock 可以通过参数控制为 公平锁还是非公平锁
十五、synchronized锁的都是什么
synchronized 语法上可以在三个方面或者三个维度加锁
-
修饰普通方法 锁的是当前方法的调用者
-
修饰静态方法 锁的是当前.class
-
修饰代码块 可以实现所当前实例对象的方法,这块重点锁一下
` public class Demo {
private Demo lock1 = new Demo ();
private Demo lock2 = new Demo ();public void locktest1() { synchronized (lock1) { while (true) { System.out.println("lock1"); } } } public void locktest2() { synchronized (lock2) { while (true) { System.out.println("lock2"); } } }
}`
当两个线程同时调用locktest1 和 locktest2 会发现都能获取到各自的锁
public class Demo {
public void demo1() {
synchronized (this) {
while (true) {
System.out.println("lock1");
}
}
}
public void demo2() {
synchronized (this) {
while (true) {
System.out.println("lock2");
}
}
}
}
两个线程同时调用demo1 和demo2 会发现只有一个线程能够获取到锁
只要一个线程获取到锁另一个只能阻塞等待前一个线程释放锁之后才能获取
- synchronized 从使用结果上可分为两种类型
类锁、 对象
可以通过八锁问题 更清晰、直观的了解到底是synchronized 锁的是什么
十六、反射
java 反射就是 在运行时 能够知道任意一个类的 属性于方法 并且能够调用对象的属性和方法,简单的说就是在运行时能够获取类的所有信息
获取类信息的几种方式
1、Object类的 getClass()方法
2、静态类.class
3、Class类的forname()方法
关于java 反射类的常用api 都在java.lang.reflect包下面
十七、JDK动态代理和CGLB动态代理的区别
JDK 代理原理上是通过委托机制进行代理的,而且只能代理实现接口的类
代理的类 和目标的类 实现同一个接口 InvocationHandler持有目标类,代理类委托InvocationHandler去调用目标类
CGLB 代理通过继承机制 代理类实现了目标类 重写了目标方法 通过回调函数MethodInterceptor调用父类方法
Jdk1.8 已经对 Jdk代理进行了优化效率高于CGLB执行效率,1.7 以前 效率是不如CGLB的
未完待续。。。。。。