大家好,今天继续分析250+ Java开发者面试题。分析的前几部分:第一、第二、第三。那么让我们继续吧。
<类名>{继承父类}{接口的实现}
因此,我们拥有: {class 访问修饰符} - 只有public修饰符和缺少的访问修饰符(即default )可用于 class 。 {class static} - static是一个修饰符,表示该类是静态的,仅适用于内部类(其他类内部的类)。 {class Finality} - 正如我们所记得的,这是final修饰符,在它的存在下,类变得不可继承(来自盒子的示例 - String)。 {class abstraction} - 修饰符-abstract,表示该类可能有未实现的方法。该修饰符与final修饰符冲突,即类头中只能有其中之一,因为abstract修饰符意味着给定的类将被继承并且其抽象部分将被实现。而final表示这是该类的最终(final)版本,并且不能被继承。实际上,同时使用这两个修饰符是荒谬的,编译器不会允许我们这样做。 <class>是必需的关键字,指示类声明。 <class name>是一个简单的类名,它是特定Java类的标识符。完全限定类名由完全限定包名 + 组成。+ 简单的类名。 {继承自父类} - 使用extends关键字指定父类(如果有)。例如, ..扩展 ParentClass。 {interfaceimplementation} - 使用implements关键字指定此类实现的接口(如果有)。例如: ...实现 FirstInterface、SecondInterface ... 好吧,作为类头的示例,考虑Lion类的头,它继承自Cat并实现WildAnimal接口:
29. 是否可以在构造函数中使用 return ?
可以,但return右侧没有返回值。即可以使用return; 作为构造函数中计算时的辅助构造,以便紧急完成(中断)后续代码的执行并完成对象的初始化。例如,我们有一个类Cat,如果Cat无家可归 - isHomeless = true,我们需要完成初始化,而不填写其他字段(毕竟,它们对我们来说是未知的,因为猫无家可归):public Cat(int age, String name, boolean isHomeless) {
if (isHomeless){
this.isHomeless = isHomeless;
return;
}
this.isHomeless = isHomeless;
this.age = age;
this.name = name;
}
但当涉及到特定值时,构造函数不能使用 return 来返回值,因为:
- 当声明构造函数时,你不会有任何类似于返回类型的东西;
- 通常,构造函数在实例化期间被隐式调用;
- 构造函数不是方法:它是一种单独的机制,其唯一目的是初始化实例变量,而new运算符负责创建对象。
30. 构造函数是否可以抛出异常?
构造函数处理异常的方式与方法完全相同。而如果方法允许我们通过在方法头中写入throws <ExceptionType>来抛出异常,那么构造函数允许我们这样做,并且在继承和定义继承构造函数时,我们可以扩展异常类型。例如,IOException -> Exception(但反之则不然)。作为构造函数抛出异常的示例,我们以Cat类为例。假设在创建它时我们想从控制台输入姓名和年龄:public Cat() throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
this.name = reader.readLine();
this.age = Integer.parseInt(reader.readLine());
}
由于reader.readLine()抛出 IOException,我们在标头中将其指定为可能抛出的异常。
31. 类头由哪些元素组成?写一个例子
说到构成类头的元素,让我们看一个小图:- 强制组件将放在括号 <> 中
- 可选 - 在 {} 中
public final class Lion extends Cat implements WildAnimal
32. 方法头由哪些元素组成?写一个例子
同样,在查看构成方法头的元素时,请考虑一个小图表,其中:- 强制组件位于括号 <> 中
- 可选 - 在 {} 中
public static void main(String[] args) throws IOException
33. 如果基础对象中没有定义(但定义了另一个构造函数),则在后代对象中创建默认构造函数
我不完全理解这个问题本身,但也许这意味着,例如,在父级中我们有一些自定义构造函数:public Cat(int age, String name) {
this.age = age;
this.name = name;
}
因此,在祖先类中,我们肯定需要定义一个构造函数来填充(调用)父构造函数:
public class Lion extends Cat {
public Lion(int age, String name) {
super(age, name);
}
}
34.什么时候使用this关键字?
在 Java 中,这有两种不同的含义。1. 作为当前对象的引用,例如this.age = 9。也就是说,this引用它被调用的对象以及使用this 的代码所引用的对象。主要作用是增加代码的可读性,避免歧义。例如,如果内部类字段的名称和方法参数相同:public void setName(String name) {
this.name = name;
}
也就是说,this.name是对象名的字段 ,是方法参数,静态方法中不能使用this引用。2. this可以以方法调用的形式在构造函数中使用,例如this(value)。在这种情况下,它将调用同一类的另一个构造函数。简而言之,创建对象时可以同时调用两个构造函数:
public Cat(int age, String name) {
this(name);
this.age = age;
}
public Cat(String name) {
this.name = name;
}
当创建Cat对象并调用第一个构造函数时,该对象的两个字段都将被调用并成功初始化。有一些细微差别:
- this()只在构造函数中起作用。
- 对另一个构造函数的引用必须位于构造函数块(主体)的第一行。因此,不能在一个构造函数中调用给定类的多个(其他)构造函数。
35.什么是初始化器?
据我了解,在这个问题中我们讨论的是普通和统计初始化块。首先,让我们记住什么是初始化。初始化是创建、激活、工作准备、参数确定。使程序或组件进入准备使用状态。正如您所记得的,在对象创建期间,可以在声明时直接初始化类变量:class Cat {
private int age = 9;
private String name = "Tom";
或者通过构造函数在外部设置它:
class Cat {
private int age;
private String name;
public Cat(int age, String name) {
this.age = age;
this.name = name;
}
但还有另一种方法:通过初始化块设置内部对象变量,它看起来像类内部的 大括号{ } ,没有名称(如方法或构造函数):
class Cat {
private int age;
private String name;
{
age = 10;
name = "Tom";
}
也就是说,初始化块是创建对象时加载的一段代码。通常,此类块用于执行加载类时所需的一些复杂计算。这些计算的结果可以指定为变量的值。另外,除了常规初始化块之外,还有静态初始化块,它们看起来相同,但在大括号之前有static关键字:
class Cat {
private static int age;
private static String name;
static{
age = 10;
name = "Tom";
}
该块与前一个块完全相同。但是,如果常规对象在每个对象初始化时触发,则静态对象只会在类加载时触发一次。在这样的块中,通常也会为后续静态类变量的初始化进行一些复杂的计算。与静态方法相同的限制也适用于静态块:它不能使用非静态数据,也不能使用对当前对象的引用 - this。接下来,我们可以看到类的初始化顺序(及其祖先),以便更好地理解初始化块被触发的时刻。
36、继承一个类public class Child extends Parent,写出该对象的初始化顺序
当Child类被加载时,初始化顺序如下:- 父类的静态字段。
- 父类的静态初始化块。
- Child类的静态字段。
- Child类的静态初始化块。
- Parent类的非静态字段。
- 不是父类的静态初始化块。
- 父类的构造函数。
- Child类的非静态字段。
- 不是Child类的静态初始化块。
- Child类的构造函数。
37.你知道类(对象)之间有哪些关系?
Java中类之间的关系有两种类型:- IS-A关系
Lion IS-A Cat
(但不是每只猫都是狮子)接口的情况完全相同。如果Lion类实现了WildAnimal接口,那么它们也存在关系:
Lion IS-A WildAnimal
- HAS-A关系
Car HAS-A Passenger
反之亦然:如果Passenger引用了Car,那么关系如下:
Passenger HAS-A Car
38.你知道物体之间有哪些关联关系?
聚合和组合只不过是关联的特殊情况。 聚合是一种关系,其中一个对象是另一个对象的一部分。例如,乘客可能在车里。此外,可能有几位乘客,也可能根本没有(如果我们谈论的是特斯拉,则不需要司机)。例如:public class Car {
private List passengers = new ArrayList<>();
void setPassenger(Passenger passenger) {
passengers.add(passenger);
}
void move() {
for (Passenger passenger : passengers) {
System.out.println("Перевозка пассажира - " + passenger.toString());
}
passengers.clear();
}
}
也就是说,我们不关心乘客的数量(或者是否有乘客):Car类的功能不依赖于此。聚合还意味着当一个对象被另一个对象使用时,第一个对象可以在其他对象中使用。例如,同一个学生可以既是针织俱乐部的成员,又是摇滚音乐团体的成员,同时又加入了英语学习者团体。如您所知,聚合是类之间较松散的关联关系。当一个对象不仅是另一个对象的一部分,而且另一个对象的工作非常依赖于第一个对象时,组合是一种更加严格的关系。例如,汽车发动机。尽管发动机可以脱离汽车而存在,但离开汽车就毫无用处。好吧,汽车没有发动机就无法工作:
public class Car {
private Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
void startMoving() {
engine.start();
...
}
组合还意味着,当一个对象被另一个对象使用时,第一个对象不能属于其他对象。如果我们回到我们的例子,一台发动机只能属于一辆汽车,但不能同时属于两辆或更多辆汽车。今天我们可能就停在这里。
GO TO FULL VERSION