JavaRush /Java 博客 /Random-ZH /Java 开发人员访谈问答分析。第 4 部分

Java 开发人员访谈问答分析。第 4 部分

已在 Random-ZH 群组中发布
大家好,今天继续分析250+ Java开发者面试题。Java 开发人员访谈问答分析。 第 4 - 1 部分分析的前几部分:第一第二第三。那么让我们继续吧。

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运算符负责创建对象。
Java 开发人员访谈问答分析。 第 4 - 2 部分

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. 类头由哪些元素组成?写一个例子

说到构成类头的元素,让我们看一个小图:
  • 强制组件将放在括号 <> 中
  • 可选 - 在 {} 中
{类访问修饰符}{类静态性}{类终结性}{类抽象} <类名>{继承父类}{接口的实现} 因此,我们拥有: {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接口:
public final class Lion extends Cat implements WildAnimal
Java 开发人员访谈问答分析。 第 4 - 3 部分

32. 方法头由哪些元素组成?写一个例子

同样,在查看构成方法头的元素时,请考虑一个小图表,其中:
  • 强制组件位于括号 <> 中
  • 可选 - 在 {} 中
{访问修饰符}{方法静态}{方法抽象}{方法终结性}{同步修饰符} {本机修饰符}<返回值><方法名称> <(> {方法参数} <)>{抛出异常} {访问修饰符 } — 所有访问修饰符均可用于该方法:publicprotecteddefaultprivate{method static} - static是一个修饰符,表示该方法是静态的,也就是说,它不绑定到对象,而是绑定到类。 {method Abstraction}abstract修饰符,表示该方法没有实现(主体)。为了正确操作,您还需要为提供该方法的类提供一个抽象修饰符。如在类头中,这个修饰符与final修饰符冲突,但除此之外,它还与static修饰符冲突,因为 抽象方法意味着重写后代中的方法,并且静态方法不会被重写。 {方法的最终性} -最终- 指示此方法不能被覆盖的修饰符。 {同步修饰符} -同步- 修饰符意味着该方法受到保护,不会从不同线程同时访问它。如果该方法不是静态的,它将关闭对象的 this 互斥体。如果该方法是静态的,它将关闭当前类的互斥锁。 {native 修饰符} -本机- 此修饰符指示该方法是用不同的编程语言编写的。 <return value>是方法应返回的值的类型。如果它不应该返回任何内容,则 void<方法名称>是方法的名称,它在系统中的标识符。 {方法参数}是方法采用的参数(参数):它们是实现其功能所必需的。 {可抛出异常} - throwsExceptionType - 此方法可以抛出的已检查异常的列表。作为方法头的示例,我将给出以下内容:
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);
   }
}
Java 开发人员访谈问答分析。 第 4 - 4 部分

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对象并调用第一个构造函数时,该对象的两个字段都将被调用并成功初始化。有一些细微差别:
  1. this()只在构造函数中起作用。
  2. 对另一个构造函数的引用必须位于构造函数块(主体)的第一行。因此,不能在一个构造函数中调用给定类的多个(其他)构造函数。
Java 开发人员访谈问答分析。 第 4 - 5 部分本文中有更多示例。

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";
   }
该块与前一个块完全相同。但是,如果常规对象在每个对象初始化时触发,则静态对象只会在类加载时触发一次。在这样的块中,通常也会为后续静态类变量的初始化进行一些复杂的计算。与静态方法相同的限制也适用于静态块:它不能使用非静态数据,也不能使用对当前对象的引用 - thisJava 开发人员访谈问答分析。 第 4 - 6 部分接下来,我们可以看到类的初始化顺序(及其祖先),以便更好地理解初始化块被触发的时刻。

36、继承一个类public class Child extends Parent,写出该对象的初始化顺序

当Child类被加载时,初始化顺序如下:
  1. 类的静态字段。
  2. 类的静态初始化块。
  3. Child类的静态字段。
  4. Child类的静态初始化块。
  5. Parent类的非静态字段。
  6. 不是父类的静态初始化块。
  7. 类的构造函数。
  8. Child类的非静态字段。
  9. 不是Child类的静态初始化块。
  10. Child类的构造函数。
Java 开发人员访谈问答分析。 第 4 - 7 部分这是一篇简短的文章,解释了实践中的初始化顺序。

37.你知道类(对象)之间有哪些关系?

Java中类之间的关系有两种类型:
  • IS-A关系
OOP 中的 IS-A 原则基于类继承或接口实现。例如,如果类Lion继承自Cat,我们就说LionCat
Lion IS-A Cat
(但不是每只猫都是狮子)接口的情况完全相同。如果Lion类实现了WildAnimal接口,那么它们也存在关系:
Lion IS-A WildAnimal
  • HAS-A关系
这种类型的关系基于其他类对类的使用,也称为“关联”。关联是一个类引用另一个类(甚至相互引用)。例如,Car类可以引用Passenger类,关系如下:
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类的功能不依赖于此。聚合还意味着当一个对象被另一个对象使用时,第一个对象可以在其他对象中使用。例如,同一个学生可以既是针织俱乐部的成员,又是摇滚音乐团体的成员,同时又加入了英语学习者团体。如您所知,聚合是类之间较松散的关联关系。当一个对象不仅是另一个对象的一部分,而且另一个对象的工作非常依赖于第一个对象时,组合是一种更加严格的关系Java 开发人员访谈问答分析。 第 4 - 8 部分例如,汽车发动机。尽管发动机可以脱离汽车而存在,但离开汽车就毫无用处。好吧,汽车没有发动机就无法工作:
public class Car {
   private Engine engine;

   public Car(Engine engine) {
       this.engine = engine;
   }

   void startMoving() {
       engine.start();
           ...
   }
组合还意味着,当一个对象被另一个对象使用时,第一个对象不能属于其他对象。如果我们回到我们的例子,一台发动机只能属于一辆汽车,但不能同时属于两辆或更多辆汽车。今天我们可能就停在这里。Java 开发人员访谈问答分析。 第 4 - 9 部分
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION