Tutorial Study Image

Java 面试问题

Java 虚拟机或 JVM 是一个虚拟机或抽象规范。当 JVM 安装在计算机上时,它可以帮助运行 Java 字节码,而无需考虑计算机硬件的复杂性。

Java 运行时环境。 JRE 只是一个容器,它同步 Java 类库和 (JVM) Java 虚拟机。 JVM 使用 JRE 提供的类库来运行 Java 字节码,为之提供环境。

1. 可移植性:由于 Java 程序被编译成平台无关的字节码,因此可以在任何机器上运行,而无需考虑硬件。简而言之,我们可以说 Java 是平台无关的。出于同样的原因,它是一种架构中立的语言。

2. 面向对象:在 Java 中,一切皆对象。

3. 高性能:由于其即时编译器(Just-in-time compiler)可以即时编译,Java 程序的性能相当快。

4. 安全:Java 的公钥加密使其成为一种安全的语言。

6. 健壮性:由于其编译时和运行时错误检查,Java 犯错的可能性较低。

Java 运行时环境和 Java 虚拟机。 Java 虚拟机是一组规范,而 JRE 是该规范的实际环境。 JVM 将字节码转换为机器语言,而 JRE 拥有此过程所需的二进制文件和类库。

Java 开发工具包 (JDK) 是一个基于平台的开发包,可用于 Java 应用程序开发。它包括用于 Java 程序开发、编译和执行的工具。

是的,实际上 JDK(Java 开发工具包)包含了开发工具和 Java 运行时环境。Java 运行时环境包含类库和 Java 虚拟机规范。

JIT 是高性能编译器“即时编译器”(Just in Time Compiler)的缩写。与一次性编译整个代码然后运行的传统编译器不同,JIT 会即时编译代码。

因此,它们可以创建更快的可执行机器代码。

Java 既是解释型语言也是编译型语言。Java 代码首先被编译成字节码,然后字节码由 Java 虚拟机解释。

Java 拥有即时编译器,它不是批量编译代码,而是即时编译代码。编译后的代码是字节码,它本身就是一组执行速度快的操作,可以快速转换为依赖于机器的代码。

此外,Java 使用多线程,这意味着 Java 虚拟机管理各种线程,每个线程都可以执行一个任务,并且多个线程可以共存。

程序的每个部分都被分配给一个线程,并且线程可以共存。这使得并发执行成为可能,并充分利用了 CPU。

JDB 是 JAVA Debugger 的缩写。它是一个命令行工具,可以帮助您进入 Java 类并调试代码。

关键字是 Java 中的保留字。这些是用于编程语言特殊目的的特殊文本。这些单词不能用作标识符。

标识符是 Java 中事物的名称。 Java 中的事物可以是变量、类和函数。

字母(大写和小写)、_、$ 和数字可以是 Java 标识符的一部分。每个标识符必须至少有一个非数字字符。标识符不能以数字开头,其余可以是数字、_、$ 和字母或它们的组合。

在 Java 中,变量的作用域在 {} 之间,即在代码块中。局部变量是属于方法、构造函数或代码块的变量。在 Java 中,通常没有全局变量的概念,但所有成员变量在方法或构造函数外部声明时都被视为全局变量。这是因为它们可以在任何成员函数中访问。

示例



class ExampleGlobalLocal

{

     static int ExGlobal; //This variable acts as a global variable

     static void ExMethod()

     {

          int Ex>0;

          System.out.println(ExOnelocal);

          System.out.println(ExGlobal);

 

     } 

}

变量是容器,而字面量是它们的值。变量具有类型、名称和值。

示例

int a = 0

这里 0 是字面量,a 是变量。

Java 中有 8 种原始数据类型。它们是:

1. byte:存储范围从 -128 到 127 的数字。

2. short:存储范围从 -32768 到 32767 的整数。

3. int: 可以存储从 -2^31 到 (2^31)-1 的整数。

4. long:long 数据类型可以存储从 -2^63 到 (2^63)-1 的数字。

5. float:此数据类型可以存储小数,单精度 32 位 IEEE 754 浮点数。

6. double:此数据类型可以存储比 float 更大的小数。可以存储双精度 64 位 IEEE 754 浮点数。

7. boolean:布尔数据类型有两个可能的值:True 和 False。

8. char:存储字符。它们以 16 位 Unicode 编码字符的形式存储。

 

int:存储整数。

作用域是指变量可访问的代码区域。不同类型的变量作用域不同。例如,实例变量的作用域在类中(静态方法除外);类变量的作用域在类中;局部变量的作用域在代码块内。

在 Java 程序中,如果将一个值赋给不同类型的变量,则这两种类型可能不兼容。如果数据类型兼容,Java 会自动执行转换,称为自动类型转换;如果不兼容,则需要显式转换。

C++ 是平台相关的,而 Java 是平台无关的。

C++ 支持运算符重载,而 Java 不支持。

在 C++ 中可以使用指针编写程序,但在 Java 中,程序不能使用指针。

 

用于运行时数据管理,用于存储局部变量和结果,类区域用于存储每个类的数据,程序计数器用于当前执行地址,以及本地方法栈用于存储运行程序的本地方法。

要成为一门完全面向对象的编程语言,所有“事物”都应该是对象。但在 Java 中,使用了非对象(原始数据类型),如 boolean、byte、char 等。

构造函数是一个初始化对象的类方法。此方法与类名相同。创建对象时会自动调用它。

默认构造函数不接受任何参数。而参数化构造函数可以通过传递的参数值来初始化对象。

复制构造函数是接受对象作为参数并复制其特征以创建新对象的类方法。

单例类是其构造函数是私有的类。之所以这样命名,是因为一次只能创建一个类的实例。

重写意味着修改现有类,而重载是使用相同名称的类执行不同功能的用法。

Java 中的类型安全意味着不允许程序访问不安全的内存位置。换句话说,每个对象都会被分配一个特定的内存块,并且每个对象只能访问对其有效的内存块。

枚举数据类型或 **enum** 是 Java 中的一个特殊类,它代表一组常量。

示例

enum Languages {
  English,
  Dutch,
  Latin
}

 

将浮点数转换为整数,截去小数部分。

区分 BigDecimal 和 float?

构造函数链是从一个构造函数调用另一个构造函数的过程。这可以通过两种方式实现:使用 `this()` 从同一类进行构造函数链,以及使用 `super()` 从子类到父类进行构造函数链。

`final` 关键字可用于类以创建 `final` 类。这些类不能进一步继承。如果另一个类尝试扩展 `final` 类,Java 会抛出错误。

1. Final 变量:当 `final` 关键字用于变量时,变量的值在赋值后不能更改。

2. Final 方法:当 `final` 关键字应用于方法时,该方法永远不能被重写。

3. Final 类:当 `final` 关键字应用于类时,它们不能被继承。

public 是函数的可访问说明符。public 意味着该方法可以被任何其他类访问。

static 是一个关键字,意味着在引用此方法之前不需要创建类的实例。

void 意味着该方法不返回任何内容。

main 是该方法的名称。

String 是传递的参数类型。

args[] 是在运行代码时通过命令行传递值并接收它们的参数。

 

为了将原始数据类型(如 int、bool、char 等)转换为它们各自的类(如 Integer、Boolean、Character 等),我们可以使用包装类。例如,Integer 是 int 类型的包装类。

简单来说,集合是 Java 中任何一组对象。而 Java 集合框架是特殊的,它是一组接口和类,有助于高效地存储和处理数据。该框架有几个有用的类,它们具有有用的函数,可以帮助编程。

当一个值最初被赋给一个变量时,如果稍后赋给另一个值,而后者与前者类型不同,为了使它们兼容,我们可以转换数据类型。

例如

float num0 = 100.99;
long num1 = (long)num;

方法调用与过程体的链接称为绑定。如果在编译时完成此链接,则称为静态绑定;如果在运行时完成链接,则称为动态绑定。

重载允许一个类拥有执行不同功能的同名方法。编译器通过查看参数来区分两者。这意味着要实现重载,我们必须更改参数的数量或类型。

而重写则允许子类拥有与父类同名的方法,并给出自己的实现。

接口是 Java 中类似类的概念,有助于实现完全抽象。接口的定义方式与类类似,但它没有方法定义,只有签名;变量默认为 static、final 和 public。

抽象类是不能拥有自身对象的类。相反,这个类可以被扩展。子类将从其父抽象类获得通用模板,子类可以进行自己的专业化。

`this` 关键字或 `this` 指针指向类的当前对象。

`super` 关键字或 `super` 指针指向当前实例的父对象。

变量的生命周期表示变量在内存中存在的时间。对于不同类型的变量,生命周期也不同。例如,实例变量的生命周期或变量在相应对象存在于内存中之前一直存在于内存中。对于类变量,生命周期直到程序结束;对于局部变量,生命周期直到控制离开相应的块。

在 Java 中,根据变量的作用域和生命周期,有三种类型的变量:

1. 实例变量:声明在类中,但在任何方法之外的变量称为 *实例* 变量。

2. 类变量:声明在类中,但在任何方法之外并且是 `static` 的变量称为类变量。

3. 局部变量:声明在方法或块内的变量。

示例

public class ExVarTypes{

           int n1, n2; //实例变量

           static int sum; //类变量

           int sum(int a, int b) //a 和 b 是局部变量

                {

                 n1 =a;

                 n2=b;

                 return a+b;

                }

}

 

所有对象都存储在堆中。每当使用 new 关键字创建新对象时,对象都会被分配到堆中。当声明新变量时,只创建引用;当使用 new 关键字时,会分配堆。

序列化是将对象转换为字节流的机制。而反序列化是反向过程,其中字节流用于在内存中重新创建相应的对象。

当一个类定义在另一个类内部时,这样的类称为嵌套类。

语法

class ClassA

{

            Class TheNestedClass

             {

              }

}

 

 

从内存中删除不再使用的对象的行为称为垃圾回收。在 Java 中,这是自动完成的。垃圾收集器线程会定期检查运行时堆,如果发现废弃对象(没有活动引用的对象),垃圾收集器线程会先调用 `finalize()` 方法来清理对象,然后将对象从内存中清除。

Java 中的堆结构分为:

1. 年轻代:年轻代进一步分为 Eden 空间和 Survivor 空间。一旦存储了对象,它就会存储在 Eden 空间中。当年轻代填满并运行 minor GC 时,幸存的对象将被移至 Survivor 空间。

2. 老年代:年轻代中的对象随着时间的推移会变老,并在达到阈值后移至老年代。当老年代填满时,会进行 major GC。

3. 永久代包含 Java 虚拟机所需的元数据。

3.

当创建了一个类的对象时,我们就说这个类被实例化了。

1. 单一继承:子类继承一个超类的特性。

2. 多层继承:一个派生类将继承一个基类,并且该派生类也充当其他类的基类。

3. 层级继承:一个类作为多个子类的基类。

4. 多重继承:一个类可以拥有多个超类并从所有父类继承特性。

5. 混合继承:它是上述两种或多种继承类型的组合。

封装是将数据和操作绑定到称为类的单个单元的过程。优点是:

  • 数据隐藏:用户不知道类的内部实现。
  • 提高灵活性:可以根据需要调整变量的访问。
  • 可重用性:封装还提高了可重用性,并易于根据新需求进行更改。
  • 代码易于测试:封装的代码易于单元测试。

多态是同一个实体或名称以不同形式存在的概念。

在 Java 中,有两种类型多态:

1. 编译时多态:也称为静态多态。方法重载和运算符重载属于此类。

2. 运行时多态:重写属于此类,因为对重写方法的函数调用仅在运行时解析。

它也称为动态方法分派。这是一个在运行时解析对重写方法的函数调用的过程。这种类型的多态是通过方法重写来实现的。

数据抽象是一种只向用户显示必要详细信息的概念。冗余的细节不会显示给用户。在 Java 中,抽象是通过接口和抽象类实现的。

抽象方法声明时没有实现。抽象方法应在子类中重新定义或重写。

Java 的访问修饰符是 **public**、**private** 和 **protected**。**public:** 当类的成员被 **public** 修饰符修改时,任何其他代码都可以访问该成员。

**private:** 当类的成员被指定为 **private** 时,只有同一类的其他成员可以访问该成员。
**protected:** 被声明为 protected 的成员可以在同一包内或在其他包的子类中访问。

当类没有指定访问修饰符时,成员具有 **default** 访问修饰符。它们只能在同一包内访问。

非访问修饰符是用于提供有关实体信息标记。这些实体可以是类、方法、变量或构造函数。Java 中有 7 个非访问修饰符,它们是:

1. Static:在创建其类的任何对象之前就可以访问。

2. Final:应用于变量时创建常量变量,应用于方法时防止方法重写,应用于类时防止继承。

3. Abstract:用于创建抽象类和方法。

4. Synchronized:确保同一时间只有一个线程可以访问一个资源。

5. Transient:当不想将某个变量的值保存在文件中时使用。

6. Volatile:用于使类线程安全。

7. Native:用于指示方法是在本地代码中使用(Java Native Interface)实现的。

 

扩大就是自动类型转换本身。当两种类型兼容,并且值是从较低数据类型赋给较高数据类型时,Java 会自动将类型从较低转换为较高,因此得名扩大。

在 Java 程序中,当将较高数据类型的值赋给较低数据类型的变量时,不会自动发生转换。在这种情况下,需要应用显式类型转换。这也被称为缩小。