Java基础面试题知识点总结(上篇)

大家好,我是栗筝i,从 2022 年 10 月份开始,我持续梳理出了全面的 Java 技术栈内容,一方面是对自己学习内容进行整合梳理,另一方面是希望对大家有所帮助,使我们一同进步。得到了很多读者的正面反馈。

而在 2023 年 10 月份开始,我将推出 Java 面试题/知识点系列内容,期望对大家有所助益,让我们一起提升。

本篇是对 Java 基础系列的面试题 / 知识点的总结的上篇


系列相关链接:


文章目录

        • 1、Java基础面试题问题
        • 2、Java基础面试题解答
          • 2.1、JavaObject类相关
          • 2.2、Java深拷贝浅拷贝相关
          • 2.3、Java序列化反序列化相关
          • 2.4、Java数据类型相关
          • 2.5、Java字符串相关


1、Java基础面试题问题

Java基础面试题问题(上篇)

  • 问题 1. Object 类在 Java 中是什么样的存在?为何在 Java 中,所有的类都会继承自 Object 类?
  • 问题 2. Object 类有哪些主要的方法?每个方法的作用是什么?
  • 问题 3. Object 类 native 方法和非 native 方法区别是什么?
  • 问题 4. Java 中 == 和 equals 的有什么区别?
  • 问题 5. Java 中为什么重写 equals() 方法后,还必须重写 hashCode()?
  • 问题 6. 什么是深拷贝和浅拷贝?
  • 问题 7. Java 中的 clone() 方法默认是深拷贝还是浅拷贝?
  • 问题 8. 在实现深拷贝时,如果遇到循环引用该如何处理?
  • 问题 9. 在实现深拷贝时,对于数组和集合类应该如何处理?
  • 问题 10. Cloneable 接口在 Java 中的作用是什么?
  • 问题 11. 为什么说 Cloneable 是一个标记接口?
  • 问题 12. 什么是 Java 的序列化和反序列化?
  • 问题 13.Java 中的 Serializable 接口有什么作用?
  • 问题 14. 在 Java 中,如果一个对象的某个字段不想被序列化,应该如何处理?
  • 问题 15. 如何自定义序列化与反序列化过程?
  • 问题 16. 静态字段是否可以被序列化?为什么?
  • 问题 17. 在 Java 中,默认的序列化机制是怎样的?
  • 问题 18. Java 中的基本数据类型有哪些?
  • 问题 19. Java 中的自动装箱和拆箱是什么?
  • 问题 20. 在 Java 中什么是强制类型转换、隐式类型转换、显式类型转换?
  • 问题 21. 为什么 Java 中的字符串不可变?它有什么优势?
  • 问题 22. 什么是 Java 中的字符串池?
  • 问题 23. 简述 String str = "aaa"String str = new String("i") 一样吗 ?
  • 问题 24. Java 中有哪些创建字符串的方式?
  • 问题 25. 介绍一下 String、StringBuffer、StringBuilder 和他们之间的区别?

2、Java基础面试题解答
2.1、JavaObject类相关
  • 问题 1. Object 类在 Java 中是什么样的存在?为何在 Java 中,所有的类都会继承自 Object 类?

解答:Object 类在 Java 中被视为所有类的基础和起点。这是因为在 Java 中,所有的类都默认继承自 Object 类,无论是 Java 内置的类,还是用户自定义的类。这种设计使得所有的 Java 对象都能够调用一些基本的方法,例如 equals(), hashCode(), toString() 等,这些方法都在 Object 类中被定义。

  • 问题 2. Object 类有哪些主要的方法?每个方法的作用是什么?

解答:Object 类中的方法可以分为两类:native 方法和非 native 方法。

非 native 方法是:

  1. equals():判断与其他对象是否相等。
  2. clone():创建并返回此对象的一个副本。
  3. toString():返回该对象的字符串表示。
  4. finalize():当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。

native 方法是:

  1. getClass():返回此 Object 的运行时类。
  2. hashCode():返回该对象的哈希码值。
  3. notify():唤醒在此对象监视器上等待的单个线程。
  4. notifyAll():唤醒在此对象监视器上等待的所有线程。
  5. wait(long timeout):在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。
  • 问题 3. Object 类 native 方法和非 native 方法区别是什么?

解答:native 方法和非 native 方法的主要区别在于它们的实现方式和运行环境。

  1. native 方法:这些方法在 Java 代码中声明,但是它们的实现是用其他语言(通常是 C 或 C++)编写的,并且在 Java 之外的环境中运行。native 方法可以访问系统特有的资源,如硬件设备接口、系统调用等。在 Java 代码中,native 方法通常用关键字 “native” 声明。
  2. 非 native 方法:这些方法完全在 Java 中声明和实现。它们在 Java 虚拟机(JVM)内部运行,并且只能访问由 JVM 提供的资源。非 native 方法不能直接访问系统资源或执行系统调用。
  • 问题 4. Java 中 == 和 equals 的有什么区别?

在 Java 中,==equals() 方法用于比较两个对象,但它们的比较方式和使用场景有所不同。

  1. ==:对于基本数据类型,== 比较的是值是否相等;对于引用类型,== 比较的是两个引用是否指向同一个对象,即它们的地址是否相同。

  2. equals():这是一个方法,不是操作符。它的行为可能会根据它在哪个类中被调用而变化。在 Object 类中,equals() 方法的行为和 == 相同,比较的是引用是否指向同一个对象。但是在一些类(如 String、Integer 等)中,equals() 方法被重写,用于比较两个对象的内容是否相等。因此,如果你想比较两个对象的内容是否相等,应该使用 equals() 方法。

  • 问题 5. Java 中为什么重写 equals() 方法后,还必须重写 hashCode()?

解答:在 Java 中,equals()hashCode() 两个方法是密切相关的。如果你重写了 equals() 方法,那么你也必须重写 hashCode() 方法,以保证两个相等的对象必须有相同的哈希码。这是因为在 Java 集合框架中,特别是哈希表相关的数据结构(如 HashMapHashSet 等)在存储和检索元素时,会使用到对象的 hashCode() 方法。

以下是 Java 中 equals()hashCode() 方法的一般约定:

  1. 如果两个对象相等(即,equals(Object) 方法返回 true),那么调用这两个对象中任一对象的 hashCode() 方法都必须产生相同的整数结果。

  2. 如果两个对象不等(即,equals(Object) 方法返回 false),那么调用这两个对象中任一对象的 hashCode() 方法,不要求必须产生不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同的整数结果可能提高哈希表的性能。

因此,如果你重写了 equals() 方法但没有重写 hashCode() 方法,可能会导致违反上述的第一条约定,从而影响到哈希表相关数据结构的正确性和性能。


2.2、Java深拷贝浅拷贝相关
  • 问题 6. 什么是深拷贝和浅拷贝?

解答:深拷贝和浅拷贝是编程中常见的两种复制对象的方式,主要区别在于是否复制对象内部的引用对象。

  1. 浅拷贝(Shallow Copy):当进行浅拷贝时,如果对象中的字段是基本类型,会直接复制其值;如果对象中的字段是引用类型,那么只复制其引用,而不复制引用指向的对象。因此,原对象和拷贝对象会共享同一个引用对象。这就意味着,如果其中一个对象改变了这个引用对象的内容,那么另一个对象的这个引用对象的内容也会随之改变。

  2. 深拷贝(Deep Copy):当进行深拷贝时,无论对象中的字段是基本类型还是引用类型,都会创建一个新的副本。对于引用类型,会复制引用指向的对象,而不仅仅是复制引用。因此,原对象和拷贝对象不会共享任何一个引用对象。这就意味着,无论哪一个对象改变了引用对象的内容,都不会影响到另一个对象。

需要注意的是,实现深拷贝可能会比较复杂,特别是当对象的引用结构很复杂时,例如存在循环引用。此外,深拷贝可能会消耗更多的计算和存储资源。

  • 问题 7. Java 中的 clone() 方法默认是深拷贝还是浅拷贝?

解答:在 Java 中,clone() 方法默认进行的是浅拷贝。

这意味着,如果你的对象中包含了对其他对象的引用,那么 clone() 方法只会复制这个引用,而不会复制引用指向的对象。因此,原对象和克隆对象会共享这个引用指向的对象,这就是所谓的浅拷贝。

如果你想实现深拷贝,即完全复制一个新的对象,包括其引用的所有对象,那么你需要重写 clone() 方法,手动复制这些对象。

  • 问题 8. 在实现深拷贝时,如果遇到循环引用该如何处理?

解答:在实现深拷贝时,如果遇到循环引用,需要特别小心,否则可能会导致无限递归,最终导致栈溢出。

处理循环引用的一种常见方法是使用一个哈希表来跟踪已经复制过的对象。具体来说,每当你复制一个对象时,都将原对象和复制的新对象放入哈希表中。然后,在复制一个对象之前,先检查这个对象是否已经在哈希表中。如果已经在哈希表中,那么就直接返回哈希表中的复制对象,而不再进行复制。

