Java基础 高频面试题,狂刷1个月Java面试题

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
img

正文

    • 1 abstract
    • 1)抽象类
  • 2)抽象方法

  • 2 final

  • 3 static

  • 4 synchronized

  • 2.3 extends 和 implements

    • 1 extends
  • 2 implements

  • 2.4 new、this、super 和 instanceof

    • 1 new(新建)
  • 2 this

  • 3 super

  • 4 instanceof(实例)

  • 2.5 try、catch、finally、throw 和 throws

    • 1 try(捕获异常)
  • 2 catch(处理异常)

  • 3 finally(必须执行)

  • 4 throw 与 throws

  • 3 Java 的 IO 流

    • 3.1 为什么有了字节流,还要有字符流
  • 3.2 BIO、NIO、AIO 有什么区别

    • 1)同步与异步、阻塞与非阻塞
  • 2)Java 的 IO 模型

  • 3.3 用键盘输入常用的两种方式

  • 4 Java 的异常处理

    • 4.1 异常类层次结构图
  • 4.2 处理异常的方式

  • 5 Java 的反射

    • 5.1 反射机制介绍
  • 5.2 反射机制优缺点

  • 5.3 反射机制的应用场景

  • 6 Java 序列化

    • 6.1 序列化的含义、意义和使用场景
  • 6.2 序列化实现的方法

  • 6.3 总结

  • 7 相似内容的区别

    • 7.1 String、StringBuilder 和 StringBuffer
  • 7.2 == 和 equals

  • 7.3 hashCode() 和 equals

    • 1)hashCode() 的介绍
  • 2)hashCode() 的作用

  • 7.4 重载(overload)和重写(override)

  • 7.5 接口和抽象类的区别

  • 7.6 成员变量和局部变量的区别

  • 7.7 静态方法和实例方法的区别

  • 7.8 Java 中字符常量和字符串常量的区别

  • 7.9 浅拷贝和深拷贝

  • 7.10 基本类型数据和包装类型数据的区别#

  • 8 其它问题

    • 8.1 装箱与拆箱
  • 8.2 什么是 Java 程序的主类

  • 8.3 为什么在一个静态方法内调用一个非静态成员是非法的

  • 8.4 创建⼀个对象用什么运算符?对象实体与对象引用有何不同?

  • 8.5 对象相等和指向他们的引用相等,这两者有什么不同?

  • 8.6 构造方法有什么特点

  • 8.7 在 Java 中定义⼀个不做事且没有参数的构造方法的作用

  • 8.8 ⼀个类的构造方法的作用是什么? 若⼀个类没有声明构造方法,该程序能正确执行吗? 为什么?

  • 8.9 什么是方法的返回值,方法的返回值有什么作用

  • 8.10 不用第三个变量,交换两个变量的值

  • 8.11 Java 运算符优先级

  • 8.12 Java 的数据类型,分别占多大内存

  • 8.13 Object 类有哪些方法

  • 8.14 Java 与 Python 的区别

  • 8.15 如何不利用第三个变量交换两个变量的值

  • 8.16 Java 创建对象的方式

1 Java 语言的特点

===============================================================================

Java 语言含有以下特点:

  • 是一门面向对象编程的语言;

  • 通过 Java 虚拟机实现了跨平台运行,即实现了一次编译,随处运行;

  • 编译与解释并存:利用 javac 将 Java 代码编译成 Java 字节码,同时保留了解释型语⾔可移植的特点。

1.1 何为面向对象


总结:

面向对象语言具有三大特性,分别是封装、继承和多态,这是面向对象与面向过程的主要区别,利用这三大特性,面向对象可以设计出低耦合的程序,使其更易维护、复用和扩展。

1)面向对象与面向过程编程的区别

  • 面向过程编程就好像是有有一只“上帝的手”通过制定一系列规则来操纵一堆“死物“,通过函数来解决问题;性能一般来说较面向对象的高;

  • 面向对象就好像是把世界描绘成有主动性的“活物”之间的交互;通过对象来解决问题;由于类调用时需要实例化,比较消耗资源,所以性能较面向过程的低,但其易维护、易复用、易扩展。

2)封装性

封装就是将一个对象的属性私有化,不允许外部程序直接访问,而是通过该对象的 setter 或者 getter 方法来实现对隐藏信息的操作。

3)继承性

