1、StringBuffer和StringBuilder的区别
共同点:两者都继承了抽象的字符串父类:AbstractstringBuilder。
区别
一:线程安全
1)StringBuffer:线程安全,原因:公共方法都是synchronized修饰。
2)StringBuilder:线程不安全,原因:公共方法没有synchronized修饰。
二:缓冲区
1)StringBuffer:拥有缓冲区。
2)StringBuilder:没有缓冲区。
三:性能
1)StringBuffer:有synchronized修饰,性能低于StringBuilder。
2)StringBuilder:没有synchronized修饰,性能高于StringBuffer。
总结:StringBuffer适用于多线程操作同一个StringBuffer的场景,StringBuilder适用于单线程场景。
2、StringBuffer和StringBuilder的默认容量大小
默认容量大小:两者默认都是16个字符。如下图:
扩容大小:两者都是为原来的2倍+2个字符。源码在AbstractStringBuilder类,如下图:
3、抽象类和普通类的区别
1)抽象类必须用abstract关键字标识,普通类不需要。
2)抽象类可以包含 abstract标识的抽象方法,抽象方法不用在抽象类中实现,普通类不能包含抽象方法。
3)抽象类是设计给子类继承,不能直接new实例化或匿名内部类实例化,普通类可以直接new进行实例化。
4、接口和抽象类的区别
1)接口是一个"接口”,抽象类是一个"类",两者的概念和应用场景不一样,这是接口和抽象类的主要区别。
2)接口可以多继承,抽象类只能单继承,意味着类与类只能单继承,而类与接口、接口与接口可以多继承。
3)接口不能写构造方法,抽象类可以写构造方法,因此抽象类是参与到类的实例化过程。
4)接口中的变量默认全是public static final修饰的常量,不能被外部修改,而抽象类可以有成员变量,允许通过自己的非抽象方法进行改变。
5、静态变量和实例变量的区别
静态变量:被static 修饰的变量,它属于类但不属于类的任何一个对象,一个类无论创建多少个对象,静态变量在内存中有且仅有一个,静态变量可以实现让多个对象共享内存。
实例变量:它属于对象实例,需要通过一个类的对象实例才能访问。
6、Java生成随机数
1)Math.random:线程安全,只能生成伪随机浮点数(double),需要进行转换才能生成其他类型的随机数。
2)java.util.Random:线程安全,提供了多种随机数生成选项,包括不同类型的随机数和种子设置,在多线程并发使用同一个实例性能不佳,适用于并发量不高的或者单线程环境。
3)java.util.concurrent.ThreadLocalRandom:提供了多种随机数生成选项,是多线程环境下的首选,每个线程都有自己的生成器,无需同步操作。
4)其他第三方:如Apache的commons-lang3开发工具包中的两个工具类:RandomUtils、
RandomStringUtils。
7、equals和hashCode的关系
1)如果两个对象使用equals()方法比较返回true,那么两个对象的hashCode()方法必须返回相同的值。因此重写equals()方法时必须重写hashCode()方法,否则在Java中(比如HashMap)会产生逻辑错误。
2)如果equals()方法比较返回false,hashCode()方法最好返回不同的值,避免hash冲突,提高哈希表性能。
此处引出一个问题:两个对象的equals()方法相等,hashCode()方法也会相等吗?
答案:不一定,但是严格意义上必须相等。
Java通用约定:两个对象equals相等,则它们的hashCode必须相等,反过来则不需要相等。
8、为什么重写equals就要重写hashCode
重写equals就要重写hashCode是Java编程的共识和规范。
如果重写equals方法而没有重写hashCode方法,就会造成对象equals相等而hashCode不相等。
Hash*相关的集合都是基于Hash表来实现,比如HashMap的底层数据结构就是以数组+链表为基础,其中的关键是数组索引下标的处理,而下标是根据传入元素的hashCode方法来决定。
在hashCode相等的情况下:
1)数组索引位置上有值,值相等则进行覆盖,不相等则加入到对应的链表中。
2)数组索引位置上没有值,则直接插入。
因此,如果两个对象的equals相等而hashCode不相等,它们就会不断插入到数组中,而不会进行覆盖,由此会带来Hash*相关的集合不能正常运行。
9、Java泛型
JDK 1.5开始引入泛型,泛型提供了编译时类型安全检测机制,可以在编译时检测到非法的类型。
泛型的本质就是参数化类型,可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
泛型中的T、R、K、V、E分别代表什么?
10、Java获取当前系统时间戳
1)使用System类(最常用)
long longTime = System.currentTimeMillis();
2)使用Date类
Date date = new Date();
long dateTime = date.getTime();
3)使用Calendar类
Calendar calendar = Calendar.getInstance();
long calendarTime = calendar.getTimeInMillis();
4)使用Instant类(Java 8+)
Instant instant = Instant.now();
long instantTime = instant.toEpochMilli();
第三篇基础面试题到此结束,本篇也是Java基础面试题最后一篇,后面将会收录(手撸)集合面试题,请各位看官老爷点一下您高贵的赞~