以下是一个简单的示例:

public class Node {public Node next;// ...
}public class DeepCopy {private HashMap<Node, Node> visited = new HashMap<>();public Node clone(Node node) {if (node == null) {return null;}if (visited.containsKey(node)) {return visited.get(node);}Node cloneNode = new Node();visited.put(node, cloneNode);cloneNode.next = clone(node.next);return cloneNode;}
}

在这个示例中,DeepCopy 类使用了一个 visited 哈希表来跟踪已经复制过的 Node 对象。在 clone() 方法中,每次复制一个 Node 对象之前,都会先检查这个对象是否已经在 visited 哈希表中。这样就可以避免因为循环引用而导致的无限递归。

  • 问题 9. 在实现深拷贝时,对于数组和集合类应该如何处理?

解答:在实现深拷贝时,对于数组和集合类的处理需要特别注意,因为它们都可能包含引用类型的元素。

数组:如果数组的元素是基本类型,那么可以直接使用 clone() 方法或 System.arraycopy() 方法来复制数组。如果数组的元素是引用类型,那么需要遍历数组,对每个元素进行深拷贝。

MyClass[] copy = new MyClass[array.length];
for (int i = 0; i < array.length; i++) {copy[i] = array[i].clone();
}

集合类:对于集合类,如 ArrayListHashSet 等,需要创建一个新的集合,然后遍历原集合,对每个元素进行深拷贝,并添加到新集合中。

ArrayList<MyClass> copy = new ArrayList<>();
for (MyClass item : list) {copy.add(item.clone());
}

需要注意的是,实现深拷贝可能会比较复杂,特别是当对象的引用结构很复杂时,例如存在循环引用。此外,深拷贝可能会消耗更多的计算和存储资源。

  • 问题 10. Cloneable 接口在 Java 中的作用是什么?

解答:Cloneable 接口在 Java 中被称为标记接口(Marker Interface),它本身并没有定义任何方法,但是它对于 Java 的对象克隆机制来说非常重要。

当一个类实现了 Cloneable 接口后,它就表明它的对象是可以被克隆的,即它的 clone() 方法可以被合法地调用。如果一个类没有实现 Cloneable 接口,但是调用了它的 clone() 方法,那么将会在运行时抛出 CloneNotSupportedException 异常。

实现 Cloneable 接口的目的是为了让 Objectclone() 方法知道它可以对这个类的对象进行字段对字段的复制。

需要注意的是,虽然 Cloneable 接口本身并没有定义任何方法,但是实现 Cloneable 接口的类通常需要重写 Object 类的 clone() 方法,以提供公开的克隆方法并实现类特定的克隆行为,例如深拷贝。

  • 问题 11. 为什么说 Cloneable 是一个标记接口?

Cloneable 接口被称为标记接口,是因为它本身并没有定义任何方法,它的作用主要是为了标记一个类的对象可以被克隆。

在 Java 中,Cloneable 接口的主要作用是告诉 Objectclone() 方法,它可以对实现了 Cloneable 接口的类的对象进行字段对字段的复制。

如果一个类没有实现 Cloneable 接口,但是调用了它的 clone() 方法,那么将会在运行时抛出 CloneNotSupportedException 异常。

因此,Cloneable 接口虽然没有定义任何方法,但是它对于 Java 的对象克隆机制来说非常重要,它是一种标记,表明一个类的对象可以被克隆。


2.3、Java序列化反序列化相关
  • 问题 12. 什么是 Java 的序列化和反序列化?

解答:Java 的序列化(Serialization)和反序列化(Deserialization)是 Java 对象持久化的一种机制。

  1. 序列化:序列化是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化过程中,对象将其当前状态写入到一个输出流中。

  2. 反序列化:反序列化是从一个输入流中读取对象的状态信息,并根据这些信息创建对象的过程。

序列化和反序列化在很多场景中都非常有用,例如:

  • 在网络通信中,序列化可以用于在网络上发送对象。
  • 在持久化数据时,序列化可以用于将对象保存到磁盘,然后在需要时通过反序列化重新创建。
  • 在 Java RMI(远程方法调用)技术中,序列化和反序列化被用于在 JVM 之间传递对象。

