目录
面向对象基础
创建一个对象用什么运算符?对象实体和对象引用有何不同?
1.new运算符,new创建对象实例(对象实例存放在堆内存中),对象引用指向对象实例(对象引用存放在栈内存中)。
2. 一个对象引用可以指向0个或1个对象,一个对象可以有n个引用 指向它。
对象相等和引用相等的区别?
-
对象相等(Object Equality):
- 对象相等指的是两个对象在逻辑上相等,即它们的内容相同或者表示相同的实体。
- 在 Java 中,可以通过重写
equals()
方法来实现对象相等的比较逻辑。通常在自定义类中需要重写equals()
方法,以便正确地比较对象的内容。 - 对象相等的比较是基于对象的内容进行的,而不是基于对象的引用。
-
引用相等(Reference Equality):
- 引用相等指的是两个引用变量引用的对象是否是同一个对象,即它们指向的内存地址是否相同。
- 在 Java 中,可以通过
==
运算符来比较两个引用变量是否引用同一个对象。 - 引用相等的比较是基于内存地址的,只有当两个引用变量指向同一个对象时,它们才是引用相等的。
代码示例
String str1 = new String("Hello");
String str2 = new String("Hello");
String str3 = str1;
// 对象相等
System.out.println(str1.equals(str2)); // true,内容相同
System.out.println(str1.equals(str3)); // true,引用相同
// 引用相等
System.out.println(str1 == str2); // false,引用不同
System.out.println(str1 == str3); // true,引用相同
在上面的示例中,str1
和 str2
是内容相同但引用不同的两个 String
对象,它们通过 equals()
方法比较返回 true
,表示对象相等;通过 ==
运算符比较返回 false
,表示引用不相等。而 str1
和 str3
是引用相同的两个对象,它们指向同一个内存地址,因此 ==
运算符比较返回 true
,表示引用相等。
类的构造方法的作用?
-
初始化对象: 构造方法用于初始化新创建的对象,为对象的成员变量赋予初始值,确保对象处于一个合适的状态。
-
创建对象: 构造方法负责创建类的对象。当通过
new
关键字实例化一个对象时,实际上是调用了该类的构造方法来创建对象的实例。 -
提供对象的初始化: 构造方法允许在创建对象时进行一些初始化操作,例如设置对象的初始状态、分配内存空间等。
总的来说,类的构造方法是用于创建和初始化对象的特殊方法,它确保对象在被创建后处于一个有效的状态,并允许在对象创建过程中进行必要的初始化和操作。
如果一个类没有声明构造方法,该程序能正确执行吗?
如果一个类没有显式声明构造方法,Java 编译器会自动为该类生成一个默认的无参构造方法(无参构造器)。因此,即使没有明确声明构造方法,该类仍然会有一个默认的构造方法。
当你创建该类的对象时,会调用默认的构造方法来初始化对象。如果你没有提供自定义的构造方法,Java 编译器会自动添加默认的构造方法,这个构造方法会执行一些默认的操作,例如将对象的成员变量初始化为默认值。
所以,即使没有显式声明构造方法,程序仍然能够正确执行,因为 Java 编译器会提供默认的构造方法。但是,如果你在类中定义了其他的构造方法(有参构造方法),并且没有提供无参构造方法,那么在创建对象时如果没有提供参数就会导致编译错误。因此,在有特殊需求时,需要显式声明构造方法,以确保程序的正确性。
构造方法有哪些特点?是否可override?
- 特点如下:
- 名字与类名相同。
- 没有返回值,但不能用void声明构造函数。
- 生成类的对象时自动执行,无需调用。
- 构造方法不能被重写,但是可以被重载,所以可以看到一个类中有多个构造函数
面向对象的三大特征?
-
封装(Encapsulation):
- 封装是将数据和操作数据的方法封装在一个单元内部,使其成为一个独立的、可控制的对象。
- 封装可以隐藏对象的内部细节,只暴露必要的接口给外部使用,提高了代码的安全性和可维护性。
- 封装也可以实现信息隐藏,使对象的内部状态只能通过对象的方法来访问和修改。
-
继承(Inheritance):
- 继承是指一个类可以基于另一个类进行扩展,并且继承了父类的属性和方法。
- 子类(派生类)可以继承父类(基类)的成员变量和方法,并且可以添加自己的新功能。
- 继承可以提高代码的复用性,避免重复编写相似的代码,同时也体现了类与类之间的关系。
-
多态(Polymorphism):
- 多态是指同一个方法调用在不同的对象上可以有不同的行为。
- 多态可以通过方法重载(Overloading)和方法重写(Overriding)来实现。方法重载指的是在同一个类中定义多个方法具有相同的名称但参数列表不同,而方法重写指的是子类可以重新定义父类中已有的方法。
- 多态可以提高代码的灵活性和可扩展性,使代码更易于理解和维护。
接口和抽象类有什么共同点和区别?
共同点:
- 都不能被实例化: 接口和抽象类都不能直接被实例化,只能被子类实现或继承后才能创建对象。
- 都可以包含抽象方法: 接口和抽象类都可以包含抽象方法,即没有具体实现的方法。子类需要实现接口中的所有抽象方法,或者在抽象类中实现所有抽象方法后才能创建对象。
- 都支持多态性: 接口和抽象类都支持多态性,即可以通过父类引用指向子类对象,实现不同对象的统一调用接口。
区别:
- 成员变量: 接口中只能包含常量(
public static final
),而抽象类中可以包含成员变量、常量、普通方法和抽象方法。 - 构造方法: 接口中不能包含构造方法,而抽象类可以包含构造方法,被子类继承时会调用父类的构造方法。
- 单继承和多实现: Java 中类是单继承的,即一个类只能继承一个直接父类,但一个类可以实现多个接口。因此,如果一个类已经继承了一个类,则不能再继承其他类,但可以实现多个接口。
深拷贝和浅拷贝区别了解吗?什么是引用拷贝?
-
浅拷贝(Shallow Copy):
- 浅拷贝是指在复制对象时,只复制对象本身和其内部的基本数据类型的成员变量,而不会复制对象内部的引用类型成员变量。新对象和原对象中的引用类型成员变量将引用相同的对象。
- 因此,对于浅拷贝的新对象和原对象来说,它们共享相同的引用类型成员变量,对其中一个对象的引用类型成员变量进行修改会影响另一个对象。
-
深拷贝(Deep Copy):
- 深拷贝是指在复制对象时,不仅复制对象本身,还会递归复制对象内部所有的引用类型成员变量,直到复制完所有的引用对象。
- 深拷贝生成的新对象和原对象完全独立,对新对象进行修改不会影响原对象,因为它们引用的是不同的对象。
-
引用拷贝:
- 引用拷贝是指在进行对象复制时,仅复制对象的引用(内存地址),而不复制对象本身或对象内部的成员变量。
- 对于引用拷贝而言,新对象和原对象都指向相同的内存地址,因此它们实际上是同一个对象。修改其中一个对象的成员变量会影响另一个对象,因为它们共享同一份数据。
在 Java 中,通过实现 Cloneable
接口和重写 clone()
方法可以实现对象的浅拷贝,但对于对象内部的引用类型成员变量,仍然是引用拷贝。要实现对象的深拷贝,可以通过序列化和反序列化、手动递归复制等方式来实现。
Java中是值传递还是引用传递,还是两者共存?
Java中只有值传递。
Java常见的类(Object,String)基础面试题
==和equals的区别?
-
==
运算符:==
运算符用于比较两个对象的引用是否相同,即判断两个对象是否指向同一个内存地址。- 如果两个对象的引用相同,则
==
运算符返回true
,否则返回false
。 - 对于基本数据类型,
==
运算符比较的是值是否相同;对于引用类型,==
运算符比较的是引用地址是否相同。
-
equals()
方法:equals()
方法是Object
类的方法,在子类中可以重写以实现特定的比较逻辑。- 默认情况下,
equals()
方法用于比较对象的引用是否相同,即与==
运算符的作用相同。 - 但是,许多类(如
String
、Integer
等)会重写equals()
方法以比较对象的内容是否相同,而不是引用地址。 - 如果一个类没有重写
equals()
方法,则默认继承自Object
类的equals()
方法,即只比较引用地址。
总的来说,==
运算符比较的是两个对象的引用地址是否相同,而 equals()
方法比较的是两个对象的内容是否相同。在实际开发中,需要根据具体情况选择合适的比较方式。