String, StringBuffer, StringBuilder的区别
String#equals()和Object#equals()有啥区别
String s1 = new String(“abc”)创建了几个对象
面向对象和面向过程的区别
面向对象会先抽象出对象,然后用对象执行方法的方式来解决问题 面向过程会把解决问题的过程拆成一个个方法,通过一个个方法来执行解决问题
面向过程具有良好的性能,但扩展性较差,面向对象具有较好的扩展性,但性能较差。
创建一个对象用啥运算符?对象实体与对象引用有何不同
创建一个对象用new运算符
对象实体与对象引用的区别
- 对象实体存储在堆中。
- 对象实体指向对象实体。
- 一个对象引用可以指向 0 个或 1 个对象(一根绳子可以不系气球,也可以系一个气球)。
- 一个对象可以有 n 个引用指向它(可以用 n 条绳子系住一个气球)。
对象的相等和引用相等的区别
对象相等是指内存中的内容是否相等
引用相等时指指针内存地址是否相等
如果一个类没有声明构造方法,该程序能正确执行吗
可以的
- 系统会生成一个默认的无参构造器
当我们如果实现有参构造器,最好手动加一个无参构造器,这个可以帮助我们少踩坑。
构造方法有啥特点?是否可被override
- 名字与类名相同。
- 没有返回值。
- 自动执行,在生成类的对象时,构造方法会自动执行,无需显式调用。
- 构造方法不能被重写,只能被重载。
面向对象三大特怔
封装
- 简单来说就是将一个对象的属性封装在一起,对外仅仅暴露方法调用。(比如你用空调遥控器时,空调遥控器内部的细节不知道,但你可以通过它提供的按钮来使用)
继承
- 子类拥有父类的属性和方法(私有方法和私有属性有但不能继承)。提高代码的复用性,程序的可维护性。
多态
- 一个对象可以有多种状态,即父类引用指向子类的多种实例。
接口和抽象类有啥共同点和区别
接口和抽象类的共同点
- 实例化: 接口和抽象类都不能直接实例化,只能被实现(接口)或继承(抽象类)后才能创建具体的对象
- 抽象方法: 接口和抽象类都可以包含抽象方法。抽象方法没有方法体,必须在子类或实现类中实现。
接口和抽象类的区别 接口和抽象类在设计动机上有所不同。
-
接口的设计是自上而下的。我们知晓某一行为,于是基于这些行为约束定义了接口,一些类需要有这些行为,因此实现对应的接口。
-
抽象类的设计是自下而上的。我们写了很多类,发现它们之间有共性,有很多代码可以复用,因此将公共逻辑封装成一个抽象类,减少代码冗余。
简单来说就是接口是先规范然后去实现,抽象是先实现然后再抽象出来一个类。
深度拷贝和浅拷贝了解吗?啥是引用拷贝?
-
浅拷贝:浅拷贝后的对象和原对象共享引用对象的实例。
-
深拷贝:会重现创建一个实例,使得深拷贝后的对象与原对象完全独立。修改一个对象不会影响另一个对象。
-
引用拷贝就是两个不同的引用指向同一个对象
Object类的常见方法有哪些
== 和 equals()的区别
- == 对于基本数据类型就是比较值,而对于引用类型就是比较对象的内存地址
- equals() 不能用于判断基本数据类型的变量,只能用来判断两个对象是否相等。equals()方法存在于Object类中,而Object类是所有类的直接或间接父类,因此所有的类都有equals()方法。
hashCode()有啥用
hashCode用于返回对象的哈希码,确定该对象在哈希表中的索引位置。
为啥要有hashCode
大大提高索引速度,从而提高执行速度。
为啥重写equals()时必须重写hashCode()方法
因为根据业务来说我们想的时equals()判断的相等就一定相等,而不重写的hashCode返回的是对象的哈希码,这与我们最初的想法相违背,所以必须重写hashCode()。
String, StringBuffer, StringBuilder的区别
- 可变性: String不可变,StringBuilder可变,StringBuffer可变。
- 线程安全性: String中的对象是不可变的,可以理解为常量,线程安全。StringBuffer安全,加了同步锁。StringBuilder并没有对方法进行加同步锁,所以不安全。
- 性能: String性能最低,因为每次改变时生成的是一个新的String对象。StringBuffer,StringBuilder性能较高。
总结:
- 操作少量的数据: 适用 String
- 单线程操作字符串缓冲区下操作大量数据: 适用 StringBuilder
- 多线程操作字符串缓冲区下操作大量数据: 适用 StringBuffer
String为啥是不可变的
-
1.String的类是用final修饰的,不可以被其他类继承,因此方法不能被重写,里面的数据都不能被改变。
-
2.String的char数组是私有的而且用final修饰,因此不能改变其字符数组的引用变量,因此改变不了String。
字符串拼接用 “+” 还是StringBuilder
字符串拼接用StringBuffer,因为用"+“拼接的话底层会创建一个新的StringBuilder对象(对于大多数场景比如说循环)比较耗时间,效率比较低。
String#equals()和Object#equals()有啥区别
String的equals()会比较字符串是否相等而Object的equals会比较内存的地址是否相等。
字符串的常量池了解过吗
字符串的常量池是JVM为了提升性能和减少内存消耗针对字符串(String类)专门开辟的一块区域,主要是为了避免字符串的重复创建。
创建String对象的两种方式以及不同
String s1 = new String(“abc”)创建了几个对象
这得分情况讨论
- 1.如果是常量池中已经存在"abc"则创建一个对象。(即s1直接指向常量池中的"abc”)
- 2.如果是常量池中不存在"abc"则创建二个对象。(即首先在常量池中创建"abc",然后s1指向常量池中的"abc")
String#intern方法有啥作用
intern方法是一个本地方法,目的返回字符串在常量池中的引用
String 类型的变量和常量做“+”运算时发生了什么
- 对于编译期可以确定值的字符串,也就是常量字符串 , jvm 会将其存入字符串常量池。并且,字符串常量拼接得到的字符串常量在编译阶段就已经被存放字符串常量池, 这个得益于编译器的优化。
- 引用的值在程序编译期是无法确定的,编译器无法对其进行优化。(可以加final进行优化)