CodeGym /Java 博客 /随机的 /探索 Java 开发人员职位面试中的问题和答案。第五部分
John Squirrels
第 41 级
San Francisco

探索 Java 开发人员职位面试中的问题和答案。第五部分

已在 随机的 群组中发布
你好你好!如今,Java 开发人员的需求量很大。当然,我不能为你提供职位空缺,但我会尽力帮助你获得一些新知识并填补一些空白。那么让我们继续回顾一下 Java 开发人员面试问题。您可以在文章末尾找到评论前面部分的链接。 探索 Java 开发人员职位面试中的问题和答案。 第 5 - 1 部分

39. Java中的访问修饰符有哪些?说出他们的名字。它们有什么用?

我之前在一个有关用于实现封装的 Java 元素的问题中介绍了访问修饰符。但我还是要提醒你。Java 中的访问修饰符是描述授予特定 Java 组件的访问级别的关键字。存在以下访问修饰符:
  • public — 用此修饰符标记的元素是公共的。换句话说,字段和方法以及使用 public 修饰符声明的类对于其自己的包和外部包中的其他类都是可见的;
  • protected — 标有此修饰符的元素可以从当前包或派生类中其自己的类中的任何位置访问,即使它们位于其他包中;
  • 当未指示访问修饰符时,默认(或根本没有修饰符)隐式应用。它与前一个类似,只是它在其他包中找到的派生类中可见;
  • private——这是所有修饰符中最私密的。它只允许访问当前类中的元素。

40.说出静态和非静态方法的主要特征

主要区别在于静态方法属于类。事实上,您不需要创建此类的实例 - 可以仅从类类型调用静态方法。例如,假设我们有一个抚摸猫的静态方法:

public class CatService {
   public static void petTheCat(Cat cat) {
       System.out.println("Pet the cat: " + cat.getName());
   }
我们不需要CatService类的实例来调用它:

Cat cat = new Cat(7, "Bobby");
CatService.petTheCat(cat);
相比之下,普通方法绑定(属于)一个对象。要调用它们,您必须有一个将在其上调用该方法的实例(对象)。例如,假设我们的猫有一个非静态方法meow()

class Cat {
   public void meow() {
       System.out.println("Meow! Meow! Meow!");
   }
要调用此方法,我们需要一个特定的猫实例:

Cat cat = new Cat(7, "Bobby");
cat.meow();

41. 适用于静态和非静态方法的主要限制是什么?

正如我之前所说,普通(非静态)方法的主要限制是必须始终存在调用该方法的实例。但静态方法不需要这个。此外,静态方法不能使用对象元素的 this引用,因为现在该方法存在当前对象。

42. static关键字是什么意思?静态方法可以被重写或重载吗?

用static关键字标记的元素不属于类的实例,而是属于类本身。它是在类本身加载时加载的。静态元素对于整个程序是相同的,而非静态元素仅对于特定对象是相同的。以下元素可以是静态的:
  • 类的字段;
  • 类的初始化块;
  • 类的方法;
  • 一个类的嵌套类(当然,这也是同义反复)。
静态方法不能被重写:它属于类并且不被继承,但同时它可以被重载。

43. 一个方法可以同时是静态的和抽象的吗?

我已经在上一篇文章中回答过这个问题:方法不能同时是抽象的和静态的。如果一个方法是抽象的,则意味着必须在子类中重写它。但是静态方法属于类,并且不能被覆盖。这会产生矛盾,编译器会注意到这一点并对此感到不安。如果您发现自己处于这种情况,您应该认真考虑应用程序架构的正确性(提示:它显然有问题)。 探索 Java 开发人员职位面试中的问题和答案。 第 5 - 2 部分

44. 静态方法可以用在非静态方法中间吗?反之亦然?为什么?

我们可以在非静态方法中使用静态方法。没有什么可以阻止这一点。也就是说,相反的情况是不可能的:静态方法不能在不引用类的特定实例的情况下使用非静态方法。请记住,类的静态成员无权访问this引用:您可以拥有任意多个类的具体对象,并且每个对象都将包含一个this引用,这是一个自引用。那么如何确定使用哪个this引用呢?呃,你不知道。这就是为什么静态元素不能在没有引用特定对象的情况下引用非静态元素。基本上,静态方法只有在引用特定对象时才可以使用非静态方法。例如,作为方法参数出现的一个:

public static void petTheCat(Cat cat) {
   System.out.println("Pet the cat: " + cat.getName());
}
这里我们看到,在静态petTheCat()方法中调用getName ,这是Cat对象的普通非静态方法。

45.什么是接口?能有最终的界面吗?

我们还记得 Java 没有多重继承。接口是它的一种替代方案。接口就像一个非常精简的类。他们定义了功能,但没有具体的实现。该任务留给实现这些接口的类。接口示例:

public interface Animal {
    void speak();
}
类的接口实现示例

class Cat implements Animal {
 