继承就是使用已经存在的类的定义作为基础来建立新的类的技术,它可以使用父类的功能,也可以在其基础上增加新的数据或者功能,甚至是重写父类的功能,但不能选择性地继承父类的功能。

注意:

  • 子类拥有父类的所有属性和方法(包括私有属性和方法),但对于父类的私有属性和方法,子类是无法访问的,只是拥有。

  • 继承后 new 时的初始化顺序:父类属性的初始化 → 父类构造方法的初始化 → 子类属性的初始化 → 子类构造方法的初始化。

4)多态性

多态性就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定。

即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在程序运行期间才能确定。

在 Java 中有两种形式可以实现多态:

  1. 子类继承父类;

  2. 类实现接口。

1.2 JVM、JRE 以及 JDK


JVM < JRE < JDK

1)JVM

Java 虚拟机(JVM)是运行 Java 字节码的虚拟机,JVM 有针对不同系统的特定实现,目的是当使用相同的字节码时,它们都会给出相同的结果,字节码和不同系统的 JVM 实现是 Java 语言“一次编译,随处可以运行”的关键所在。

在 Java 中,JVM 可以理解的代码就叫做字节码 (即扩展名为 .class 的⽂件),它不⾯向任何特定的处理器,只⾯向虚拟机。Java 语⾔通过字节码的方式,在⼀定程度上解决了传统解释型语⾔执行效率低的问题,同时⼜保留了解释型语⾔可移植的特点。所以 Java 程序运行时比较高效,而且,由于字节码并不针对⼀种特定的机器,因此,Java 程序⽆须重新编译便可在多种不同操作系统的计算机上运⾏。

Java 程序从源代码到运行的过程:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SKVjl42W-1634887132899)(C:\Users\Sharm\Pictures\Typora图片存储\面经\3.jpg)]

2)JRE

JRE 是 Java 运⾏时环境。它是运⾏已编译 Java 程序所需的所有内容的集合,包括 Java 虚拟机(JVM)、Java 类库、java 命令和其他的⼀些基础构件。但是,它不能⽤于创建新程序。

3)JDK

JDK 是 Java 开发工具包,它是功能⻬全的 Java SDK,它拥有 JRE 所拥有的⼀切,还有编译器(javac)和⼯具(如 javadoc 和 jdb)。它能够创建和编译程序。

2 Java 关键字总结

===============================================================================

2.1 private、protected、public


它们是用来定义访问权限修饰符的关键字。

请添加图片描述

其中在一个 .java 文件中的两个 Class 是算同一个包里的两个类,而非同一个类。

2.2 abstract、final、static、synchronized


用于定义类、方法、变量的关键字。

1 abstract

abstract 可以修饰类和方法;参考文献:传送门

1)抽象类

抽象类的书写形式为:[public]abstract class 类名{};

特点:

  1. 抽象类不能被实例化。因为抽象类本身就代表了一种类型,无法确定为一个具体的类型;

  2. 虽然抽象类不能被实例化,但其可以有构造方法。因为当子类进行初始化的时候,必然会优先初始化父类的属性以及方法。同时,对于抽象类中的非 static 和非 abstract 方法中的 this 关键字代表的是它的继承类,而非抽象类本身;

  3. 抽象类不能使用 final 关键字修饰,因为 final 修饰的类是无法被继承的;

2)抽象方法
  1. 抽象方法没有自己的主体,即没有{}包起来的业务逻辑,这一点跟接口中的方法有点类似;

public abstract class Car {

public abstract void run();

}

class Bicycle extends Car{

@Override

public void run() {

System.out.println(“人踩着跑。。。”);

}

}

  1. 抽象方法不能用 private 修饰,因为抽象方法必须被子类重写,而 private 权限对于子类来说是不能访问的,所以就会产生矛盾;

  2. 抽象方法也不能用 static 修饰,试想一下,如果用 static 修饰了,那么我们可以直接通过类名调用,而抽象方法压根就没有主体,没有任何业务逻辑,这样做毫无意义;

  3. 抽象方法必须在抽象类中,而抽象类可以没有抽象方法,因为它可以有非抽象的方法

  4. 如果一个类继承了一个抽象类,且这个子类不是抽象类的话,那么它必须重写抽象类中全部的抽象方法。

2 final

