第一题:Java 创建对象有哪⼏种⽅式?
Java 中有以下四种创建对象的⽅式:
- new 创建新对象
- 通过反射机制
- 采⽤ clone 机制
- 通过序列化机制
前两者都需要显式地调⽤构造⽅法。对于 clone 机制,需要注意浅拷⻉和深拷⻉的区别,对于序列化机制需要明确其实现原理,在 Java 中序列化可以通过实现 Externalizable 或者 Serializable 来实现
第二题 .Integer a= 127,Integer b = 127;Integer c= 128,Integer d =128;相等吗?
答案是 a 和 b 相等,c 和 d 不相等。
- 对于基本数据类型==⽐较的值
- 对于引⽤数据类型==⽐较的是地址
Integer a= 127 这种赋值,是⽤到了 Integer ⾃动装箱的机制。⾃动装箱的时候会去缓存池⾥取 Integer 对象,没有取到才会创建新的对象。
如果整型字⾯量的值在-128 到 127 之间,那么⾃动装箱时不会 new 新的 Integer 对象,⽽是直接引⽤缓存池中的Integer 对象,超过范围 a1==b1 的结果是 false
public static void main(String[] args) {
Integer a = 127;
Integer b = 127;
Integer b1 = new Integer(127);
System.out.println(a == b); //true
System.out.println(b==b1); //false
Integer c = 128;
Integer d = 128;
System.out.println(c == d); //false
}
什么是 Integer 缓存?
因为根据实践发现⼤部分的数据操作都集中在值⽐较⼩的范围,因此 Integer 搞了个缓存池,默认范围是 -128 到127,可以根据通过设JVMXX:AutoBoxCacheMax= 来修改缓存的最⼤值,最⼩值改不了。
实现的原理是 int 在⾃动装箱的时候会调⽤ Integer.valueOf,进⽽⽤到了IntegerCache。
很简单,就是判断下值是否在缓存范围之内,如果是的话去 IntegerCache 中取,不是的话就创建⼀个新的Integer 对象。
IntegerCache 是⼀个静态内部类, 在静态块中会初始化好缓存值
private static class IntegerCache {
……
static {
//创建Integer对象存储
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
……
}
}
第三题.Object 类的常⻅⽅法?
Object 类是⼀个特殊的类,是所有类的⽗类,也就是说所有类都可以调⽤它的⽅法。它主要提供了以下 11 个⽅法,⼤概可以分为六类:
对象⽐较:
- public native int hashCode() :native ⽅法,⽤于返回对象的哈希码,主要使⽤在哈希表中,⽐如 JDK 中的HashMap。
- public boolean equals(Object obj):⽤于⽐较 2 个对象的内存地址是否相等,String 类对该⽅法进⾏了重写⽤户⽐较字符串的值是否相等。
对象拷⻉:
- protected native Object clone() throws CloneNotSupportedException:naitive ⽅法,⽤于创建并返回当前对象的⼀份拷⻉。⼀般情况下,对于任何对象 x,表达式 x.clone() != x 为 true,x.clone().getClass() ==x.getClass() 为 true。Object 本身没有实现 Cloneable 接⼝,所以不重写 clone ⽅法并且进⾏调⽤的话会发⽣ CloneNotSupportedException 异常。
对象转字符串:
- public String toString():返回类的名字@实例的哈希码的 16 进制的字符串。建议 Object 所有的⼦类都重写这个⽅法。
多线程调度:
- public final native void notify():native ⽅法,并且不能重写。唤醒⼀个在此对象监视器上等待的线程(监视器相当于就是锁的概念)。如果有多个线程在等待只会任意唤醒⼀个。
- public final native void notifyAll():native ⽅法,并且不能重写。跟 notify ⼀样,唯⼀的区别就是会唤醒在此对象监视器上等待的所有线程,⽽不是⼀个线程。
- public final native void wait(long timeout) throws InterruptedException:native ⽅法,并且不能重写。暂停线程的执⾏。注意:sleep ⽅法没有释放锁,⽽ wait ⽅法释放了锁 。timeout 是等待时间。
- public final void wait(long timeout, int nanos) throws InterruptedException:多了 nanos 参数,这个参数表示额外时间(以毫微秒为单位,范围是 0-999999)。 所以超时的时间还需要加上 nanos 毫秒。
- public final void wait() throws InterruptedException:跟之前的 2 个 wait ⽅法⼀样,只不过该⽅法⼀直等待,没有超时时间这个概念
反射:
- public final native Class<?> getClass():native ⽅法,⽤于返回当前运⾏时对象的 Class 对象,使⽤了 final关键字修饰,故不允许⼦类重写。
垃圾回收:
- protected void finalize() throws Throwable :通知垃圾收集器回收对象。
第四题 List和Set的区别
- List:有序,按对象进⼊的顺序保存对象,可重复,允许多个Null元素对象,可以使⽤Iterator取出
所有元素,在逐⼀遍历,还可以使⽤get(int index)获取指定下标的元素 - Set:⽆序,不可重复,最多允许有⼀个Null元素对象,取元素时只能⽤Iterator接⼝取得所有元素,在逐⼀遍历各个元素
第五题 ArrayList和LinkedList区别
-
⾸先,他们的底层数据结构不同,ArrayList底层是基于数组实现的,LinkedList底层是基于链表实现的
-
由于底层数据结构不同,他们所适⽤的场景也不同,ArrayList更适合随机查找,LinkedList更适合删除和添加,查询、添加、删除的时间复杂度不同
-
另外ArrayList和LinkedList都实现了List接⼝,但是LinkedList还额外实现了Deque接⼝,所以LinkedList还可以当做队列来使⽤
如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!