在 Java 中,如果一个类的对象需要支持序列化和反序列化,那么这个类需要实现 java.io.Serializable 接口。这个接口是一个标记接口,没有定义任何方法,只是用来表明一个类的对象可以被序列化和反序列化。

  • 问题 13.Java 中的 Serializable 接口有什么作用?

解答:在 Java 中,Serializable 接口是一个标记接口,用于表明一个类的对象可以被序列化和反序列化。

序列化是将对象的状态信息转换为可以存储或传输的形式的过程。反序列化则是从一个输入流中读取对象的状态信息,并根据这些信息创建对象的过程。

如果一个类实现了 Serializable 接口,那么它的对象可以被序列化,即可以将对象的状态信息写入到一个输出流中。然后,这个输出流可以被存储到磁盘,或通过网络发送到另一个运行 JVM 的机器。在需要时,可以从这个输出流中读取对象的状态信息,并通过反序列化重新创建对象。

需要注意的是,Serializable 接口本身并没有定义任何方法,它只是一个标记接口。实际的序列化和反序列化过程是由 JVM 通过一些特殊的机制来完成的。

  • 问题 14. 在 Java 中,如果一个对象的某个字段不想被序列化,应该如何处理?

在 Java 中,如果你不希望对象的某个字段被序列化,你可以使用 transient 关键字来修饰这个字段。

transient 是 Java 的一个关键字,用来表示一个字段不应该被序列化。在对象序列化的过程中,被 transient 修饰的字段会被忽略,不会被写入到输出流中。因此,这个字段的状态信息不会被持久化。

例如:

public class MyClass implements Serializable {private int field1;private transient int field2;// ...
}

在这个例子中,field1 字段会被序列化,而 field2 字段则不会被序列化。

需要注意的是,如果一个字段被标记为 transient,那么在反序列化的过程中,这个字段的值会被初始化为其类型的默认值,例如 null0false

  • 问题 15. 如何自定义序列化与反序列化过程?

解答:在 Java 中,虽然默认的序列化机制已经足够强大,但在某些情况下,你可能需要自定义序列化过程。例如,你可能需要对某些敏感信息进行加密,或者需要以特定的格式写入对象的状态信息。

要自定义序列化过程,你可以在类中添加一个名为 writeObject() 的方法。这个方法必须接受一个 ObjectOutputStream 类型的参数,并且返回 void

private void writeObject(ObjectOutputStream out) throws IOException {// 自定义序列化过程
}

在这个方法中,你可以自定义序列化过程。例如,你可以选择只序列化部分字段,或者对某些字段进行特殊处理。

需要注意的是,writeObject() 方法必须是 private 的,这是因为序列化机制会忽略 publicprotectedwriteObject() 方法。

同样,如果你需要自定义反序列化过程,你可以添加一个名为 readObject() 的方法:

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {// 自定义反序列化过程
}

在这个方法中,你可以自定义反序列化过程。例如,你可以选择只反序列化部分字段,或者对某些字段进行特殊处理。

同样,readObject() 方法必须是 private 的。

  • 问题 16. 静态字段是否可以被序列化?为什么?

解答:静态字段不能被序列化。这是因为静态字段不属于对象,而是属于类。

在 Java 中,静态字段是类级别的,所有的对象实例共享同一个静态字段。因此,静态字段的状态不应该被看作是对象的一部分,所以在序列化对象时,静态字段会被忽略。

序列化的主要目的是为了保存对象的状态,以便在需要时可以恢复这个状态。但是,静态字段的状态是与特定的对象无关的,所以无需在序列化过程中保存和恢复。

如果你需要保存和恢复静态字段的状态,你需要通过其他方式来实现,例如,你可以在序列化和反序列化过程中手动处理静态字段。

  • 问题 17. 在 Java 中,默认的序列化机制是怎样的?

解答:在 Java 中,对象的默认序列化机制是通过实现 java.io.Serializable 接口来完成的。Serializable 是一个标记接口,它本身并没有定义任何方法,但是它告诉 Java 虚拟机(JVM)这个对象是可以被序列化的。

当一个对象被序列化时,JVM 会将该对象的类信息、类的签名以及非静态和非瞬态字段的值写入到一个输出流中。这个过程是自动的,不需要程序员进行任何特殊处理。

具体来说,序列化过程如下:

  1. 如果对象的类定义了 writeObject 方法,那么 JVM 会调用这个方法进行序列化。否则,JVM 会默认地进行序列化。

  2. JVM 会检查每个需要序列化的字段。如果字段是基本类型,那么 JVM 会直接写入其值。如果字段是引用类型,那么 JVM 会递归地对这个字段指向的对象进行序列化。

  3. 如果对象的类实现了 Externalizable 接口,那么 JVM 会调用 writeExternal 方法进行序列化。

反序列化过程与序列化过程相反。当一个对象被反序列化时,JVM 会从输入流中读取类信息和字段的值,然后根据这些信息创建新的对象。

需要注意的是,静态字段和用 transient 关键字修饰的字段不会被序列化。静态字段属于类,而不是对象。transient 关键字告诉 JVM 该字段不应该被序列化。


2.4、Java数据类型相关
  • 问题 18. Java 中的基本数据类型有哪些?

解答:Java 中的数据类型可以分为 4 类 8 种,4 类分别为:整型、浮点型、字符型和布尔型。

  1. 整型:包括 byte、short、int 和 long 四种类型,主要用于表示没有小数部分的数值,区别在于它们的取值范围和存储大小不同。

byte:占用 1 字节,取值范围为 -128 到 127

short:占用 2 字节,取值范围为 -32768 到 32767

int:占用 4 字节,取值范围为 -2147483648 到 2147483647

long:占用 8 字节,取值范围为 -9223372036854775808 到 9223372036854775807

  1. 浮点型:包括 float 和 double 两种类型,主要用于表示有小数部分的数值。

float:单精度浮点型,占用 4 字节,取值范围为 1.4E-45 到 3.4028235E38

double:双精度浮点型,占用 8 字节,取值范围为 4.9E-324 到 1.7976931348623157E308

  1. 字符型:只有 char 一种类型,主要用于表示单个字符。

char:占用 2 字节,取值范围为 0 到 65535,可以表示 Unicode 编码中的任何字符。

  1. 布尔型:只有 boolean 一种类型,主要用于表示真或假的逻辑值。

boolean:只有两个取值,即 true 和 false。

  • 问题 19. Java 中的自动装箱和拆箱是什么?

解答:自动装箱和拆箱是 Java 5.0 版本引入的新特性,主要用于基本数据类型和对应的包装类之间的自动转换。

自动装箱和拆箱是 Java 编译器的特性,它在编译阶段会自动为我们插入必要的代码来实现基本数据类型和包装类之间的转换。

  1. 自动装箱(Autoboxing):是指基本数据类型自动转换为对应的包装类。例如,将 int 类型自动转换为 Integer 类型。
int i = 10;
Integer integer = i;  // 自动装箱 编译器会将这行代码转换为:Integer integer = Integer.valueOf(i);
  1. 自动拆箱(Unboxing):是指包装类自动转换为对应的基本数据类型。例如,将 Integer 类型自动转换为 int 类型。
Integer integer = new Integer(10);
int i = integer;  // 自动拆箱 编译器会将这行代码转换为:int i = integer.intValue();

这两个特性使得基本数据类型和包装类在很多情况下可以互相替代,大大提高了编程的便利性。

  • 问题 20. 在 Java 中什么是强制类型转换、隐式类型转换、显式类型转换?

解答:

  1. 强制类型转换:也称为显式类型转换,是指程序员明确要求进行的类型转换。在 Java 中,可以通过在表达式前加上类型名的方式来进行强制类型转换。例如:
double d = 10.5;
int i = (int) d;  // 将 double 类型转换为 int 类型
  1. 隐式类型转换:也称为自动类型转换,是指编译器在编译过程中自动进行的类型转换。在 Java 中,当我们把一个表示范围小的类型赋值给一个表示范围大的类型时,编译器会自动进行类型转换。例如:
int i = 10;
double d = i;  // 将 int 类型自动转换为 double 类型
  1. 显式类型转换:和强制类型转换是同一个概念,都是指程序员明确要求进行的类型转换。

2.5、Java字符串相关
  • 问题 21. 为什么 Java 中的字符串不可变?它有什么优势?

解答:Java 中的字符串被设计为不可变的,这意味着一旦创建字符串对象,其内容无法更改。这个设计决策具有一些重要的优势:

  1. 线程安全性: 不可变字符串是线程安全的,因为多个线程可以同时访问一个字符串对象而无需担心并发修改导致的问题。这对于多线程应用程序来说是非常重要的。

  2. 安全性: 不可变字符串可以用作参数传递给方法,而不必担心方法在不经意间更改了字符串的内容。

  3. 性能优化: 因为字符串不可变,可以在运行时对其进行缓存,以减少内存占用和提高性能。例如,多个字符串变量可以共享相同的字符串字面值,从而节省内存。

  4. 哈希码缓存: 字符串的哈希码可以在创建时计算并缓存,这样在后续哈希比较(如在哈希表中查找字符串)时会更加高效。

  5. 字符串池: 不可变字符串使得字符串池的实现更容易,从而可以共享字符串字面值,减少内存占用。

  6. 安全性: 不可变字符串对于安全性是有帮助的。例如,当字符串用于密码或其他敏感数据时,不可变性可以确保这些数据不会在内存中不经意地被修改。

  7. 简化字符串操作: 不可变性简化了字符串操作。例如,当你连接两个字符串时,实际上是创建了一个新的字符串,而不是修改原始字符串。

尽管不可变字符串有很多优势,但它们也有一些劣势,例如在频繁修改字符串内容时可能会导致性能下降,因为每次修改都会创建新的字符串对象。为了解决这个问题,Java 提供了 StringBuilderStringBuffer 等可变字符串类,以便更高效地进行字符串拼接和修改。然而,在大多数情况下,不可变字符串的优点远远超过了其劣势,因此它们在 Java中得到广泛应用。

  • 问题 22. 什么是 Java 中的字符串池?

解答:Java 中的字符串池(String Pool)是 Java 堆内存中的一个特殊区域,用于存储所有由字面量创建的字符串对象。

当我们创建一个字符串字面量(例如,String str = "Hello";),JVM 首先会检查字符串池中是否已经存在 “Hello” 这个字符串。如果存在,那么 str 就会指向这个已存在的 “Hello” 字符串;如果不存在,JVM 就会在字符串池中创建一个新的 “Hello” 字符串,然后 str 会指向这个新创建的字符串。

通过这种方式,字符串池可以帮助我们节省内存,因为它允许相同的字符串字面量共享同一个存储空间。

  • 问题 23. 简述 String str = "aaa"String str = new String("i") 一样吗 ?

解答:String str = "aaa";String str = new String("aaa"); 在 Java 中并不完全相同。

  1. String str = "aaa";:这种方式创建的字符串会被放入字符串池中。如果字符串池中已经存在 “aaa” 这个字符串,那么 str 就会指向这个已存在的字符串;如果不存在,JVM 就会在字符串池中创建一个新的 “aaa” 字符串,然后 str 会指向这个新创建的字符串。

  2. String str = new String("aaa");:这种方式会在堆内存中创建一个新的字符串对象,然后 str 会指向这个新创建的对象。这时,无论字符串池中是否存在 “aaa” 这个字符串,都不会影响 str 的创建。

所以,虽然这两种方式创建的字符串内容相同,但是他们在内存中的存储位置可能不同。如果你使用 == 操作符比较这两个字符串,可能会得到 false,因为 == 操作符比较的是对象的引用,而不是内容。如果你使用 equals() 方法比较这两个字符串,会得到 true,因为 equals() 方法比较的是字符串的内容

  • 问题 24. Java 中有哪些创建字符串的方式?

解答:在 Java 中,主要有以下几种创建字符串的方式:

  1. 字符串字面量:这是最常见的创建字符串的方式,例如 String str = "Hello";。这种方式创建的字符串会被放入字符串池中。

  2. 使用 new 关键字:例如 String str = new String("Hello");。这种方式会在堆内存中创建一个新的字符串对象。

  3. 通过字符数组:例如 char[] array = {'H', 'e', 'l', 'l', 'o'}; String str = new String(array);。这种方式会创建一个新的字符串,内容是字符数组的内容。

  4. 通过 StringBuilderStringBuffer:例如 StringBuilder sb = new StringBuilder("Hello"); String str = sb.toString();。这种方式可以创建一个可变的字符串,然后再转换为不可变的 String

  5. 通过 String.format() 方法:例如 String str = String.format("Hello %s", "World");。这种方式可以创建一个格式化的字符串。

以上就是在 Java 中创建字符串的主要方式。

  • 问题 25. 介绍一下 String、StringBuffer、StringBuilder 和他们之间的区别?

解答:

  1. String:在 Java 中,String 是不可变的,也就是说一旦一个 String 对象被创建,我们就不能改变它的内容。每次对 String 类型进行修改,都会生成一个新的 String 对象。这在需要大量修改字符串时,会导致内存的大量占用和效率的降低。

  2. StringBufferStringBuffer 是线程安全的可变字符序列。每个方法都是同步的,可以被多个线程安全地调用。但是,这种线程安全带来的缺点是效率相对较低。

  3. StringBuilderStringBuilder 是一个可变字符序列,它提供了 appendinsertdeletereversesetCharAt 等方法来修改字符串。与 StringBuffer 相比,StringBuilder 不是线程安全的,因此在单线程环境下,StringBuilder 的效率更高。

总结一下,他们之间的区别主要在于:

  • String 是不可变的,而 StringBufferStringBuilder 是可变的。
  • StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的。
  • 在单线程环境下,如果需要对字符串进行大量修改,应优先考虑使用 StringBuilder。在多线程环境下,应使用 StringBuffer 来确保线程安全。如果字符串不需要修改,那么使用 String 是最好的选择。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/115049.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分享一下我家网络机柜,家庭网络设备推荐

家里网络机柜搞了几天终于搞好了&#xff0c;非专业的&#xff0c;走线有点乱&#xff0c;勿喷。 从上到下的设备分别是&#xff1a; 无线路由器&#xff08;当ap用&#xff09;:TL-XDR6088 插排&#xff1a;德木pdu机柜插排 硬盘录像机&#xff1a;TL-NVR6108-L8P 第二排左边…

面试题 02.01. 移除重复节点

​题目来源&#xff1a; leetcode题目&#xff0c;网址&#xff1a;110. 平衡二叉树 - 力扣&#xff08;LeetCode&#xff09; 解题思路&#xff1a; 哈希表。遍历链表若当前元素在哈希表中&#xff0c;则将其删除&#xff0c;否则将其加入哈希表。 解题代码&#xff1a; /*…

Python中不同进制间的转换

Python中不同进制间的转换 一、不同进制在计算机科学、数学和其他领域中具广泛的应用。以下是一些常见的应用&#xff1a;1. 二进制&#xff08;base-2&#xff09;: 在计算机系统中&#xff0c;数据以二进制形式存储和处理。二进制由0和1组成&#xff0c;是数字电子技术的基础…

【Spring Cloud Alibaba】seata分布式事务官方入门案例(实战版)

文章目录 1. 业务介绍1.1. 用例1.2. 架构图1.3. 3个服务的代码及业务逻辑&#xff08;略&#xff09; 2. SEATA 的分布式交易解决方案3. 由Dubbo SEATA提供支持的示例&#xff08;实战&#xff09;3.1. 步骤 1&#xff1a;建立数据库&#xff0c;如seata数据库3.2. 步骤 2&…

flink中使用异步函数的几个注意事项

背景 在flink系统中&#xff0c;我们为了补充某个流事件成一个完整的记录&#xff0c;经常需要调用外部接口获取一些配置数据&#xff0c;流事件结合这些配置数据就可以组合成一条完整的记录&#xff0c;然而如果同步调用外部系统接口来实现&#xff0c;那么会有很大的性能瓶颈…

2023高频前端面试题(含答案)

一、简单页面1、CSS选择器样式优先级2、CSS实现三列布局&#xff08;左右固定宽度&#xff0c;中间自适应&#xff09; &#xff08;1&#xff09;CSS浮动 第一个float:left&#xff0c;第二个float:right&#xff0c;第三个设置margin-left和margin-right &#xff08;2&#…

使用反射获取API数据并强制转为实例

例如获取API数据&#xff0c;以下只教思想&#xff0c;我下面也是代码也是大概写了写&#xff1a; 1.新建两个实例&#xff0c;一个是API提供方提供的API返回data&#xff0c;一个是本地用于接收的data数据&#xff0c;以下两个类虽然后者多几个字段&#xff0c;但是除多出那几…

实现图像处理和分析的关键技术

在计算机视觉中&#xff0c;我们可以利用摄像头捕捉到的图像来进行各种分析和处理。以下是一些常见的计算机视觉任务&#xff1a; 对象检测&#xff1a;识别图像中的特定对象并标注其位置。人脸识别&#xff1a;识别和验证人脸身份。姿态估计&#xff1a;估计人体的姿态和动作…

无纸化办公小程序数据交互、wxs的使用

前言 很多同志们再写小程序的过程中&#xff0c;不知道该怎么发起HTTP请求到后端&#xff0c;在Web环境中发起HTTPS请求是很常见的&#xff0c;但是微信小程序是腾讯内部的产品&#xff0c;不能直接打开一个外部的链接。例如&#xff0c;在微信小程序中不能直接打开www.taobao…

ASRPRO语音识别模块

ASRPRO语音识别模块 SOFT IIC 与PCA9685模块通信 pca9685 iic通信 地址位 ADDR<<1|0 左移一位 #define I2C_WRITE 0 #define I2C_READ 1 否则通信地址错误 asrpro 通过UART与电脑连接&#xff0c;可以进行简单的交互 将STM32作为接口扩展&#xff0c;通过SPI或I…

Seata学习

Seata Seata 是一款开源的分布式事务解决方案&#xff0c;致力于在微服务架构下提供高性能和简单易用的分布式事务服务。 官网地址&#xff1a;https://seata.io/zh-cn/index.html 为什么会产生分布式事务&#xff1f; 示例&#xff1a;用户下单后需要创建订单&#xff0c;同时…

DDR电源硬件设计要点

一、DDR电源简介 1. 电源 DDR的电源可以分为三类: a、主电源VDD和VDDQ,主电源的要求是VDDQ=VDD,VDDQ是给IO buffer供电的电源,VDD是给但是一般的使用中都是把VDDQ和VDD合成一个电源使用。 有的芯片还有VDDL,是给DLL供电的,也和VDD使用同一电源即可。电源设计时,需要考…

最短路相关笔记

Floyd Floyd 算法&#xff0c;是一种在图中求任意两点间最短路径的算法。 Floyd 算法适用于求解无负边权回路的图。 时间复杂度为 O ( n 3 ) O(n^3) O(n3)&#xff0c;空间复杂度 O ( n 2 ) O(n^2) O(n2)。 对于两点 ( i , j ) (i,j) (i,j) 之间的最短路径&#xff0c;有…

如何让ChatGPT生成图片?

目录 一、那么如何解决让ChatGPT具有画图能力的问题呢&#xff1f; 二、那ChatGPT为什么能生成图片呢&#xff1f; 我们都知道ChatGPT只是个纯文本的AI模型&#xff0c;不具备画图能力。它可以生成文本&#xff0c;但如果让他生成图片就会显示如下的声明&#xff1a; 但通过本…

图像信号处理板设计原理图:2-基于6U VPX的双TMS320C6678+Xilinx FPGA K7 XC7K420T的图像信号处理板

综合图像处理硬件平台包括图像信号处理板2块&#xff0c;视频处理板1块&#xff0c;主控板1块&#xff0c;电源板1块&#xff0c;VPX背板1块。 一、板卡概述 图像信号处理板包括2片TI 多核DSP处理器-TMS320C6678&#xff0c;1片Xilinx FPGA XC7K420T-1FFG1156&#xff0c;1片X…

strcpy函数

文章目录 strcpy函数描述函数使用总结目标空间为什么必须可变&#xff1f;模拟实现 strcpy函数描述 重点&#xff1a;including the terminating null character (and stopping at that point).意为拷贝的值包括停止字符 传参时第一个参数为要拷贝参数&#xff0c;第二个参数为…

游戏盾如何有效防护DDoS

从进入计算机时代以来&#xff0c;DDoS攻击一直是网络世界中的一大威胁&#xff0c;让无数服务陷入瘫痪。这种攻击的原理非常简单&#xff1a;攻击者使用大量的僵尸主机或蠕虫病毒&#xff0c;向目标服务器发送海量请求&#xff0c;迅速耗尽服务器的资源&#xff0c;使其无法继…

某全球领先的芯片供应商:优化数据跨网交换流程,提高安全管控能力

1、客户介绍 某全球领先的芯片供应商&#xff0c;成立于2005年&#xff0c;总部设于北京&#xff0c;在国内上海、深圳、合肥等地及国外多个国家和地区均设有分支机构和办事处&#xff0c;致力于为客户提供更优质、便捷的服务。 2、建设背景 该公司基于网络安全管理的需求&am…

Datawhale学习笔记AI +新能源:电动汽车充电站充电量预测2

在飞浆平台上成功运行出pandas-profiling啦~ 首先一键安装 pip install ydata_profiling然后演示&#xff0c;可以生成一个网页对数据有一个比较好的理解 import numpy as np import pandas as pd from ydata_profiling import ProfileReporttrain_power pd.read_csv(/home/…

【论文阅读】以及部署BEVFusion: A Simple and Robust LiDAR-Camera Fusion Framework

BEVFusion: A Simple and Robust LiDAR-Camera Fusion Framework BEVFusion&#xff1a;一个简单而强大的LiDAR-相机融合框架 NeurIPS 2022 多模态传感器融合意味着信息互补、稳定&#xff0c;是自动驾驶感知的重要一环&#xff0c;本文注重工业落地&#xff0c;实际应用 融…