final 可以用来修饰类、方法和变量。

  1. 当用来修饰变量时,如果该变量是基本数据类型的变量,则其数值一旦初始化后便不能更改;如果该变量是引用数据变量,则其初始化后便不能再让其指向另一个对象。

  2. 当用来修饰方法时,表示该方法是不能被子类重写的;

  3. 当用来修饰类时,表示该类是不能被继承的,同时该类中所有成员方法都会被隐式地指定为 final 方法。

3 static

static 关键字可以用来修饰成员变量、成员方法、代码块和内部类;

  1. 用 static 关键字修饰的静态变量和不用 static 关键字修饰的实例变量。静态变量属于类,在内存中只有一个复制,只要静态变量所在的类被加载,这个静态变量就会被分配空间,对静态变量的引用有两种方式,分别是“类.静态变量"和”对象.静态变量"。实例变量属于对象,只有对象被创建后,实例变量才会被分配内存空间,才能被使用,它在内存中存在多个复制,只有用“对象.实例变量”的方式来引用。

  2. static 方法是类的方法,不需要创建对象就可以被调用,而非 static 方法是对象的方法,只有对象被创建出来后才可以被使用。static 方法中不能使用 this 和 super 关键字,不能调用非 static 方法,只能访问所属类的静态成员变量和成员方法。

  3. static 代码块在类中是独立于成员变量和成员方法的代码块的,同时,这些 static 代码块只会被执行一次,即实例化的时候执行;

  4. 创建静态内部类的对象时,不需要外部类的对象,可以直接创建 内部类 对象名= new 内部类()

4 synchronized

synchronized 关键字可以用来修饰方法和代码块,其作用是防止程序的关键代码在同一时间被多个线程执行。

  1. 当应用于静态方法时,该方法由一个线程执行时,整个类将被锁定;

  2. 当应用于实例方法时,该方法由一个线程执行时,该实例将被锁定;

  3. 如果应用于对象或数组,当关联的代码块一次由一个线程执行时,对象或数组将被锁定。

参考文献,传送门

2.3 extends 和 implements


表示定义类与类之间关系的关键字。

1 extends

  1. extends 关键字用在 class 或 interface 声明中,用于指示所声明的类或接口是 extends 关键字后的类或接口的子类(子接口);

  2. 子类继承父类的所有 public 和 protected 变量和方法;

  3. 子类可以重写父类的任何非 final 方法;

  4. 一个类只能继承一个其它类。

2 implements

  1. implements 关键字在 class 声明中使用,以指示所声明的类提供了在 implements 关键字后面的名称所指定的接口中所声明的所有方法的实现;

  2. 一个类可以实现多个接口。

2.4 new、this、super 和 instanceof


表示定义建立实例、引用实例和判断实例的关键字。

1 new(新建)

  1. new 关键字用于创建类的新实例;

  2. new 关键字后面的参数必须是类名,并且类名的后面必须是一组构造方法参数(必须带括号);

  3. 参数集合必须与类的构造方法的参数匹配;

  4. = 左侧的变量的类型必须与要实例化的类具有赋值兼容关系。

2 this

  1. this 关键字用于引用当前实例

  2. this 和 super 是针对于对象实例的;

3 super

  1. super 关键字用于引用此类的父类;

  2. 作为独立语句出现的 super 表示调用父类的构造方法;

  3. super.() 表示调用父类的方法。只有在如下情况中才需要采用这种用法:要调用在该类中被重写的方法,以便指定应当调用在超类中的该方法。

4 instanceof(实例)

  1. instanceof 关键字用来确定对象实例所属的类。

2.5 try、catch、finally、throw 和 throws


用来处理异常的关键字。

处理异常的方式:

  • 通过使用 try catch finally 来捕获异常,自己处理;

  • 通过 throw 或 throws 来抛出异常,让别人处理;

1 try(捕获异常)

  1. try 关键字用于包含可能引发异常的语句块;

  2. 每个 try 块都必须至少有一个 catch 或 finally 子句;

  3. 如果某个特定异常类未被任何 catch 子句处理,该异常将沿着调用栈递归地传播到下一个封闭 try 块,如果任何封闭 try 块都未捕获到异常,Java 解释器将退出,并显示错误消息和堆栈跟踪信息。

2 catch(处理异常)

  1. catch 关键字用来在 try-catch 或 try-catch-finally 语句中定义异常处理块。

3 finally(必须执行)

  1. finally 关键字用来定义始终在 try-catch-finally 语句中执行的块;

  2. finally 块通常包含清理代码,用在部分执行 try 块后恢复正常运行;

  3. finally 块的 return 语句比 catch 块优先执行。