   @Override
   public void speak() {
       System.out.println("Meow! Meow! Meow!");
   }
}
以下是有关使用接口需要了解的重要事项:
  1. 接口方法必须仅包含标头。它们不能有特定的方法体,即它们必须是抽象的(尽管它们不使用abstract关键字)。但也有例外:静态方法和默认方法,它们需要方法体。

  2. 一个类可以实现许多接口(正如我所说,接口是多重继承的替代方案)。接口名称在方法头中用逗号分隔:类 Lion 实现 Animal, Wild

  3. 接口是使用interface关键字创建的。

  4. 当类实现接口时,我们使用implements关键字。

  5. 实现某个接口的类必须实现其所有抽象方法,或者必须将自身声明为抽象。

  6. 使用接口的主要目的是实现多态性(使对象能够呈现多种形式)。

  7. 通常,方法的访问修饰符不在接口中指示:默认情况下它们是public 的,并且您不能指定public之外的修饰符。从 Java 9 开始,您可以在方法上使用private修饰符。

  8. 默认情况下,接口变量是static final。换句话说,它们是常量——它们必须始终直接在接口中初始化。

  9. 您无法创建接口的实例。

接口是否可以是final的问题的答案当然是否定的。事实上,拥有接口的全部意义在于实现它们。我们都记得很清楚,类级别的Final修饰符使得类不可继承,对于接口来说 - 不可实现。为什么我们需要一个我们无法实现和使用的接口?你是对的——我们不会!编译器也同意。:) 探索 Java 开发人员职位面试中的问题和答案。 第 5 - 3 部分实际上,从 Java 8 开始引入静态接口方法,这可能是有道理的,但这并不能改变接口不能是 Final 的事实。我只是非常肤浅地谈论了接口,因为这是一个广泛的话题。有关这方面的更多信息,请参阅有关 Java 中的接口 以及抽象类和接口之间的区别 的文章。

46. 静态字段可以在哪里初始化?

静态字段可以初始化:
  • 声明后立即使用等号 ( = );
  • 在静态初始化块中;
  • 在非静态初始化块中(但你需要明白,每次创建对象时,执行此初始化块时静态字段都会被覆盖;
  • 在类构造函数中。每次调用构造函数时(即每次使用此构造函数创建对象时),该字段都会被覆盖;
  • 在静态方法中;
  • 在非静态方法中;
  • 在嵌套的静态和非静态、本地和匿名类中。

47.什么是匿名类?

匿名类是没有自己的类型的类。我在说什么?当我们谈论接口时,我提到您无法创建对象的实例:您只能创建实现接口的类的实例。如果您不希望某个类实现接口但需要一个实现该接口的对象怎么办?这可能是该物体的唯一用途。而且您无需创建成熟的实现类。你会怎么做?这是正确的!通过使用匿名类! 探索 Java 开发人员职位面试中的问题和答案。 第 5 - 4 部分假设我们有一些Animal接口:

public final interface Animal {
   public void speak();
}
如果我们想使用匿名类来实例化给定的接口:

Animal cat = new Animal() {
   @Override
   public void speak() {
       System.out.println("Meow! Meow! Meow!");
   }
};
然后,您可以安全地使用该对象及其实现的talk()方法。换句话说,匿名类此时此地实现了接口及其所有抽象方法。否则,我们将无法创建接口/抽象类对象,因为会有未实现/抽象方法。正如我提到的,匿名类不仅用于实现接口的抽象方法,还用于实现抽象类的抽象方法。这种方法适用于对象被使用一次或给定方法实现仅需要一次的情况。无需创建一个单独的类来实现所需的抽象类/接口。但我也注意到,匿名类在工作中很少使用。原则上,普通班仍优先考虑。您可以在本文中 阅读有关匿名类的更多信息。

48.什么是原始类?

我认为这是一个误导性的问题,可能是一个欺骗性的问题,因为 Java 没有原始类这样的东西。只有我们之前考虑过的原始类型的概念。我们记得 Java 有 8 种基本类型:byteShortintlongfloatdoublecharboolean

49.什么是包装类?

在 Java 中使用基本类型的主要问题是它们不是类,而 Java 是一种 OOP 语言。也就是说,用这种语言编写的程序相当于对象之间的交互。但基元不是对象。它们没有方法,甚至没有Object类的标准方法。但是如果我们需要使用原语作为Map中的键怎么办?然后我们需要调用它的hashCode()方法。您还可以在那里调用它的equals()方法。然后怎样呢?在很多时候你需要一个类,而不是一个基元。这使得原语在程序中变得不可用和不受欢迎的元素,因为它们违反了 OOP 的理念。但情况并不像看起来那么糟糕。毕竟,Java 有原始包装器的概念。在 Java 中,每个基本类型都有一个双胞胎——包装类。
  • 字节->字节.class
  • ->短类
  • int ->整数类
  • ->长类
  • 浮动-> Float.class
  • ->双.class
  • 字符->字符.class
  • 布尔值-> Boolean.class
这些类型代表简单类型,但在成熟的类中具有许多不同且有用的方法。引入自动装箱和拆箱的概念是为了方便使用这些类。 自动装箱是在必要时将基本类型自动转换为其类似类(例如,将int转换为Integer)。 拆箱是相反的过程:将原始包装类自动转换为原始类型(例如,将Integer转换为int)。由于引入了原始包装类以及自动装箱拆箱过程,原始类型现在已成为 Java 作为 OOP 语言的成熟成员。 探索 Java 开发人员职位面试中的问题和答案。 第 5 - 5 部分为了更深入地讨论这个主题,我强烈建议阅读这篇文章

50.什么是嵌套类?它用在哪里?

嵌套类是一个本身是另一个类的成员的类。Java 中的嵌套类有 4 种: 1. 内部类 这种类直接在另一个类的主体中声明。内部类是非静态嵌套类,可以访问外部类的任何私有字段或实例方法。作为示例,让我们创建一个包含动物(斑马)的动物园:

public class Zoo {
   class Zebra {
       public void eat(String food) {
           System.out.println("Zebra eats " + food);
       }
   }
}
并不复杂,对吧?我们来看一个创建内部类实例的例子:

Zoo.Zebra zebra = new Zoo().new Zebra();
zebra.eat("apple");
正如您已经看到的,首先需要创建封闭类的对象。然后使用对象引用创建内部类的实例。我还想指出,内部类(非静态嵌套类)不能有静态方法或静态字段。这正是因为内部类与其外部类的实例隐式关联,因此不能在其内部声明任何静态方法。 2. 静态嵌套类 这些类与前面的类别类似,但它们在类声明中具有static访问修饰符。由于这种类无法访问外部类的非静态字段,因此它看起来更像是外部类的静态部分而不是内部类。但是这个类可以访问外部类的所有静态成员,甚至是私有成员。静态嵌套类的示例:

public class Zoo {
   static class Zebra {
       public void eat(String food) {
           System.out.println("Zebra eats " + food);
       }
   }
}
它的创建方式与之前的略有不同:

Zoo.Zebra zebra = new Zoo.Zebra();
zebra.eat("apple");
这里我们不需要外部类的对象来创建静态嵌套类的对象。我们只需要知道嵌套类的名称就可以在外部类中找到它。 3. 局部类 局部类是在方法体中声明的类。本地类的对象只能在封闭方法中创建和使用。例子:

public class Zoo {
   public void feed(String animal, String food) {
       switch(animal) {
           case "zebra":
               class Zebra {
                   public void eat(String food) {
                       System.out.println("Zebra eats " + food);
                   }
               }
               Zebra zebra = new Zebra();
               zebra.eat(food);
               ...
这是一个例子:

Zoo zoo = new Zoo();
zoo.feed("zebra", "apple");
如果您没有看到feed()方法 的代码,那么您甚至不会怀疑本地类的存在,不是吗?本地类不能是static瞬态的,但可以将其标记为抽象最终(其中之一或另一个,但不能同时使用这两个修饰符,因为同时使用这两个修饰符会产生冲突)。 4. 匿名类 上面我们已经讨论过匿名类,您会记得,它们可以从两个来源创建:接口和类。 使用它们的原因 使用 嵌套静态和非静态类是因为有时最好将小类嵌入到更通用的类中并将它们保持在一起,以便它们具有更高的内聚性和共同的目的。基本上,嵌套类可以让您增加代码的封装性。如果本地类仅在单个方法中使用,您可以选择使用该类。在这种情况下,我们是否需要将代码分散到应用程序中?不。话虽如此,我要补充一点,根据我的经验,我从未见过有人使用本地类,因为是否需要它们存在很大争议。当仅需要一次接口或抽象类的特定实现时,您可以使用匿名类。在这种情况下,无需创建具有实现的单独的、成熟的类。相反,我们保持简单并使用匿名类实现了我们需要的方法,使用了该对象,然后忘记了它(当然,垃圾收集器没有忘记)。本文将增强您对嵌套类的理解。

51.类可以有哪些访问修饰符?

类有不同类型,并且适用不同的访问修饰符:
  • 外部类可以具有public访问修饰符或根本没有修饰符(默认修饰符);
  • 内部类(非静态嵌套类)可以具有 4 个访问修饰符中的任何一个;
  • 嵌套静态类可以具有除protected之外的任何一个访问修饰符,因为该修饰符意味着继承,这与该类的任何静态成员相矛盾(静态成员不被继承);
  • 局部类只能有默认修饰符(即根本没有修饰符);
  • 匿名类没有类声明,因此它根本没有访问修饰符。
今天我们就到这里结束。再见!探索 Java 开发人员职位面试中的问题和答案。 第 5 - 6 部分
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION