整理1000道Java面试题|从初级到高级,包含答案、小测、各类学习资源 第一:Java基础面试题 1. 为什么 Java 是一种平台无关语言? Java 语言是以这样一种方式开发的,它不依赖于任何硬件或软件,因为编译器编译代码,然后将其转换为可以在多个系统上运行的独立于平台的字节码。运行该字节码的唯一条件是机器中安装了运行时环境 (JRE)。 2. 为什么Java 不是纯粹的面向对象语言? Java 支持原始数据类型——byte、boolean、char、short、int、float、long 和 double,因此它不是纯面向对象的语言。 3. C/C++ 中使用指针。为什么Java不使用指针? 指针对于初学者来说非常复杂且不安全。Java 注重代码的简单性,指针的使用使其具有挑战性。指针的使用也可能导致潜在的错误。此外,如果使用指针,安全性也会受到影响,因为用户可以在指针的帮助下直接访问内存。 因此,通过在 Java 中不包含指针,提供了一定程度的抽象。此外,指针的使用会使垃圾收集过程变得非常缓慢和错误。与指针不同,Java 使用引用,因为它们不能被操纵。 4、你怎么理解实例变量和局部变量? 实例变量是类中所有方法都可以访问的变量。它们在方法外部和类内部声明。这些变量描述了一个对象的属性。 该类的每个实例都将拥有它独自的实例变量以供使用。如果对这些变量进行了任何修改,那么只有该实例会受到它的影响,而所有其他类实例将继续保持不受影响。 例子: 局部变量是存在于方法中并且只能在它们内部访问的那些变量。变量的使用仅限于当前方法范围。 例子:
5、数据封装是什么意思?数据封装是一种面向对象的编程概念,将数据属性及其行为隐藏在一个单中。它通过确保每个对象通过拥有自己的方法、属性和功能而独立于其他对象,帮助开发人员在开发软件时遵循模块化。它用于对象私有属性的安全性,因此用于数据隐藏的目的。
6. 谈一谈 JIT 编译器JIT 全称是 Just-In-Time,用于提高运行时的性能。它同时完成编译部分具有相似功能的字节代码的任务,从而减少代码运行的编译时间。编译器只不过是源代码到机器可执行代码的翻译器。但是 JIT 编译器有什么特别之处呢?让我们看看它是如何工作的:首先,Java 源代码 (.java) 到字节码 (.class) 的转换是在 javac 编译器的帮助下发生的。然后,JVM 在运行时加载 .class 文件,并在解释器的帮助下,将这些文件转换为机器可理解的代码。JIT 编译器是 JVM 的一部分。启用 JIT 编译器后,JVM 会分析 .class 文件中的方法调用并编译它们以获得更高效的本机代码。它还确保优化优先级方法调用。完成上述步骤后,JVM 将直接执行优化后的代码,而不是再次解释代码。这提高了执行的性能和速度。
7.你能分辨Java中的equals()方法和相等运算符(==)的区别吗? equals()==这是在 Object 类中定义的方法。它是 Java 中的运算符。此方法用于根据指定的业务逻辑检查两个对象之间的内容是否相等。对于引用数据类型来说,该运算符用于比较引用的地址是否相同。 笔记:在类中未重写 equals 方法的情况下,该类使用父类的 equals 方法的默认实现。Object类被认为是所有java类的父类。Object 类中的 equals 方法的实现使用 == 运算符来比较两个对象。可以根据业务逻辑覆盖此默认实现。 8. Java 中如何声明死循环? 死循环是那些无限运行而没有任何中断条件的循环。使用 For 循环: 使用while循环: 使用 do-while 循环: 9.简述构造方法重载的概念 构造方法重载是在类中创建多个名字相同,参数不同的过程。根据参数的数量及其对应的类型,由编译器来区分不同类型的构造函数。
此处定义了三个构造函数,但它们因参数类型和编号而异。 10. 说一说方法重载和重写。 在 Java 中,通过在由相同名称组成的同一类中引入不同的方法来实现方法重载。尽管如此,所有函数在参数的数量或类型上都不同。它发生在一个类中,并增强了程序的可读性。 方法返回类型的唯一区别不构成方法重载。
这两个函数具有相同的名称,但参数数量不同。第一种方法计算矩形的面积,而第二种方法计算长方体的面积。 方法重写是两个具有相同方法签名的方法存在于两个不同的类中的概念,其中存在继承关系。通过使用方法重写,子类可以实现特定的方法实现(已经存在于父类中)。让我们看一下这个例子:
这两个类方法都具有名称 walk 和相同的参数、距离和时间。如果调用子类方法,则父类方法 walk 将被子类的方法重写。 11. 在一个 Java 程序中,一个 try 块是否可以和多个 catch 块可以共存。 是的,可以存在多个 catch 块,但特定的方法应该先于通用方法,因为只有满足 catch 条件的第一个 catch 块才会被执行。给定的代码说明了相同的内容: 在这里,由于除以 0 (i / x),将执行第二个 catch 块。如果 x 大于 0,则第一个 catch 块将执行,因为 for 循环运行直到 i = n 并且数组索引直到 n-1。 12.解释final关键字在变量、方法和类中的使用。 在 Java 中,final 关键字用于定义常量。final修饰变量:当一个变量在 Java 中被声明为 final 时,该值一旦被赋值就不能被修改。如果任何值尚未分配给该变量,则它只能由类的构造函数分配。final修饰方法:声明为 final 的方法不能被其子类覆盖。构造函数不能被标记为 final,因为无论何时继承一个类,构造函数都不会被继承。因此,将其标记为 final 是没有意义的。Java抛出编译错误说 – final class:不能从声明为 final 的类继承任何类。但最终类可以扩展其他类以供其使用。 13、final、finally和finalize关键字的作用一样吗? 所有三个关键字在编程时都有自己的作用。 Final:如果需要对类、变量或方法进行任何限制,则 final 关键字会派上用场。final 类的继承和 final 方法的覆盖受 final 关键字的使用限制。合并 final 关键字后,变量值变为固定值。例子: 第二个语句会抛出错误。 最后:它是程序中存在的块,其中写入的所有代码都会执行,而不管异常处理如何。例子: Finalize:在对象的垃圾回收之前,调用 finalize 方法以便实现清理活动。jdk9中已经被废弃,例子: 14.什么时候可以使用super关键字? super 关键字用于访问父类的隐藏字段和覆盖的方法或属性。以下是可以使用此关键字的情况:访问父类的数据成员,当该类及其子类的成员名称相同时。在子类内部调用父类的默认构造函数和参数化构造函数。当子类覆盖它们时访问父类方法。 以下示例演示了使用 super 关键字时的所有 3 种情况。 15.静态方法可以重载吗? 是的!一个类中可以有两个或多个具有相同名称但输入参数不同的静态方法。 16. 静态方法可以覆盖吗?不!可以在子类中声明具有相同签名的静态方法,但在这种情况下不能发生运行时多态性。覆盖或动态多态发生在运行时,但静态方法被加载并在编译时静态地查找。因此,这些方法不能被覆盖。 17.垃圾收集的主要目标是什么?这个过程的主要目的是通过删除那些不可达的对象来释放Java程序执行过程中不必要的和不可达的对象所占用的内存空间。这可确保有效使用内存资源,但不能保证有足够的内存用于程序执行。 18. 内存的哪一部分 – 堆栈或堆 – 在垃圾收集过程中被清理?堆。 第二、Java中级面试题 19. 除了安全方面,在 Java 中使字符串不可变的原因是什么? String的源码中是由final修饰的数组,final修饰的变量不可变,从其他因素来看有这几个因素导致的:字符串池: Java 的设计者意识到程序员和开发人员将主要使用字符串数据类型这一事实。因此,他们希望从一开始就进行优化。他们提出了使用字符串池(Java 堆中的一个存储区域)来存储字符串文字的概念。他们打算借助共享来减少临时 String 对象。需要一个不可变的类来促进共享。在两个未知方之间共享可变结构是不可能的。因此,不可变的 Java 字符串有助于执行字符串池的概念。
多线程:关于 String 对象的线程安全是 Java 中的一个重要方面。如果 String 对象是不可变的,则不需要外部同步。因此,可以编写更清晰的代码来跨不同线程共享 String 对象。这种方法促进了并发的复杂过程。集合:在 Hashtables 和 HashMaps 的情况下,键是 String 对象。如果 String 对象不是不可变的,那么它可以在它驻留在 HashMap 期间被修改。因此,无法检索所需的数据。这种不断变化的状态带来了很多风险。因此,使字符串不可变是非常安全的。 20. 你如何区分 String、StringBuffer 和 StringBuilder?可变性: String 是不可变的,而 StringBuilder 和 StringBuffer 都是可变的。线程安全:在线程环境的情况下,使用 StringBuilder 和 StringBuffer 而没有使用 String。但是StringBuilder适合单线程环境,StringBuffer适合多线程。 句法: 21. 使用相关属性突出接口和抽象类之间的差异。方法的可用性:接口中只有抽象方法可用,而非抽象方法可以与抽象类中的抽象方法一起出现。变量类型:静态和最终变量只能在接口的情况下声明,而抽象类也可以有非静态和非最终变量。继承:接口促进了多重继承,而抽象类不促进多重继承。数据成员可访问性:默认情况下,接口的类数据成员是公共类型的。相反,抽象类的类成员也可以是受保护的或私有的。实现:借助抽象类,可以轻松实现接口。然而,反之则不然。 抽象类示例: 接口示例: 22. 在 Java 中,可以覆盖静态方法和私有方法。这种说法是否正确。上下文中的陈述是完全错误的。静态方法与对象无关,这些方法属于类级别。在子类的情况下,具有与父类完全相同的方法签名的静态方法可以存在,甚至不会引发任何编译错误。这里提到的现象通常称为方法隐藏,覆盖肯定是不可能的。私有方法覆盖是不可想象的,因为私有方法的可见性仅限于父类。因此,只能促进隐藏而不是覆盖。 23. HashSet 与 TreeSet 有何不同?尽管 HashSet 和 TreeSet 都不同步并确保不存在重复项,但还是有某些属性可以将 HashSet 与 TreeSet 区分开来。实现:对于HashSet,哈希表用于以无序方式存储素。然而,TreeSet 使用红黑树以排序的方式存储素。复杂度/性能:对于添加、检索和删除素,HashSet 的时间分摊复杂度为 O(1)。TreeSet 执行相同操作的时间复杂度稍高,等于 O(log n)。总的来说,HashSet 的性能比 TreeSet 更快。方法: hashCode() 和 equals() 是 HashSet 用来在对象之间进行比较的方法。相反,TreeSet 使用 compareTo() 和 compare() 方法来促进对象比较。对象类型:可以借助 HashSet 存储异构和空对象。在 TreeSet 的情况下,插入异构对象或空对象时会发生运行时异常。 24. 为什么字符数组比字符串更适合存储机密信息?在 Java 中,字符串基本上是不可变的,即它不能被修改。在它声明之后,只要不以垃圾的形式被移除,它就会继续留在字符串池中。换句话说,在执行字符串值处理后,字符串会在内存的堆部分驻留一段不受限制且未指定的时间间隔。因此,如果黑客非法访问内存转储,黑客可能会因从事有害活动而窃取重要信息。可以通过使用可变对象或结构(如字符数组)来存储任何变量来消除此类风险。字符数组变量的工作完成后,可以将变量同时配置为空白。因此,它有助于节省堆内存,也不会给黑客提取重要数据的机会。 25、Java中JVM、JRE和JDK的区别是什么?标准JDKJREJVM缩写Java 开发工具包Java运行时环境Java虚拟机定义JDK 是用于开发 Java 应用程序的完整软件开发工具包。它包括 JRE、JavaDoc、编译器、调试器等。JRE 是一个软件包,提供 Java 类库、JVM 和运行 Java 应用程序所需的所有组件。JVM 是一个依赖于平台的抽象机器,由 3 个规范组成——描述 JVM 实现要求的文档、满足 JVM 要求的计算机程序和用于执行 Java 字节码并提供运行时环境的实例对象。主要目的JDK 主要用于代码开发和执行。JRE 主要用于创建环境来执行代码。JVM 为 JRE 的所有实现提供了规范。提供的工具JDK 为代码开发提供了编译器、调试器等工具JRE 提供了 JVM 运行程序所需的库和类。JVM 不包含任何工具,而是提供了实现规范。概括JDK = (JRE) + 开发工具JRE = (JVM) + 执行应用程序的库JVM = 执行 Java 字节码的运行时环境。 26、Java中HashMap和HashTable的区别是什么? HashMapHashTableHashMap 不是同步的,因此更适合非线程应用程序。HashTable 是同步的,因此它适用于线程应用程序。只允许一个空键,但值中允许任意数量的空值。这不允许在键或值中使用 null。通过使用其子类 LinkedHashMap 支持插入顺序。HashTable 中不保证插入顺序。 27. 反射在 Java 中的重要性是什么? 该术语用于描述代码对其自身或其系统的其他代码的检查能力,并在运行时对其进行修改。考虑一个例子,我们有一个未知类型的对象,我们有一个方法“fooBar()”,我们需要在对象上调用它。Java 的静态类型系统不允许这种方法调用,除非事先知道对象的类型。这可以使用反射来实现,它允许代码扫描对象并识别它是否有任何称为“fooBar()”的方法,然后仅在需要时调用该方法。 使用反射有其自身的缺点:速度——由于反射引起的方法调用比直接方法调用慢大约三倍。类型安全——当一个方法被错误地使用反射通过其引用调用时,调用会在运行时失败,因为它在编译/加载时没有被检测到。可追溯性——每当反射方法失败时,由于巨大的堆栈跟踪,很难找到失败的根本原因。必须深入研究 invoke() 和 proxy() 方法日志以找出根本原因。 因此,建议遵循不涉及反射的解决方案并将此方法用作最后的手段。 28、线程的使用方式有哪些? 我们可以通过两种方式在java中定义和实现线程:扩展 Thread 类 实现 Runnable 接口 使用 Runnable 接口的方法实现线程是更优选和有利的,因为 Java 不支持类的多重继承。方法用于为线程执行创建单独的调用堆栈。一旦创建了调用堆栈,JVM 就会调用该调用堆栈中执行线程的方法。实现Callable接口 29. Java 中类的构造函数和方法有什么区别? 构造函数方法构造函数用于初始化对象状态。方法用于暴露对象的行为。构造函数没有返回类型。方法应该有一个返回类型。即使它不返回任何内容,返回类型也是无效的。构造函数被隐式调用。必须在对象上显式调用方法。如果未定义构造函数,则由 java 编译器提供默认构造函数。如果未定义方法,则编译器不提供它。构造函数名称应等于类名称。方法名可以是任意名称,也可以是类名。最终变量实例化在构造函数中是可能的,并且 this 的范围适用于整个类及其对象。如果在方法内初始化,则最终变量可确保变量不能仅在该方法的范围内更改。 30. Java 会出现“值传递”还是“引用传递”现象? Java 总是作为“传值”工作。Java 中没有所谓的“通过引用传递”。但是,当对象在任何方法中传递时,由于 Java 中对象处理的性质,传递的是值的地址。传递对象时,Java 创建引用的副本并将其传递给方法。对象指向相同的内存位置。方法内部可能会发生2种情况:情况 1:当对象指向另一个位置时:在这种情况下,对该对象所做的更改在传递给方法之前不会反映原始对象,因为引用指向另一个位置。 例如: 情况 2:当对象引用未被修改时:在这种情况下,由于我们拥有指向同一内存位置的主对象的引用副本,因此对象内容的任何更改都会反映在原始对象中。 例如: 31. 当数据需要进行大量更新时,应该优先选择String或String Buffer中的哪一个? StringBuffer 本质上是可变的和动态的,而 String 是不可变的。String 的每次更新/修改都会创建一个新的 String,从而使字符串池中包含不必要的对象超载。因此,在大量更新的情况下,总是首选使用 StringBuffer,因为它会减少在字符串池中创建多个 String 对象的开销。 32. Java 中如何不允许类的属性序列化? 为了实现这一点,可以在使用关键字的同时声明属性,如下所示: 在上面的例子中,除了可以序列化的所有字段。 33.如果静态修饰符没有包含在Java的main方法签名中会怎样? 不会有任何编译错误。但随后程序运行,由于JVM无法映射主方法签名,代码在运行时抛出“NoSuchMethodError”错误。 34.如果Java中一个类中有多个main方法会怎样? 程序无法编译,因为编译器说该方法已在类中定义。 35.你对Object Cloning的理解是什么,你是如何在Java中实现的? 它是创建任何对象的精确副本的过程。为了支持这一点,java 类必须实现 java.lang 包的 Cloneable 接口并覆盖 Object 类提供的 clone() 方法,其语法为: 如果未实现 Cloneable 接口而仅覆盖该方法,则会导致 Java 中的 CloneNotSupportedException。 36.异常如何在代码中传播?当异常发生时,它首先搜索以定位匹配的 catch 块。如果找到匹配的 catch 块,则将执行该块。否则,异常会通过方法调用堆栈传播并进入调用者方法,在那里执行匹配 catch 块的过程。这种传播一直发生,直到找到匹配的 catch 块。如果未找到匹配项,则程序将在 main 方法中终止。
37. 在 try 块之后是否必须遵循 catch 块?不,在 try 块之后没有必要出现 catch 块。- try 块之后应该跟一个 catch 块或一个 finally 块。如果异常可能性更大,则应使用方法的 throws 子句声明它们。 38. 当 return 语句写在 try 块和 catch 块的末尾时,finally 块是否会被执行,如下所示 无论异常与否,finally 块都将被执行。不执行 finally 块的唯一情况是当它在 try/catch 块中的任何地方遇到“System.exit()”方法时。 39. 你能在另一个构造函数中调用一个类的构造函数吗?是的,这个概念可以称为构造函数链接,可以使用.
40. 连续的内存位置通常用于在数组中而不是在 ArrayList 中存储实际值在 ArrayList 的情况下,无法以原始数据类型(如 int、float 等)的形式存储数据。ArrayList 中存在的数据成员/对象具有对位于内存中不同位置的对象的引用。因此,实际对象或非原始数据类型(如整数、双精度等)的存储发生在不同的内存位置。
但是,这不适用于数组。对象或原始类型值可以存储在连续内存位置的数组中,因此每个素不需要对下一个素的任何引用。
第三、Java 高级面试题 41. 虽然继承是一个流行的 OOPs 概念,但它不如组合有利。解释。 在以下场景中,继承落后于组合:Java 中无法实现多重继承。类只能从一个超类扩展。在需要多种功能的情况下,例如 – 将信息读取和写入文件,组合模式是首选。可以通过将作者和读者功能视为私有成员来使用作者和读者功能。组合物有助于获得高灵活性并防止封装破裂。单测试可以通过组合而不是继承来实现。当开发者想要测试一个组成不同类的类时,可以创建 Mock Object 来表示组成的类,以方便测试。这种技术在继承的帮助下是不可能的,因为如果没有继承中超类的帮助,就无法测试派生类。组合的松耦合特性优于继承的紧耦合特性。 让我们举个例子: 在上面的例子中,遵循了继承。现在,对 Top 类进行了一些修改,如下所示: 如果按照Top类的新实现,Bottom类必然会出现编译时错误。Top.stop() 函数存在不兼容的返回类型。必须对 Top 或 Bottom 类进行更改以确保兼容性。但是,可以利用组合技术来解决给定的问题: 42. 使用 new() 创建 String 与使用文字创建 String 有何不同? 当字符串在赋值运算符的帮助下形成为文字时,它会进入字符串常量池,以便可以进行字符串实习。如果两个对象的内容相同,则堆中的同一个对象将被不同的字符串引用。 当两个变量引用相同的内容时,checking() 函数将返回 true。
相反,当在 new() 运算符的帮助下形成字符串时,不会发生实习。即使存在相同的内容对象,该对象也会在堆内存中创建。 由于两个变量未引用相同的内容,因此checking() 函数将返回false。
43. 尽管有垃圾收集器,程序中是否可能超过内存限制? 是的,尽管存在垃圾收集器,程序仍有可能耗尽内存。垃圾收集有助于识别和消除程序中不再需要的那些对象,以释放它们使用的资源。 在程序中,如果某个对象不可访问,则垃圾收集的执行将针对该对象进行。如果创建新对象所需的内存量不足,则在垃圾收集器的帮助下,为那些不再在范围内的对象释放内存。当释放的内存不足以创建新对象时,就会超出程序的内存限制。 此外,如果对象的创建方式使它们保留在作用域中并消耗内存,则会耗尽堆内存。开发人员应确保在完成工作后取消引用该对象。尽管垃圾收集器尽最大努力尽可能多地回收内存,但仍然可能超出内存限制。 让我们看一下下面的例子: 44. 为什么需要同步?借助相关示例进行解释。 通过同步可以同时执行不同的进程。当多个线程共享特定资源时,可能会出现多个线程需要相同共享资源的情况。 同步有助于解决问题,资源一次由一个线程共享。让我们举个例子来更清楚地理解它。例如,您有一个 URL,您必须找出对其发出的请求数。两个同时请求可能会使计数不稳定。 无同步:
如果一个线程Thread1查看计数为10,它将增加1到11。同时,如果另一个线程Thread2查看计数为10,它会增加1到11。因此,计数值不一致,因为预期的最终值是 12,但我们得到的实际最终值将是 11。 现在,函数increase() 是同步的,因此不能同时进行访问。 同步:
如果线程 Thread1 将计数视为 10,它将增加 1 到 11,然后线程 Thread2 将看到计数为 11,它将增加 1 到 12。因此,计数值发生了一致性。 45.在下面给定的代码中,…的意义是什么? 能够提供一个称为 varargs(可变参数)的特性,它是作为 Java 5 的一部分引入的。上面例子中的函数表明它可以接收数据类型字符串的多个参数。例如, fooBarMethod 可以通过多种方式调用,我们仍然可以使用一种方法来处理数据,如下所示: 46.你能解释一下Java线程生命周期吗? Java线程生命周期如下:New – 当线程的实例被创建并且 start() 方法未被调用时,线程被认为是活动的,因此处于 NEW 状态。Runnable – 一旦 start() 方法被调用,在 JVM 调用 run() 方法之前,线程被称为处于 RUNNABLE(准备运行)状态。这种状态也可以从线程的 Waiting 或 Sleeping 状态进入。运行- 当 run() 方法被调用并且线程开始执行时,线程被称为处于 RUNNING 状态。不可运行(阻塞/等待) ——当线程尽管处于活动状态而无法运行时,该线程被称为处于不可运行状态。理想情况下,在其活跃一段时间后,线程应该进入可运行状态。如果一个线程想要进入同步代码,但它无法进入,则称该线程处于阻塞状态,因为另一个线程正在同一对象的同步块中运行。第一个线程必须等到另一个线程退出同步块。如果一个线程正在等待来自另一个线程的信号执行,即它等待工作直到接收到信号,则称该线程处于等待状态。 终止- 一旦 run() 方法执行完成,线程被认为进入了 TERMINATED 步骤并被认为是不活跃的。 下面的流程图清楚地解释了 Java 中线程的生命周期。
47. 使用无序数组与使用有序数组之间的权衡是什么? 拥有有序数组的主要优点是降低了搜索时间复杂度,而无序数组的时间复杂度为。有序数组的主要缺点是它增加了 O(n) 的插入时间,因为它的素必须在每次插入期间重新排序以保持数组的顺序,而无序数组的时间复杂度仅为 O(1 )。考虑到以上2个关键点,根据开发者需要什么样的场景,可以使用合适的数据结构来实现。 48. 是否可以在 Java 中两次导入同一个类或包,在运行时会发生什么? 可以多次导入一个类或包,但是,这是多余的,因为 JVM 在内部只加载一次包或类。 49.如果一个包有子包,是否只导入主包就可以了?例如,导入 com.myMainPackage.* 是否也导入 com.myMainPackage.mySubPackage.*? 这是一个很大的问题。我们需要明白,一个包的子包的导入需要显式的完成。导入父包只会导致导入其中的类,而不是其子/子包的内容。 50.如果代码System.exit(0)写在try块的末尾会不会执行finally块? 不。程序 post 的控制立即消失,程序终止,这就是 finally 块永远不会执行的原因。 51、Java中的marker接口是怎么理解的? 标记接口,也称为标记接口,是那些没有定义方法和常量的接口。它们用于帮助编译器和 JVM 有关对象的运行时相关信息。 52.解释Java中的术语“双括号初始化”? 这是在 Java 中初始化任何集合的便捷方式。考虑下面的例子。 在上面的例子中,我们看到 stringSets 是使用双括号初始化的。第一个大括号执行创建匿名内部类的任务,该类具有访问父类行为的能力。在我们的示例中,我们创建了 HashSet 的子类,以便它可以使用 HashSet 的 add() 方法。第二个大括号执行初始化实例的任务。 通过此方法初始化时应小心,因为该方法涉及创建匿名内部类,这可能会在垃圾收集或序列化过程中引起问题,也可能导致内存泄漏。 53、为什么说String类的length()方法返回的结果不准确? length 方法返回字符串的 Unicode 单数。让我们了解什么是 Unicode 单位以及下面的混淆是什么。我们知道 Java 使用 UTF-16 来表示字符串。有了这个 Unicode,我们就需要了解下面两个 Unicode 相关的术语:代码点:这表示一个整数,表示代码空间中的一个字符。代码单:这是用于编码代码点的位序列。为此,可能需要一个或多个单来表示一个代码点。 在 UTF-16 方案下,代码点在逻辑上分为 17 个平面,第一个平面称为基本多语言平面 (BMP)。BMP 具有经典字符 – U+0000 到 U+FFFF。其余的字符 – U+10000 到 U+10FFFF 被称为补充字符,因为它们包含在其余平面中。来自第一个平面的代码点使用一个16 位代码单进行编码其余平面的代码点使用两个代码单进行编码。 现在,如果字符串包含增补字符,则长度函数会将其计为 2 个单位,并且 length() 函数的结果将与预期不同。 换句话说,如果有 2 个单位的 1 个增补字符,则该单个字符的长度被认为是两个 – 注意这里的不准确吗?根据java文档,这是预期的,但根据实际逻辑,它是不准确的。 54. 下面代码的输出是什么,为什么? 如果在双引号(或字符串文字)中使用字母,则“位”将是打印的结果。但问题是使用了字符文字(单引号),这就是不会发生连接的原因。将添加每个字符的相应 ASCII 值,并打印该总和的结果。’b’、’i’、’t’ 的 ASCII 值是:’b’ = 98’i’ = 105’t’ = 116 因此将打印 319。 55. 在 Java 中使对象符合垃圾回收 (GC) 条件的可能方法有哪些? 第一种方法:一旦达到对象创建目的,将对象引用设置为 null。 第二种方法:将引用变量指向另一个对象。这样做,引用变量之前引用的对象将有资格进行 GC。 方法三:孤岛方法:当2个引用变量指向同一个类的实例,并且这些变量只相互引用,而这2个变量所指向的对象没有其他引用时,则称有形成了一个“隔离岛”,这两个对象有资格进行 GC。 第四、Java 面试计划 56. 使用递归检查给定的字符串是否是回文。 57. 编写一个 Java 程序来检查两个字符串是否是字谜。 主要思想是验证字符串的长度,如果发现相等,则将字符串转换为字符数组,然后对数组进行排序并检查两者是否相等。 58. 编写一个 Java 程序来找出给定数字的阶乘。 59. 给定一个从 1 到 n 的非重复数字数组,其中缺少一个数字,编写一个高效的 java 程序来找到那个缺失的数字。 想法是使用公式找到n个自然数的总和,然后找到给定数组中数字的总和。减去这两个总和得出的数字是实际缺失的数字。这导致 O(n) 时间复杂度和 O(1) 空间复杂度。 60. 编写一个 Java 程序来检查任何数字是否是幻数。如果在每个步骤中进行数字总和并依次进行该总和的数字总和后,最终结果(仅剩一位数字时)为 1,则称该数字为幻数。 例如,考虑数字:第 1 步:163 => 1+6+3 = 10第 2 步:10 => 1+0 = 1 => 因此 163 是一个幻数 第五、Java 面试小测(答案请写在评论里哦) 用于编译、调试和执行java程序的组件是什么?
2.字节码到机器码转换的任务是什么组件?
3.下面哪个是java解释器的功能?
4.当一个对象有自己的生命周期并且它的子对象不能属于另一个父对象时,它叫什么?
5.下面这段代码的输出是什么?
6.以下代码的输出是什么?
7.当垃圾收集进程在线程执行期间启动时,以下哪项会发生?
8.下面代码的输出是什么?
9.Getinstance () 的功能是什么?
10.下面代码的输出是什么?
11. 以下代码的输出是什么?
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/83992.html