4 throw 与 throws

| throw | throws |

| :-: | :-: |

| throw 是在方法体内,表示抛出一个异常; | throws 用在方法的声明上,表示该方法可能要抛出的异常; |

| throw 则是明确了这个地方要抛出这个异常; | throws E1,E2,E3 只是告诉程序这个方法可能会抛出这些异常,方法的调用者可能要处理这些异常; |

参考文献:传送门

3 Java 的 IO 流

================================================================================

详细内容见博客:传送门

3.1 为什么有了字节流,还要有字符流


问题的本质:不管是⽂件读写还是⽹络发送接收,信息的最小存储单元都是字节,那为什么 IO 流操作要分为字节流操作和字符流操呢?

虽然字符是通过字节转换而成的 ,但是这个过程非常耗时,而且编解码标准的不同会导致出现乱码错误,所以 Java 的 IO 流干脆提供了一个直接操作字符的接口,方便我们平时对字符进行流操作。

如果⾳频⽂件、图片等媒体⽂件⽤字节流⽐较好,如果涉及到字符的话使⽤字符流比较好。

3.2 BIO、NIO、AIO 有什么区别


1)同步与异步、阻塞与非阻塞

阻塞和非阻塞强调的是程序在等待调用结果时的状态,同步和异步强调的是消息通信机制。

  • 同步:当调用某个方法时,调用方得等待这个调用返回结果后才能继续往后执行;

  • 异步:当调用某个方法时,调用方也许不会立刻得到结果,但是调用方在调用这个方法后可以继续执行后续操作,而被调用方在另一个线程中执行完毕后会通过某种方法将结果返回给调用方。举个例子:线下买东西和线上买东西的区别。

  • 阻塞:阻塞是指调用结果返回之前,当前线程会被挂起,并在得到结果之后才会继续。

  • 非阻塞:非阻塞指的是如果调用结果不能立刻返回,则该调用者不会阻塞当前线程,因此对应非阻塞的情况,调用者需要定时轮询查看处理状态。

2)Java 的 IO 模型

IO 即数据的读取(接收)或写入(发送)操作,通常用户进程中的一个完整IO分为两阶段:用户进程空间<–>内核空间、内核空间<–>设备空间(磁盘、网络等)。IO有内存IO、网络IO和磁盘IO三种,通常我们说的IO指的是后两者。

  • 阻塞IO模型(Block IO):当用户线程发出 IO 请求后,内核会去查看数据是否准备就绪,如果数据还未准备就绪,则该用户线程就会处于阻塞状态,此时用户线程交出 CPU,等到数据准备就绪之后,返回结果给用户线程,此时用户线程结束阻塞状态;

  • 非阻塞IO模型(No Block IO):当用户线程发出 IO 请求后,不需要等待,而是立刻就能得到一个结果,如果结果是 error,则说明数据还没有准备好,于是其继续发出IO请求,直到返回准备好的数据。在非阻塞IO模型中,用户线程需要不断地询问内核数据是否就绪,也就说非阻塞 IO 不会交出 CPU,而会一直占用 CPU;

  • 异步IO模型(AIO):当用户线程发出 IO 请求后,不需要等待,继续执行该用户线程接下来的后续操作,等到请求的数据在另一个线程准备好后,会响应给用户线程,告诉用户线程数据已经准备就绪;

3.3 用键盘输入常用的两种方式


  • 通过 Scanner

Scanner scanner = new Scanner(System.in);

String s = scanner.nextLine();

scanner.close();

  • 通过 InputStreamReader

BufferedReader input = new BufferedReader(new InputStreamReader(System.in));

String s = input.readLine();

4 Java 的异常处理

===============================================================================

4.1 异常类层次结构图


请添加图片描述

如上图所示,java.lang 包中的 Throwable 类是所有异常类的父类,其中包括两大子类,分别是 Error 和 Exception。

  • Error(错误):程序无法处理的错误。表示运行应用程序中较严重的问题,绝大多数是程序运行时不允许出现的状况,同时,这些错误是不可查的,因为它们在应用程序的控制和处理能力之外。

  • Exception(异常):异常和错误的区别在于异常能被程序本身处理,而错误是无法处理的。

4.2 处理异常的方式


  • try 块:用于捕获异常。其后可接零个或多个 catch 块,如果没有 catch 块,则必须跟一个 finally 块;

  • catch 块:用于处理 try 捕获到的异常。

  • finally 块:无论是否捕获或处理异常,finally 块里的语句都会被执行,当在 catch 块中遇到 return 语句时,finally 语句块将在方法返回之前被执行。不过当出现以下四种特殊情况时,finally 块不会被执行:

  1. 在 finally 语句块第一行发生了异常。

  2. 在前面的代码中使用了 System.exit(int) 来已退出程序,若该语句在异常语句之后,finally 会执行;

  3. 程序所在的线程死亡;

  4. 关闭了 CPU。

注意:当 try 语句和 finally 语句中都有 return 语句时,在方法返回之前,finally 语句的内容将被执行,并且 finally 语句的返回值将会覆盖原始的返回值。如下:

public static int f(int value) {

try {

return value * value;

} finally {

if (value == 2) {

return 0;

}

}

}

// 如果调用 f(2),输出的结果为 0。

5 Java 的反射

=============================================================================

5.1 反射机制介绍


在运行期间,通过 Java 的反射机制,对于任何一个类,都能够知道这个类的属性和方法;对于任何一个对象,都能够调用这个对象的属性和方法。Java 的反射机制可以让用户动态地获取类的信息以及动态调用对象的功能

反射的原理就是利用 Java 虚拟机通过类的字节码文件反向获取该类或者对象中的属性和方法。

5.2 反射机制优缺点


  • 优点: 动态加载类,提高代码灵活度;

  • **缺点:**因为反射相当于一系列解释操作,因此性能比直接的 java 代码要慢;使用反射会模糊程序内部逻辑。

5.3 反射机制的应用场景


反射是框架设计的灵魂。

比如在 MyBatis 中,当使用 标签逐⼀定义列名和对象属性名之间的映射关系后,MyBatis 就可以通过反射来创建对象,同时利用反射给对象的属性逐⼀赋值并返回,那些找不到映射关系的属性,是⽆法完成赋值的;

又比如在 Spring 的 IoC,就是通过解析 XML 文件,获取到 id 属性和 class 属性里面的内容,然后利用反射原理获取到配置里面类的实例对象,并存入到 Spring 的 bean 容器中。

1 反射的应用场景

  • Spring 的 IoC 和 AOP 的实现都和反射有关;

  • 代码的逆向编译;

2 反射的实现方式

Class 类是基于反射机制的,Class 由 final 修饰,一个 Class 类的实例表示这个类的类型信息。

  • 通过Class c1 = 类名.class

  • 通过Class c2 = 对象名.getClass()

  • 通过Class c3 = Class.forName(类的全名的字符串)

6 Java 序列化

=============================================================================

6.1 序列化的含义、意义和使用场景


  • 序列化:将对象写入到 IO 流中;

  • 反序列化:从 IO 流中恢复对象;

  • 意义:序列化机制允许将实现序列化的 Java 对象转换位字节序列,这些字节序列可以保存在磁盘上,或通过网络传输,以达到以后恢复成原来的对象。序列化机制使得对象可以脱离程序的运行而独立存在。

  • 使用场景:所有在网络上传输的、所有保存到磁盘中的 Java 对象必须是可序列化的,且其传入的参数和返回的对象也必须是可序列化的。通常建议:程序创建的每个 JavaBean 类都实现 Serializeable 接口。

6.2 序列化实现的方法


  1. 实现 Serializable 接口:Serializable 接口是一个标记接口,不用实现任何方法,一旦实现了此接口,该类的对象就是可序列化的。

  2. 实现 Externalizable 接口:通过实现 Externalizable 接口,必须实现 writeExternal、readExternal 方法。

6.3 总结


  1. 所有在网络上传输的、所有保存到磁盘中的 Java 对象都需要实现序列化接口;

  2. 对象的类名、实例变量(包括基本类型,数组,对其他对象的引用)都会被序列化;方法、静态变量、transient 实例变量都不会被序列化;

  3. 如果想让某个变量不被序列化,使用 transient 修饰(transient 只能修饰变量,不能修饰类和方法);

  4. 序列化对象的引用类型的实例变量,也必须是可序列化的,否则,会报错。

  5. 反序列化时必须有序列化对象的 class 文件。

  6. 当通过文件、网络来读取序列化后的对象时,必须按照实际写入的顺序读取。

  7. 单例类序列化,需要重写 readResolve() 方法;否则会破坏单例原则。

  8. 同一对象序列化多次,只有第一次序列化为二进制流,以后都只是保存序列化编号,不会重复序列化。

  9. 建议所有可序列化的类加上serialVersionUID 版本号,方便项目升级。

