Java基础面试题
1.JAVA中的几种基本类型,各占用多少字节?
八种
基本类型:
- 整数类型:byte(-128.127),int(-21E.21E),long,short(-32768.32768)
- 浮点类型:float,double
- 字符型:char(16)
- 布尔型:boolean(1)
引用类型:
- 类
- 接口
- 数组
2.String能被继承吗?为什么?
不可以,String有final修饰,final修饰的类是不可以被继承的。
3.String str=”a”和String str=new String(“a”)的区别
前者涉及自动装箱拆箱问题,实际编译代码时,Class内代码会变成valueOf方法,根据类型找到对应的方法执行
拿Integer类型举例那就是return Integer.toString(i);
而后者则是执行了构造方法
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
4.String, Stringbuffer, StringBuilder 的区别。
String被final修饰,不允许被继承,String是常量,创建后就不允许被更改。
StringBuilder字符串操作类,线程不安全
Stringbuffer是线程安全的,内部大部分方法都加上了同步处理。
5.ArrayList 和 LinkedList 有什么区别。
ArrayList是用动态数组实现的,在操作数组时,可能需要重新计算大小或者是更新索引。
LinkedList是用链表实现的,相比ArrayList添加删除比较快。
6.ArrayList的数组为什么要用transient修饰
我们知道transient主要是用于不想被序列化时才加上修饰,ArrayList的数组加上是因为数组未必已满,假如数组大小为10,但现在只有3个,那就没必要序列化整个数组了,因此ArrayList重写了writeObject和readObject遍历数组,只序列化有的元素。
7.讲讲类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,当 new 的时候, 他们的执行顺序。
父类静态代变量、
父类静态代码块、
子类静态变量、
子类静态代码块、
父类非静态变量(父类实例成员变量)、
父类构造函数、
子类非静态变量(子类实例成员变量)、
子类构造函数。
8.用过哪些 Map 类,都有什么区别,HashMap 是线程安全的吗,并发下使用的 Map 是什么,他们内部原理分别是什么,比如存储方式, hashcode,扩容, 默认容量等。
HashMap、HashTable、ConcurrentHashMap
HashMap
- 使用数组+链表实现
- 默认容量是16,默认加载因子是0.75,扩容方式是2N
- 线程不安全
HashTable跟HashMap相似,但方法使用了synchronized做修饰实现线程安全
- 默认容量是11,扩容方式是2N+1
- 线程安全
ConcurrentHashMap是数组+分段锁数组+链表实现的
参考:https://www.cnblogs.com/aspirant/p/11470928.html
9.有没有有顺序的 Map 实现类, 如果有, 他们是怎么保证有序的。
TreeMap和LinkedHashMap
(这里有一篇文章)link
参考:https://blog.csdn.net/czx2018/article/details/107428434
10.抽象类和接口的区别,类可以继承多个类么,接口可以继承多个接口么,类可以实现多个接口么。
- 抽象类和接口都不能实例化,抽象类可以被继承,接口可以被实现。
- 类只能继承一个类。
- 接口可以继承多个接口。
- 类可以实现多个接口。
11.继承和聚合的区别在哪
12.讲讲你理解的 nio和 bio 的区别是啥,谈谈 reactor 模型。
bio是同步阻塞IO,nio是非阻塞IO
13.反射的原理,反射创建类实例的三种方式是什么
14.反射中,Class.forName 和 ClassLoader 区别。
15.描述动态代理的几种实现方式,分别说出相应的优缺点。
JDK的底层是使用反射机制,需要有接口。
https://www.cnblogs.com/nicori/p/13386257.html
CGLIB是基于asm框架,通过生成动态代理类实现代理,代理效率高于jdk。
16.final 的用途
修饰类、变量、方法
17.写出三种单例模式实现。
懒汉(线程不安全)
饿汉
双重校验(基于懒汉加上synchronized保证线程安全)
https://www.cnblogs.com/nicori/p/11698240.html
18.如何在父类中为子类自动完成所有的 hashcode 和 equals 实现?这么做有何优劣。
19.请结合 OO 设计理念,谈谈访问修饰符 public、private、protected、default 在应用设计中的作用。
修饰符 | 同一个类 | 同一个包 | 不同包的子类 | 不同包的非子类 |
---|---|---|---|---|
private | √ | × | × | × |
default | √ | √ | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
访问修饰符,主要标示修饰块的作用域,方便隔离防护
20.深拷贝和浅拷贝区别。
浅拷贝只会增加一个指针指向已存在的内存地址。
深拷贝是申请一个新的内存地址,把指针指向这个新内存。
21.数组和链表数据结构描述,各自的时间复杂度
数组是在内存地址中连续存放的,如果需要新增,当要在其中插入或删除一条元素时,则需要移动大量元素。数组是固定的长度
链表则是通过元素指针连接起来的,每个结点包含两部分:一个是存储元素,一个是下一个结点地址指针。查询需要从头遍历一遍才能查到数据。
22.error 和 exception 的区别,CheckedException,RuntimeException 的区别
error是错误信息,指发生不可控的错误时,通常会通知用户并中止程序运行。
exception是异常信息,这个是程序流程的错误,可以使用try···catch来处理该异常。
23.请列出 5 个运行时异常。
- NullPointException
- ClassCastException
- IOException
- SQLException
- NoSuchMethodException
24.在自己的代码中,如果创建一个 java.lang.String 对象,这个对象是否可以被类加载器加载?为什么
不会被加载,类加载是使用双亲委托模型,java.lang.String已经在ClassLoader中加载过了,所以自己创建的是不会被加载的。
25.说一说你对 java.lang.Object 对象中 hashCode 和 equals 方法的理解。在什么场景下需要重新实现这两个方法。
==主要是用于区分两个变量的内存地址,equals则是比较内容是否相同。
hashCode是用于返回变量的哈希码。
当不同的数据类型就会有不同的比较方法,这时候就需要重写equals和hashCode
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
public int hashCode() {
return Integer.hashCode(value);
}
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
26.在 jdk1.5 中,引入了泛型,泛型的存在是用来解决什么问题。
泛型是参数化类型,允许数据类型被指定为一种参数,好处是在编译时可以检查类型,并进行自动和隐式的强制转换,提高代码重用性。
27.有没有可能 2 个不相等的对象有相同的 hashcode。
有,哈希码主要是作为一个映射,主要是为了查询快。
因此这里涉及哈希冲突,HashMap就是使用链表来解决哈希冲突的。
28.Java 中的 HashSet 内部是如何工作的。
http://wiki.jikexueyuan.com/project/java-collection/hashset.html