参考文档:传送门

1 如果想阻止一个对象序列化,可以采用什么方法

不让这个对象对应的类实现 Serializable 或者 Externalizable 接口即可,transient 关键字只能修饰变量,而不能修饰方法和类。

7 相似内容的区别

============================================================================

7.1 String、StringBuilder 和 StringBuffer


| | String | StringBuffer | StringBuilder |

| :-: | :-: | :-: | :-: |

| 底层存储形式 | 底层使用 final 修饰的字符数组来保存字符串,所以 String 对象是不可变的 | 底层使用普通字符数组来保存字符串,所以 StringBuffer 对象是可变的 | 底层使用普通字符数组来保存字符串,所以 StringBuilder 对象是可变的 |

| 修改对象方面 | 每次对该对象进行改变时,都会生成一个新的 String 对象 | 每次对该对象进行改变时,只是对该对象本身进行操作,而不是生成一个新的对象 | 每次对该对象进行改变时,只是对该对象本身进行操作,而不是生成一个新的对象 |

| 线程安全方面 | String 对象是不可改变的,所以可以理解为常量,是线程安全的 | StringBuffer 对方法加了同步锁或对调用的方法加了同步锁,所以是线程安全的 | StringBuilder 并没有对方法加了同步锁或对调用的方法加了同步锁,所以是线程不安全的 |

| 适用范围 | 操作少量的数据 | 多线程下操作大量数据 | 单线程操作大量数据 |

综合来说:

String 对象的底层是用 final 修饰的字符数组来保存字符串的,所以 String 对象是不可变的,每次对该对象进行改变时,实际上都是创建了一个新的对象。

StringBuilder 和 StringBuffer 底层使用普通的字符数组来保存的,所以每次对对象进行改变时,仅仅是对对象本身进行改变,而不是创建一个新的对象。

String 和 StringBuffer 是线程安全的,StringBuilder 是线程不安全的。

1 什么是线程安全

线程安全指的是当一个线程在操作一个方法或者语句时,其它线程不能对其进行操作,只能等到该线程结束后才可以进行访问。

7.2 == 和 equals


  • == :

  • 如果是基本数据类型,则比较两个数据的值是否相同;

  • 如果是引用数据类型,则比较两个数据所保存的内存地址是否相同;

  • equals :

总结

总体来说,如果你想转行从事程序员的工作,Java开发一定可以作为你的第一选择。但是不管你选择什么编程语言,提升自己的硬件实力才是拿高薪的唯一手段。

如果你以这份学习路线来学习,你会有一个比较系统化的知识网络,也不至于把知识学习得很零散。我个人是完全不建议刚开始就看《Java编程思想》、《Java核心技术》这些书籍,看完你肯定会放弃学习。建议可以看一些视频来学习,当自己能上手再买这些书看又是非常有收获的事了。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
al 修饰的字符数组来保存字符串的,所以 String 对象是不可变的,每次对该对象进行改变时,实际上都是创建了一个新的对象。

StringBuilder 和 StringBuffer 底层使用普通的字符数组来保存的,所以每次对对象进行改变时,仅仅是对对象本身进行改变,而不是创建一个新的对象。

String 和 StringBuffer 是线程安全的,StringBuilder 是线程不安全的。

1 什么是线程安全

线程安全指的是当一个线程在操作一个方法或者语句时,其它线程不能对其进行操作,只能等到该线程结束后才可以进行访问。

7.2 == 和 equals


  • == :

  • 如果是基本数据类型,则比较两个数据的值是否相同;

  • 如果是引用数据类型,则比较两个数据所保存的内存地址是否相同;

  • equals :

总结

总体来说,如果你想转行从事程序员的工作,Java开发一定可以作为你的第一选择。但是不管你选择什么编程语言,提升自己的硬件实力才是拿高薪的唯一手段。

如果你以这份学习路线来学习,你会有一个比较系统化的知识网络,也不至于把知识学习得很零散。我个人是完全不建议刚开始就看《Java编程思想》、《Java核心技术》这些书籍,看完你肯定会放弃学习。建议可以看一些视频来学习,当自己能上手再买这些书看又是非常有收获的事了。

[外链图片转存中…(img-j9QNdazu-1713543464747)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-2lUcgnl2-1713543464747)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 20
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值