当前位置: 首页 > news >正文

Java 基础 -- Java 基础知识

目 录

  • Java 基础知识
    • 一、Java 概述
      • 1.1 Java 简介
        • 1.1.1 Java 介绍
        • 1.1.2 Java 核心特性
        • 1.1.3 Java 技术体系
      • 1.2 Java 开发环境
        • 1.2.1 Java 开发环境介绍
        • 1.2.2 JDK 下载
        • 1.2.3 Windows 免安装版
      • 1.3 Java 开发工具
    • 二、Java 语言基础
      • 2.1 Java 程序入口点
      • 2.2 Java 基本语法
      • 2.3 Java 基本数据类型
        • 2.3.1 基本数据类型介绍
        • 2.3.2 数据类型转换
        • 2.3.3 Java 包装类
      • 2.4 Java 变量与常量
        • 2.4.1 变量与常量介绍
        • 2.4.2 Java 变量
        • 2.5.3 Java 常量
      • 2.5 Java 修饰符
        • 2.5.1 Java 修饰符介绍
        • 2.5.2 访问控制修饰符
        • 2.5.3 非访问修饰符
      • 2.6 Java 运算符
        • 2.6.1 算术运算符
        • 2.6.2 关系运算符
        • 2.6.3 位运算符
        • 2.6.4 逻辑运算符
        • 2.6.5 赋值运算符
        • 2.6.6 其他运算符
    • 三、Java 流程控制
      • 3.1 Java 条件语句
        • 3.1.1 if 条件语句
        • 3.1.2 switch 分支语句
      • 3.2 Java 循环语句
        • 3.2.1 for 循环语句
        • 3.2.2 while 循环语句
        • 3.2.3 do...while 循环语句
      • 3.3 Java 循环控制
        • 3.3.1 break 语句
        • 3.3.2 continue 语句
    • 四、Java 数组
      • 4.1 数组概述
      • 4.2 一维数组
      • 4.2 二维数组
    • 五、Java 常用类
      • 5.1 Number 类
        • 5.1.1 Number 类介绍
        • 5.1.2 Number 类的子类
      • 5.2 Math 类
        • 5.2.1 Math 类介绍
        • 5.2.2 Math 类常用方法
      • 5.3 Character 类
        • 5.3.1 Character 类介绍
        • 5.3.2 Character 类判断方法
        • 5.3.3 Character 类字符转换方法
        • 5.3.4 Character 类应用示例
      • 5.4 String 类
        • 5.4.1 String 类介绍
        • 5.4.2 String 类常用方法
        • 5.4.3 String 类的不可变性
        • 5.4.3 String 类不可变的实现原理
        • 5.4.4 字符串常量池

Java 基础知识

一、Java 概述

1.1 Java 简介

1.1.1 Java 介绍

Java 是一种广泛使用、功能强大、跨平台的高级编程语言和计算平台。

1.1.2 Java 核心特性

简单易学:Java 的语法基于 C/C++,但去除了 C/C++ 中复杂且容易出错的特性,如指针运算、多重继承(通过接口实现类似功能)、显式内存管理(通过垃圾回收机制)等。

面向对象(Object-Oriented - OOP):Java 是一门纯粹的面向对象编程语言(除了基本数据类型),一切皆对象(Everything is an Object)。Java 完全支持 OOP 的四大核心特性:

  • 封装(Encapsulation):将数据(属性)和操作数据的方法(行为)捆绑在一起,通过访问修饰符(private,public,protected)控制访问权限。
  • 继承(Inheritance):子类可以继承父类的属性和方法,实现代码复用。
  • 多态(Polymorphism):同一个接口可以有不同的实现方式(如方法重写 @Override),提高了代码的灵活性和可扩展性。
  • 抽象(Abstraction):通过抽象类和接口定义规范,隐藏复杂的实现细节。

平台无关性:“一次编写,到处运行”(Write Once,Run Anywhere - WORA),这也是 Java 最核心、最革命性的特性。

  • 原理:Java 源代码(.java 文件)首先被编译成一种与平台无关的中间代码——字节码(Bytecode)(.class 文件)。然后,这个字节码由安装在目标操作系统上的 Java 虚拟机(Java Virtual Machine - JVM) 来解释执行或即时编译(JIT)成本地机器码。
  • 结果:只要目标机器安装了相应版本的 JVM,同一个编译好的 .class 文件就可以在 Windows、Linux、macOS 等不同操作系统上运行,无需重新编译。这极大地提高了软件的可移植性。

健壮性:Java 通过多种机制确保程序的稳定性和可靠性:

  • 强类型检查(Strong Typing):在编译和运行时进行严格的类型检查,减少类型错误。
  • 异常处理(Exception Handling):提供了完善的异常处理机制(try-catch-finally,throw,throws),允许程序优雅地处理运行时错误,避免程序崩溃。
  • 自动内存管理 / 垃圾回收(Garbage Collection - GC):JVM 自动管理内存的分配和回收,程序员无需手动释放内存(如 C/C++ 中的 free/delete),有效避免了内存泄漏(Memory Leak)和悬空指针(Dangling Pointer)等常见问题。

安全性:Java 设计之初就考虑了安全性,尤其是在网络环境下:

  • 沙箱机制(Sandbox):限制不受信任代码(如早期的 Applet)的权限,防止其访问本地文件系统、网络等敏感资源。
  • 字节码验证器(Bytecode Verifier):在 JVM 加载字节码时进行检查,确保其符合规范,防止恶意代码破坏系统。
  • 安全管理器(Security Manager):(虽然在现代应用中使用减少)可以进一步定义代码的权限。
  • 加密和安全 API:提供了丰富的 API 支持加密、数字签名、认证等安全功能。

多线程

  • Java 内置了对多线程编程的支持。一个 Java 程序可以同时运行多个执行路径(线程)。这使得开发高并发、响应迅速的应用(如服务器、图形界面程序)变得更加容易。
  • Java 提供了 Thread 类、Runnable 接口以及 java.util.concurrent 包等工具来简化多线程开发。

分布式:Java 为网络编程提供了强大的内置支持(如 java.net 包),可以轻松地开发能够通过网络进行通信和数据交换的应用程序,如客户端-服务器(Client-Server) 应用、Web 服务等。

高性能

  • 虽然早期的解释执行模式较慢,但现代 JVM 采用了即时编译(Just-In-Time Compilation - JIT) 技术。
  • JIT 会将热点(频繁执行)的字节码编译成本地机器码,从而获得接近 C/C++ 的执行速度。加上不断优化的垃圾回收算法,Java 的性能已经非常出色。

动态性

  • Java 能够适应不断变化的环境,其库可以自由地添加新方法和实例变量,而不会影响其客户端。
  • Java 还支持反射(Reflection) 机制,允许程序在运行时检查类、接口、字段和方法的信息,并能动态调用对象的方法或访问其属性,这为框架(如 Spring)的实现提供了基础。
1.1.3 Java 技术体系

Java 的技术生态系统,主要分为三个平台:

  • Java SE:Standard Edition - 标准版
  • Java EE:Enterprise Edition - 企业版
  • Java ME:Micro Edition - 微型版

Java SE

  • 核心:Java 的基础和核心,包含语言基础、核心 API(如 java.lang,java.utiljava.iojava.netjava.sql 等)、JVM。
  • 用途:用于开发桌面应用程序、命令行工具以及作为 Java EE 和 Java ME 的基础。

Java EE

  • 核心:建立在 Java SE 之上,提供了一套用于开发大型、分布式、多层企业级应用的 API 和运行时环境。
  • 关键组件/技术:ServletJSP(JavaServer Pages)EJB(Enterprise JavaBeans)JPA(Java Persistence API)JMS(Java Message Service)Web Services(JAX-WS,JAX-RS) 等。
  • 应用服务器:需要部署在应用服务器上运行,如 Tomcat(主要支持 Servlet/JSP),WildFly,WebLogic,WebSphere。
  • 现状:Java EE 已被捐赠给 Eclipse 基金会,并更名为 Jakarta EE。

Java ME

  • 核心:为资源受限的设备(如早期的手机、PDA、嵌入式设备、物联网设备)设计的精简版 Java 平台。
  • 用途:开发运行在小型设备上的应用程序。随着 Android 的崛起,其在手机领域的应用已大大减少,但在特定嵌入式领域仍有应用。

1.2 Java 开发环境

1.2.1 Java 开发环境介绍

JVM:JVM(Java Virtual Machine - Java 虚拟机)是 Java 平台无关性(“一次编写,到处运行”)的基石和执行引擎。可以把它看作是 JVM 的“运行套装”。

JRE:JRE(Java Runtime Environment - Java 运行时环境)是运行 Java 程序所必需的最小环境。

JDK:JDK(Java Development Kit - Java 开发工具包)是用于开发 Java 应用程序的完整工具包,它是功能最全的“开发套件”。

JDK、JRE、JVM 共同构成了 Java 的开发和运行环境,三者关系如下:

JDK、JRE、JVM

1.2.2 JDK 下载

JDK 的下载可以通过但不限于以下途径:

  • Oracle 官网:Oracle 是 JDK 的官方发布者,提供最新版本的 JDK。
  • OpenJDK 官网:OpenJDK 是开源的 JDK 实现,适合大多数开发场景。
  • Adoptium 官网:原 AdoptOpenJDK,由 Eclipse 基金会维护,提供高质量的 OpenJDK 构建版本。
  • Dragonwell 官网:Dragonwell 是阿里巴巴提供的国产优化版,阿里巴巴推出的长期支持的 OpenJDK 发行版,针对云环境进行了性能优化。

Java 环境变量配置,主要是配置:

  • JAVA_HOME:指向 JDK 的安装目录,其他工具(如 Maven、Tomcat)会依赖此变量。
  • CLASSPATH:Java 类文件(.class)的搜索路径,现代 JDK 通常可省略此配置。
  • PATH:系统可执行命令的搜索路径,便于在命令行中直接使用 javajavac 等命令。

注意:

  • CLASSPATHJDK 1.5 以后已默认包含当前目录(.),大多数情况下无需手动设置。
  • tools.jardt.jarJDK 9+ 模块化后已被移除或整合,因此高版本 JDK 不需要这些。
1.2.3 Windows 免安装版

下载免安装版的 JDK,解压并放置到指定想要安装的目录,如 C:\Program Files (x86)\Java\jdk1.8.0_91

配置环境变量,右击“我的电脑”→“属性”→“高级系统设置”→“环境变量”。

设置 JAVA_HOME,在“系统变量”中点击“新建”:

  • 变量名:JAVA_HOME
  • 变量值:C:\Program Files (x86)\Java\jdk1.8.0_91,这个目录需要根据实际路径修改

在“系统变量”中找到 Path,点击“编辑”→“新建”

  • 添加:%JAVA_HOME%\bin

设置 CLASSPATH,在“系统变量”中点击“新建”:

  • 变量名:CLASSPATH
  • 变量值:.;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\lib\dt.jar

JDK 环境变量配置的验证,打开命令提示符(cmd)输入以下命令验证,如果显示版本信息和正确路径,说明配置成功。

java -version
javac -version
echo %JAVA_HOME%

1.3 Java 开发工具

开发 Java 语言常用的开发工具如下:

  • IntelliJ IDEA:目前比较主流的 Java 开发 IDE,由 JetBrain 公司提供。
  • Eclipse:一款开源免费的开发工具,界面略显陈旧,配置相对比较复杂。
  • Visual Studio Code:(VS Code),通过添加 Java 插件的方式满足 Java 语言开发。
  • NetBeans:Apache 维护的开源 IDE,对 Java EE(Jakarta EE)支持良好,但是使用人数较少,适合特定场景。

IntelliJ IDEA 常用插件:

  • Alibaba Java Coding Guidelines:阿里规约,检测代码是否符合《阿里巴巴 Java 开发手册》规范
  • Lombok Plugin:支持 Lombok 注解(@Data、@Getter、@Setter 等),减少模板代码,需在 pom.xml 中引入 Lombok 依赖。
  • MyBatisX:MyBatis/MyBatis-Plus 映射跳转、XML 与接口方法互查。
  • Spring Boot Helper/Spring Assistant:快速生成 Spring Boot 项目结构、配置提示、端点检测。
  • Rainbow Brackets:为不同层级的括号添加颜色,提升代码可读性,尤其适合嵌套复杂的表达式。
  • Translation:官方翻译插件,直接翻译类名、变量名、文档注释。支持谷歌、有道、百度等翻译。
  • GitToolBox/Git Commit Template:增强 Git 提交信息提示、自动补全、提交模板。
  • GenerateAllSetter:右键对象可一键调用 .setXXX().setYYY() 链式赋值。
  • Database Tools and SQL:内置功能,支持连接 MySQL、Oracle、PostgreSQL 等数据库,可直接执行 SQL、查看表结构,无需切换工具。
  • Maven Helper:分析依赖冲突、可视化 pom.xml 依赖树,解决 jar 包冲突利器。
  • Grep Console:针对控制台日志,设置不同级别日志的字体颜色和背景色。
  • CodeGlance:CodeGlance 是一款代码编辑区缩略图插件,可以快速定位代码。
  • RestfulToolkit:RestfulToolkit 是一套 RESTful 服务开发辅助工具集。
  • JRebel:热部署插件,可以在修改完代码后,不用重新启动代码。
  • Json Parser:JSON 格式化工具。
  • SonarLint:代码静态分析,专注于代码质量。
  • AI 相关插件:
    • JetBrains AI Assistant:官方提供的 AI 插件
    • Lingma:阿里提供通义灵码的插件
    • CodeGeeX:支持代码生成、翻译、解释
    • GitHub Copilot:代码自动补全
    • AI Code Reviewer:代码审查助手
    • tabnine:智能代码补全,AI 问答等
    • Code Vision:代码智能提示插件,在方法或类名上方显示 AI 分析结果,如:代码复杂度评分、潜在性能问题提示、测试覆盖率建议等。

VS Code 针对 Java 开发的常用插件:

  • Java Extension Pack:官方推荐合集,包含以下核心插件,安装一个等于安装六个:
    • Language Support for Java™ by Red Hat
    • Debugger for Java
    • Test Runner for Java
    • Maven for Java
    • Project Manager for Java
    • Visual Studio Code for Java
  • Spring Boot Extension Pack:包含如下
    • Spring Boot Tools:自动补全、配置提示
    • Spring Initializr Java Support:快速创建项目
  • Lombok Annotations Support:支持 Lombok 注解解析
  • Code Runner`:一键运行 Java、Python、C++ 等单文件程序
  • Chinese (Simplified) Language Pack:中文语言包,界面汉化

Eclipse 常用插件:

  • Lombok for Eclipse:需要手动安装,下载 lombok.jar,双击运行指定 Eclipse 安装路径。
  • Spring Tools 4 (STS):官方 Spring 工具包,支持 Spring Boot 自动配置提示,可通过 Eclipse Marketplace 安装。
  • MyBatis Generator:自动生成 MyBatis 实体类、Mapper 接口和 XML 文件。
  • FindBugs/SpotBugs:静态代码分析工具,查找潜在 bug。
  • EGit:Eclipse 内置 Git 客户端,方便版本控制。

二、Java 语言基础

2.1 Java 程序入口点

每个可独立运行的 Java 程序都必须包含一个 main 方法,main 方法是 Java 程序的入口点(Entry Point),JVM 在启动程序时会自动查找并执行这个方法。

main 方法如下:

public static void main(String[] args) {System.out.println("Hello, World!");
}

main 方法解释:

  • public:访问修饰符,表示该方法可以被外部调用(特别是被 JVM 调用)。必须是 public,否则 JVM 无法访问。
  • static:静态方法,表示该方法属于类本身,而不是类的实例。这样 JVM 可以在不创建对象的情况下直接调用 main 方法。
  • void:返回类型,表示该方法没有返回值。main 方法不能有返回值。
  • main:方法名,JVM 规定的入口方法名称,不能更改。
  • String[] args:方法参数,用于接收命令行传递的参数(如字符串数组)。

main 方法的注意事项:

  • 必须是 public static void
  • 方法名必须是 main
  • 参数必须是 String[] 类型
  • 一个类可以有多个 main 方法(重载),但只有签名正确的才是入口
  • main 方法可以抛出异常

main 方法对比:

public static void main(String[] args) { ... } // ✅ 入口
public static void main() { ... }              // ❌ 不是入口
public static void main(String args) { ... }   // ❌ 参数类型不对

main 方法抛出异常:

public static void main(String[] args) throws Exception {// 可能出错的操作
}

2.2 Java 基本语法

Java 语法的基本规则:

  • 大小写敏感:Java 是大小写敏感的语言,HelloWorld 和 helloworld 是两个不同的标识符,类名、方法名、变量名都区分大小写。

  • 类名命名规则:首字母大写,采用大驼峰命名法(PascalCase),如 MyClass, StudentInfo, BankAccount

  • 方法名命名规则:首字母小写,后续单词首字母大写(小驼峰命名法 camelCase)如 main(), handleUserInfo(), getUserName()

  • 代码块:代码块使用花括号 {}

  • 代码语句:每条语句以分号 ; 结束。

  • 变量名和函数参数:只能包含字母、数字、_$,必须以字母、$_ 开头,不能以数字开头。`推荐使用有意义的名称,采用小驼峰

  • 源文件名:源文件名必须和类名相同。当保存文件的时候,应该使用类名作为文件名保存,文件名的后缀为 .java,如果文件名和类名不相同则会导致编译错误。

  • 代码注释:

    • 单行注释:使用 //,注释单行代码
    • 多行注释:使用 /* 多行<br>注释 */,注释多行代码
    • 文档注释:使用 /** JavaDoc 注释 */,常用于生成 API 文档,可被 javadoc 工具解析

注释示例:

// 这是单行注释,可以注释单行
int x = 10; // 行内的单行注释/*
这是多行注释
可以注释多行*//*** 这是文档注释* 也可以注释多行* 常用于生成 API 文档*/

2.3 Java 基本数据类型

2.3.1 基本数据类型介绍

Java 中的基本数据类型分为四大类:整数型、浮点型、字符型、布尔型。其中:

  • 整数型包括字节型、短整型、整形和长整型
  • 浮点型包括单精度和双精度

基本数据类型对比如下:

分类数据类型关键字占用空间取值范围默认值
整数型字节型byte1 字节(8 位)-128 到 1270
短整型short2 字节(16 位)-32,768 到 32,7670
整型int4 字节(32 位)-2³¹ 到 2³¹-1(约 -21 亿 ~ 21 亿)0
长整型long8 字节(64 位)-2⁶³ 到 2⁶³-10L
浮点型单精度float4 字节(32 位)约 ±3.4×10³⁸(6-7 位有效数字)0.0f
双精度double8 字节(64 位)约 ±1.8×10³⁰⁸(15 位有效数字)0.0d
字符型字符char2 字节(16 位)0 到 65,535(Unicode 字符)\u0000
布尔型布尔boolean未定义(通常 1 位)true 或 falsefalse

整数型:

  • 用于表示没有小数部分的数字。
  • long 类型字面量必须加 L,否则会被当作 int

浮点型:

  • 浮点数默认是 double 类型,赋值给 float 必须加 f
  • 不要用 float/double 表示金钱!因为会有精度丢失问题。

字符型 char

  • 表示单个字符,使用单引号 ' '

布尔型 boolean

  • 表示逻辑值,只有两个值:truefalse
  • boolean 类型在 JVM 中实际占用空间由虚拟机实现决定,但逻辑上只表示真假。
2.3.2 数据类型转换

Java 中各种数据类型间可以进行互相转换:

  • 从小类型自动转为大类型为自动类型转换,也叫隐式转换。如 byte → short → int → long → float → double
  • 从大类型转小类型为强制类型转换,也叫显式转换,这种转换可能会丢失精度。如 double → float → long → int → short → byte

自动类型转换示例:

int a = 100;
long b = a;     // ✅ int → long(安全)float f = 3.14f;
double d = f;   // ✅ float → double

强制类型转换示例:

long l = 1000L;
int i = (int) l;  // ✅ 强制转换double d = 3.99;
int n = (int) d;  // 结果是 3(直接截断,不四舍五入)
2.3.3 Java 包装类

在 Java 中,基本数据类型(Primitive Data Types) 和 包装类(Wrapper Classes) 是两种表示数据的方式。

为了使基本类型能参与面向对象操作(如放入集合、泛型),Java 为每种基本类型提供了对应的包装类,它们是对象,位于 java.lang 包中。

基本类型包装类对象示例
byteByteByte b = 10;
shortShortShort s = 20;
intIntegerInteger i = 100;
longLongLong l = 1000L;
floatFloatFloat f = 3.14f;
doubleDoubleDouble d = 3.14159;
charCharacterCharacter c = ‘X’;
booleanBooleanBoolean flag = true;

自动装箱与拆箱:

  • 自动装箱(Autoboxing):将基本类型自动转换为对应的包装类对象。
  • 自动拆箱(Unboxing):将包装类对象自动转换为基本类型。

2.4 Java 变量与常量

2.4.1 变量与常量介绍

在 Java 编程中,变量(Variable)和常量(Constant)是存储数据的基本方式。

  • 变量:变量是程序中用于存储数据值的容器,它的值在程序运行过程中可以被修改。
  • 常量:常量是在程序运行期间其值不能被改变的量。
2.4.2 Java 变量

变量的声明与赋值语法:

// 先声明变量,再给变量赋值
数据类型 变量名;
变量名 =;// 声明变量的同时给变量赋值
数据类型 变量名 =;

变量示例:

int age;           // 声明变量
age = 25;          // 给变量赋值double price = 9.99;     // 声明变量时初始化值
String name = "张三";    // 字符串变量声明并赋值

变量的命名规则

  • 只能包含:字母、数字、_$
  • 不能以数字开头:如1age
  • 区分大小写:ageAge 是两个变量
  • 不能是 Java 关键字:如 int class = 10
  • 推荐使用小驼峰命名法(camelCase):userName, studentInfo

变量的作用域:变量根据定义位置不同,其作用域(Scope)也不同

  • 局部变量:定义在方法内部,仅在该方法内有效,使用前必须先初始化
  • 成员变量:也叫实例变量,定义在类中、方法外,成员变量属于对象,在整个类都可访问,有默认值。
  • 静态变量:也叫类变量,用 static 修饰,静态变量属于类,是所有实例共享的。

变量的作用域示例:

public class Student {// 成员变量,默认 null,当前类可访问private String name;// 静态变量,当前类可访问private static String CLASS_NUM = "一班";public void study() {// 局部变量,必须初始化,当前方法可访问int count = 5;}
}

局部变量(方法内的变量)没有默认值,必须手动初始化才能使用,如下:

public void test() {int x;System.out.println(x); // ❌ 编译错误:变量未初始化
}
2.5.3 Java 常量

常量使用 final 关键字修饰,变量名通常使用全大写字母,单词间用下划线 _ 分隔。变量在声明时就必须初始化。

常量声明语法如下:

final 数据类型 常量名 =;

常量示例:

final int MAX_AGE = 120;
final double PI = 3.1415926;
final String NAME = "张三";

常量的好处

  • 防止误修改:避免程序中意外更改关键数值
  • 提高可读性:PI 比 3.1415926 更易理解
  • 便于维护:如果需要修改,只需改一处

2.5 Java 修饰符

2.5.1 Java 修饰符介绍

修饰符用来定义类、方法、变量等的关键词,用于控制访问权限、行为特性和生命周期。通常放在语句的最前端。

Java 语言提供了很多修饰符,主要分为以下两类:

  • 访问修饰符
  • 非访问修饰符
2.5.2 访问控制修饰符

访问控制修饰符用来保护对类、变量、方法和构造方法的访问,Java 支持 4 种不同的访问权限:

  • default:默认的修饰符,在同一包内可见。可用于修饰类、接口、变量、方法。
  • private:在同一类内可见。可用于修饰变量、方法。private 不能修饰外部类。
  • public:对所有类可见。可用于修饰类、接口、变量、方法。
  • protected:对同一包内的类和所有子类可见。可以用修饰变量、方法。protected 不能修饰外部类。

访问修饰符的访问权限对比:

修饰符当前类同一包内同包子孙类不同包子孙类其他包
publicYYYYY
protectedYYYY/N(通过继承)N
defaultYYYNN
privateYNNNN

protected 说明:

  • 子类与基类在同一包中:被声明为 protected 的变量、方法和构造器能被同一个包中的任何其他类访问;
  • 子类与基类不在同一包中:那么在子类中,子类实例可以访问其从基类继承而来的 protected 方法,而不能访问基类实例的 protected 方法。

访问控制权限和继承:

  • 父类中声明为 public 的方法在子类中也必须为 public
  • 父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private
  • 父类中声明为 private 的方法,不能够被子类继承。
2.5.3 非访问修饰符

非访问修饰符用于定义类、方法、变量的行为特性,Java 提供的常用非访问修饰符如下:

  • static
  • final
  • abstract
  • synchronized
  • volatile
  • transient
  • native

static 修饰符:

static 用来修饰类方法、类变量和代码块:

  • 修饰变量时:该变量属于类变量,所有实例共享
  • 修饰方法时:该方法属于类方法,不依赖对象即可调用
  • 修饰代码块时:该代码块只会在类加载时执行一次

static示例:

public class StaticDemo {// 静态变量,所有对象共享static int count = 0;// 静态方法static void handleCount() {System.out.println("Count: " + count);}// 静态代码块static {System.out.println("静态代码块,类加载时执行");}
}// 其他类调用 displayCount 方法时无需创建对象
Counter.displayCount();

final 修饰符用来修饰类、方法和变量:

  • final 修饰类时,该类不能够被继承。String 类是 final 的,不能被继承
  • final 修饰方法时,该方法不能被子类重写(override)
  • final 修饰变量时,即为常量,是不可修改的。

final示例:

// 该类不能被继承
final class MathUtils {// 常量final double PI = 3.14159;// 该方法不能被重写final void printInfo() {System.out.println("工具类");}
}

abstract 修饰符用来创建抽象类和抽象方法。

  • abstract 修饰类时,该类不能被实例化,必须被继承
  • abstract 修饰方法时:该方法只有声明,没有实现,子类继承时实现

abstract 示例:

abstract class Animal {// 抽象方法,无方法体,由子类实现abstract void makeSound();// 普通方法可以有实现void sleep() {System.out.println("Animal is sleeping");}
}class Dog extends Animal {// 必须重写抽象方法void makeSound() {System.out.println("Woof!");}
}

synchronized 用来修饰方法或代码块,保证线程安全,同一时间只有一个线程能执行。

synchronized 示例:

public synchronized void withdraw(double amount) {// 银行取款操作,防止多线程并发问题
}

volatile 用于修饰变量,确保多线程环境下变量的可见性(立即写回主内存)

volatile 示例:

private volatile boolean running = true;public void stop() {running = false;
}

transient 用于修饰变量,表示该变量不参与序列化。

transient 示例:

class User implements Serializable {String name;transient String password;  // 序列化时忽略密码
}

native 用于修饰方法,表示该方法由其他语言(如 C/C++)实现,通常用于调用操作系统底层功能。

native 示例:

public native void startThread();

2.6 Java 运算符

Java 提供了一套丰富的运算符来操纵变量,主要如下:

  • 算术运算符
  • 关系运算符
  • 位运算符
  • 逻辑运算符
  • 赋值运算符
  • 其他运算符
2.6.1 算术运算符

Java 提供的算术运算符如下:

  • +:加法
  • -:减法
  • *:乘法
  • /:除法
  • %:取模(求余数)
  • ++:自增
  • --:自减

算术运算符示例:

int a = 20;
int b = 10;
int c = a + b;
int d = a - b;
int e = a * b;
int f = a / b;
int g = a % b;
int h = a++;
int i = ++a;
int j = a--;
int k = --a;

a++++a,和 a----a

  • a++++a 都表示将变量 a 的值加 1,但执行时机和返回值不同。
  • a++ 是先使用原值,再加 1;++a 先加 1,再使用新值
int a = 20;
System.out.println("a=" + a++);  // 20
System.out.println("a=" + a);    // 21
int b = 20;
System.out.println("b=" + ++b);  // 21
System.out.println("b=" + b);    // 21

a----a 的逻辑和 a++++a 一样。

2.6.2 关系运算符

Java 提供的关系运算符如下:

  • ==:等于
  • !=:不等于
  • >:大于
  • <:小于
  • >=:大于等于
  • <=:小于等于

关系运算符示例:

System.out.println(1 == 1); // true
System.out.println(1 != 1); // false
System.out.println(1 > 1);  // false
System.out.println(1 < 1);  // false
System.out.println(1 >= 1); // true
System.out.println(1 <= 1); // true
2.6.3 位运算符

位运算符(Bitwise Operators)是 Java 中用于对整数类型的二进制位进行操作的运算符。

位运算符直接操作数据的二进制表示,效率高,常用于底层编程、性能优化、加密算法、状态标志等场景。

Java 提供的位运算符如下:

  • &:按位与(AND),两个位都为 1 时结果为 1
  • |:按位或(OR),;两个位有一个位 1 时结果为 1,否则为 0
  • ^:按位异或(XOR),两个位不同结果为 1,相同为 0
  • ~:按位取反(NOT):单目运算符,0 变 1,1 变 0
  • <<:左移:左移若干位,低位补 0
  • >>:右移:右移若干位,高位补符号位(正数补 0,负数补 1)
  • >>>:无符号右移:右移若干位,高位始终补 0

位运算符适用于:byteshortintlongchar 等整数类型。

位运算符示例:

// & 按位与
int a = 6 & 3;  // 0110 & 0011 = 0010 → 结果是 2
// | 按位或
int a = 6 | 3;  // 0110 | 0011 = 0111 → 结果是 7
// ^ 按位异或
int a = 6 ^ 3;  // 0110 ^ 0011 = 0101 → 结果是 5
// ~ 按位取反
int a = ~6;  // ~0110 = 1001(在 32 位中是补码表示)
// << 左移
int a = 6 << 1;  // 0110 << 1 = 1100 → 结果是 12
// >> 右移
int a = 6 >> 1;  // 0110 >> 1 = 0011 → 结果是 3
// >>> 无符号右移
int a = -6 >>> 1;  // 高位补 0,不考虑符号

位运算注意:

  • 位运算符优先级较低,常需加括号。
  • 类型提升:byteshort 会先提升为 int 再进行位运算。
  • 负数使用补码:Java 中所有整数以补码存储,位运算基于补码。
  • >>>>> 区别:>> 保持符号,>>> 忽略符号,高位补 0。
2.6.4 逻辑运算符

Java 提供的逻辑运算符如下:

  • &&:逻辑与,条件同时满足则为 true
  • ||:逻辑或,只要有一个条件满足则为 true
  • !:逻辑非,对结果取相反的值

逻辑运算符示例:

System.out.println(true && false);  // false
System.out.println(true || false);  // true
System.out.println(!true);          // false
2.6.5 赋值运算符

赋值运算符(Assignment Operators) 用于将某个值或表达式的结果赋给一个变量。

Java 提供的赋值运算符如下:

  • =:基本赋值
  • +=:复合赋值,加之后再赋值,等价于 a = a + b
  • -=:复合赋值,减之后再赋值,等价于 a = a - b
  • *=:复合赋值,乘之后再赋值,等价于 a = a * b
  • /=:复合赋值,除之后再赋值,等价于 a = a / b
  • %=:复合赋值,取模之后再赋值,等价于 a = a % b
  • &=:复合赋值,按位与之后再赋值,等价于 a = a & b
  • |=:复合赋值,按位或之后再赋值,等价于 a = a | b
  • ^=:复合赋值,按位异或之后再赋值,等价于 a = a ^ b
  • <<=:复合赋值,左移之后再赋值,等价于 a = a << b
  • >>=:复合赋值,右移之后再赋值,等价于 a = a >> b
  • >>>=:复合赋值,无符号右移之后再赋值,等价于 a = a >>> b

赋值运算符示例:

int x = 5;
// 位运算复合赋值
x &= 5;     // 相当于 x = x & 5; → 5 & 5 = 5
x |= 3;     // 相当于 x = x | 3; → 5 | 3 = 7
x ^= 6;     // 相当于 x = x ^ 6; → 7 ^ 6 = 1
x <<= 4;    // 相当于 x = x << 4; → 1 << 4 = 16
x >>= 2;    // 相当于 x = x >> 2; → 16 >> 2 = 4
x >>>= 1;   // 相当于 x = x >>> 1; → 4 >>> 1 = 2
2.6.6 其他运算符

Java 还提供了一些其他的运算符,常用如下:

  • ?::三元运算符,根据判断条件决定取哪个值,语法:condition?value if true : value if false
  • instanceof:类型比较运算符,用于操作对象实例

示例:

// 三元运算符
int a = 10, b = 5;
int result = (a > b) ? a : b; // 如果a>b返回a,否则返回b// instanceof示例
public class App {public static void main(String[] args) {System.out.println(new Object() instanceof Object); // trueSystem.out.println(new Object() instanceof String); // falseSystem.out.println(new Object() instanceof App);    // false}
}

三、Java 流程控制

3.1 Java 条件语句

3.1.1 if 条件语句

if 语句用于根据条件的真假来决定是否执行代码块。

if 语法:

// if
if (条件) {// 条件为true时执行的代码
}// if-else
if (条件) {// 条件为true时执行
} else {// 条件为false时执行
}// if-else if-else
if (条件1) {// 条件1为true时执行
} else if (条件2) {// 条件2为true时执行
} else {// 所有条件都为false时执行
}

if 示例:

int score = 85;if (score >= 90) {System.out.println("优秀");
} else if (score >= 80) {System.out.println("良好");
} else if (score >= 60) {System.out.println("及格");
} else {System.out.println("不及格");
}
// 输出:良好
3.1.2 switch 分支语句

switch 语句用于基于不同的值执行不同的代码块,适合处理多分支选择。

switch 语法:

switch (表达式) {case1:// 执行代码break;case2:// 执行代码break;default:// 默认执行代码(可选)
}

switch 示例:

int day = 3;
String dayName;switch (day) {case 1:dayName = "星期一";break;case 2:dayName = "星期二";break;case 3:dayName = "星期三";break;case 4:dayName = "星期四";break;case 5:dayName = "星期五";break;default:dayName = "周末";break;
}System.out.println(dayName); // 输出:星期三

switch-case 语句中,如果某个 case 分支 没有 break; 语句,程序会继续执行下一个 casedefault 分支中的代码,直到遇到 breakreturnswitch 语句结束。这种现象叫做“穿透”

示例:

int day = 2;
switch (day) {case 1:System.out.println("星期一");case 2:System.out.println("星期二");case 3:System.out.println("星期三");case 4:System.out.println("星期四");default:System.out.println("其他");
}// 输出结果:
星期二
星期三
星期四
其他

default 分支可以不放在 switch 语句的最后(不推荐这么做):

  • 如果 default 是最后一个分支,可以不写 break
  • 如果 default 不在最后,必须写 break,否则会继续执行后面的 case

3.2 Java 循环语句

3.2.1 for 循环语句

for 循环用于在已知循环次数的情况下重复执行代码。

for 语法:

// 基础 for 循环
for (初始化; 条件; 更新) {// 循环体
}// 增强 for 循环:for-each
for (元素类型 变量名 : 数组或集合) {// 循环体
}

for 示例:

// 基础 for 循环示例:
for (int i = 1; i <= 5; i++) {System.out.println(i);
}// 增强 for 循环示例
String[] names = {"张三", "李四", "王五"};
for (String name : names) {System.out.println("你好," + name);
}
3.2.2 while 循环语句

while 循环在条件为 true 时重复执行代码块。

while 语法:

while (条件) {// 循环体
}

while 示例:

int i = 1;
while (i <= 5) {System.out.println(i);i++;
}
3.2.3 do…while 循环语句

do...while 循环也是在条件为 true 时重复执行代码块,但是会先执行一次循环体,然后在条件为 true 时继续执行。

do...while 语法:

do {// 循环体
} while (条件);

do...while 示例:

int j = 1;
do {System.out.println(j);j++;
} while (j <= 5);

3.3 Java 循环控制

3.3.1 break 语句

break 是 Java 中的一个控制流语句,用于提前终止某个循环或 switch 语句的执行,程序会跳转到该结构之后的下一条语句继续执行。

break 只能用于循环或 switch 语句,不能在普通代码块中使用。

break 在 switch 语句中使用可以防止“穿透”,示例:

int day = 2;
switch (day) {case 1:System.out.println("星期一");break;case 2:System.out.println("星期二");break;  // 执行完这里就跳出 switchcase 3:System.out.println("星期三");break;default:System.out.println("其他");
}

break 在循环中使用,用于提前退出循环,可用于 forwhiledo-while 循环,一旦执行 break,立即结束整个循环。

for 循环中使用:

for (int i = 1; i <= 10; i++) {if (i == 5) {break;  // 当 i 等于 5 时,跳出循环}System.out.print(i + " ");
}// 输出:1 2 3 4

while 循环中使用:

int i = 1;
while (i <= 10) {if (i == 6) {break;}System.out.print(i + " ");i++;
}// 输出:1 2 3 4 5

带标签的 break,用于从嵌套循环中直接跳出外层循环,语法如下:

labelName:
for ( ... ) {for ( ... ) {break labelName;  // 跳出外层循环}
}

示例:

int[][] matrix = {{1, 2, 3},{4, 5, 6},{7, 8, 9}
};boolean found = false;
outer: // 标签
for (int i = 0; i < matrix.length; i++) {for (int j = 0; j < matrix[i].length; j++) {if (matrix[i][j] == 5) {System.out.println("找到 5,位置:[" + i + "][" + j + "]");found = true;break outer;  // 直接跳出最外层循环}}
}if (found) {System.out.println("搜索结束。");
}// 输出结果
找到 5,位置:[1][1]
搜索结束。
3.3.2 continue 语句

continue 是 Java 中的一个控制流语句,用于在循环中跳过当前这一次迭代,直接进入下一次循环的判断和执行,不会终止整个循环。

for 循环中使用:

for (int i = 1; i <= 10; i++) {if (i % 2 == 0) {continue;  // 如果是偶数,跳过本次循环}System.out.print(i + " ");
}// 输出结果:
1 3 5 7 9

在 while 循环中使用:

int i = 0;
while (i < 5) {i++;if (i == 3) {continue;  // 跳过 i=3 时的打印}System.out.print(i + " ");
}// 输出结果:
1 2 4 5

do-while 循环中使用

int i = 0;
do {i++;if (i == 2) {continue;}System.out.print(i + " ");
} while (i < 3);// 输出结果:
1 3

带标签的 continue 用于在嵌套循环中,跳过外层循环的当前迭代,语法:

outer:
for ( ... ) {for ( ... ) {continue outer;  // 跳过外层循环的当前迭代}
}

示例:

outer:
for (int i = 1; i <= 3; i++) {for (int j = 1; j <= 3; j++) {if (i == 2) {continue outer;  // 当 i=2 时,跳过整个内层循环,直接进入 i=3}System.out.print(i + "," + j + " ");}System.out.println(); // 换行
}// 输出结果:
1,1 1,2 1,3
3,1 3,2 3,3

四、Java 数组

4.1 数组概述

数组是一种用于存储固定大小的同类型元素的数据结构,是 Java 中最基本的数据结构之一。

数组的特点:

  • 存储相同类型的元素
  • 长度固定,一旦创建不能改变
  • 元素按顺序存储
  • 通过索引访问元素,索引从 0 开始

数组分为:

  • 一维数组
  • 二维数组

4.2 一维数组

一维数组是最基本的数组形式,可以看作是一排连续的"格子",每个格子存储一个相同类型的数据。

语法:

// 声明方式(两种等效写法)
int[] arr;     // 推荐写法
int arr[];// 创建数组(动态初始化)
arr = new int[5]; // 创建长度为5的整型数组// 声明并创建
double[] scores = new double[10];
String[] names = new String[3];

一维数组初始化示例:

// 方式1:动态初始化(系统赋予默认值)
int[] arr1 = new int[5]; // {0, 0, 0, 0, 0}// 方式2:静态初始化(手动赋值)
int[] arr2 = new int[]{1, 2, 3, 4, 5};// 方式3:简化静态初始化(最常用)
int[] arr3 = {1, 2, 3, 4, 5};
String[] fruits = {"苹果", "香蕉", "橙子"};

数组使用示例:

public static void main(String[] args) {// 创建并初始化数组int[] numbers = {10, 20, 30, 40, 50};// 获取数组长度System.out.println("数组长度:" + numbers.length); // 5// 访问和修改元素System.out.println("第一个元素:" + numbers[0]); // 10numbers[1] = 25; // 修改第二个元素// 遍历数组System.out.println("遍历数组:");for (int i = 0; i < numbers.length; i++) {System.out.println("numbers[" + i + "] = " + numbers[i]);}// 增强for循环遍历System.out.println("增强for循环:");for (int num : numbers) {System.out.print(num + " ");}System.out.println();
}

4.2 二维数组

二维数组可以看作是"数组的数组",形成一个表格结构,有行和列两个维度。

  • 每个元素通过两个索引访问:行索引和列索引
  • 可以是规则的(每行长度相同)或不规则的(锯齿数组)

语法:

// 声明
int[][] matrix;// 创建规则二维数组(3行4列)
matrix = new int[3][4];// 声明并创建
double[][] table = new double[2][3];
String[][] grid = new String[3][3];

二维数组初始化示例:

// 方式1:动态初始化(默认值)
int[][] arr1 = new int[3][3]; // 全部为0// 方式2:静态初始化
int[][] arr2 = new int[][]{{1, 2, 3},{4, 5, 6},{7, 8, 9}
};// 方式3:简化静态初始化
int[][] matrix = {{1, 2, 3},{4, 5, 6},{7, 8, 9}
};// 不规则数组(锯齿数组)
int[][] jagged = {{1, 2},{3, 4, 5},{6, 7, 8, 9}
};

二维数组使用示例:

public static void main(String[] args) {// 创建并初始化二维数组int[][] matrix = {{1, 2, 3},{4, 5, 6},{7, 8, 9}};// 获取数组维度System.out.println("行数:" + matrix.length);            // 3System.out.println("第一行列数:" + matrix[0].length);    // 3// 访问和修改元素System.out.println("matrix[0][0]:" + matrix[0][0]);     // 1matrix[1][1] = 55; // 修改中间元素// 遍历二维数组System.out.println("遍历二维数组:");for (int i = 0; i < matrix.length; i++) {for (int j = 0; j < matrix[i].length; j++) {System.out.print(matrix[i][j] + "\t");}System.out.println(); // 换行}// 增强for循环遍历System.out.println("增强for循环遍历:");for (int[] row : matrix) {for (int element : row) {System.out.print(element + "\t");}System.out.println();}
}

五、Java 常用类

5.1 Number 类

5.1.1 Number 类介绍

Number 类是 Java 中所有"数字包装类"的抽象父类,位于 java.lang 包中,它为各种数值类型提供了统一的接口。

Number 类源码:

public abstract class Number implements java.io.Serializable {// 抽象方法,子类必须实现public abstract int intValue();public abstract long longValue();public abstract float floatValue();public abstract double doubleValue();public byte byteValue() {return (byte)intValue();}public short shortValue() {return (short)intValue();}private static final long serialVersionUID = -8742448824652078965L;
}

Number 类的方法示例:

Number num = 3.1415926;
System.out.println(num.byteValue());    // 3
System.out.println(num.shortValue());   // 3
System.out.println(num.intValue());     // 3
System.out.println(num.longValue());    // 3
System.out.println(num.floatValue());   // 3.1415926
System.out.println(num.doubleValue());  // 3.1415926

所有的包装类(IntegerLongByteDoubleFloatShort)都是抽象类 Number 的子类。

Number 类及其子类

5.1.2 Number 类的子类

Byte 类源码:

public final class Byte extends Number implements Comparable<Byte> {...
}

Short 类源码:

public final class Short extends Number implements Comparable<Short> {...
}

Integer 类源码:

public final class Integer extends Number implements Comparable<Integer> {...
}

Long 类源码:

public final class Long extends Number implements Comparable<Long> {...
}

Double 类源码:

public final class Double extends Number implements Comparable<Double> {...
}

Float 类源码:

public final class Float extends Number implements Comparable<Float> {...
}

BigInteger 类源码:

public class BigInteger extends Number implements Comparable<BigInteger> {...
}

BigDecimal 类源码:

public class BigDecimal extends Number implements Comparable<BigDecimal> {...
}

5.2 Math 类

5.2.1 Math 类介绍

Math 类是 Java 中用于数学运算的工具类,位于 java.lang 包中,提供了大量的静态方法来执行基本的数学运算,如指数、对数、平方根、三角函数等。

Math 类的源码:

public final class Math {// 私有构造函数private Math() {}// 常量 Epublic static final double E = 2.7182818284590452354;// 常量 PIpublic static final double PI = 3.14159265358979323846;...
}

Math 类的特点:

  • final 类:不能被继承
  • 私有构造函数:不能被实例化
  • 所有方法都是静态的:直接通过类名调用
  • 包含数学常量:Πe
5.2.2 Math 类常用方法

绝对值:

System.out.println(Math.abs(-5));      // 5
System.out.println(Math.abs(-3.14));   // 3.14
System.out.println(Math.abs(-0.0));    // 0.0

最大值和最小值:Math 类的最大值和最小值方法支持 int, long, float, double 类型。

System.out.println(Math.max(10, 20));  // 20
System.out.println(Math.min(10, 20));  // 10
System.out.println(Math.min(10.1111, 10.101010));  // 10.10101

取整运算:

double num = 3.7;// 向下取整(返回不大于参数的最大整数)
System.out.println(Math.floor(num));   // 3.0// 向上取整(返回不小于参数的最小整数)
System.out.println(Math.ceil(num));    // 4.0// 四舍五入
System.out.println(Math.round(num));   // 4 (返回long)
System.out.println(Math.round(3.2f));  // 3 (返回int)

幂运算:

// 幂运算:a的b次方
System.out.println(Math.pow(2, 3));    // 8.0
System.out.println(Math.pow(4, 0.5));  // 2.0 (平方根)// 指数运算:e的x次方
System.out.println(Math.exp(1));       // 2.718281828459045// e为底的对数
System.out.println(Math.log(Math.E));  // 1.0// 10为底的对数
System.out.println(Math.log10(100));   // 2.0

开方运算:

// 平方根
System.out.println(Math.sqrt(16));     // 4.0// 立方根
System.out.println(Math.cbrt(27));     // 3.0

三角函数:三角函数所有角度参数都使用弧度而不是度数。

// 角度转弧度
double angleInDegrees = 45;
double angleInRadians = Math.toRadians(angleInDegrees);// 三角函数
System.out.println(Math.sin(angleInRadians));    // 0.7071067811865475
System.out.println(Math.cos(angleInRadians));    // 0.7071067811865476
System.out.println(Math.tan(angleInRadians));    // 0.9999999999999999// 反三角函数
System.out.println(Math.asin(0.5));              // 0.5235987755982989 (弧度)
System.out.println(Math.acos(0.5));              // 1.0471975511965976 (弧度)
System.out.println(Math.atan(1));                // 0.7853981633974483 (弧度)// 弧度转角度
double resultInRadians = Math.asin(0.5);
double resultInDegrees = Math.toDegrees(resultInRadians);
System.out.println(resultInDegrees);             // 30.0

指数和对数函数:

// exp(x) = e^x
System.out.println(Math.exp(1));        // 2.718281828459045
System.out.println(Math.exp(2));        // 7.38905609893065// log(x) = ln(x) (自然对数)
System.out.println(Math.log(2.718281828459045)); // 1.0// log10(x) (常用对数)
System.out.println(Math.log10(100));    // 2.0// log1p(x) = ln(1+x) (对于小数值更精确)
System.out.println(Math.log1p(0.001));  // 0.0009995003330835332

随机数生成:

// 生成0.0到1.0之间的随机数(不包括1.0)
double random = Math.random();
System.out.println("随机数: " + random);// 生成指定范围的随机整数
// 生成1到10之间的随机整数
int randomInt = (int)(Math.random() * 10) + 1;
System.out.println("1-10之间的随机数: " + randomInt);// 生成min到max之间的随机整数
int min = 5, max = 15;
int randomInRange = (int)(Math.random() * (max - min + 1)) + min;

符号相关方法:

System.out.println(Math.signum(5));     // 1.0 (正数)
System.out.println(Math.signum(-5));    // -1.0 (负数)
System.out.println(Math.signum(0));     // 0.0

近似相等相关方法:

// 判断两个double值是否近似相等
double a = 0.1 + 0.2;
double b = 0.3;
System.out.println(Math.abs(a - b) < 1e-10); // true

混合运算相关方法:

// hypot(x, y) = √(x² + y²) (避免中间计算溢出)
System.out.println(Math.hypot(3, 4));   // 5.0// IEEEremainder(x, y) - IEEE 754规定的余数
System.out.println(Math.IEEEremainder(10, 3)); // 1.0

5.3 Character 类

5.3.1 Character 类介绍

Character 类是 Java 中 char 基本数据类型的包装类,位于 java.lang 包中。它提供了许多有用的静态方法来操作字符,是处理字符数据的重要工具。

public final
class Character implements java.io.Serializable, Comparable<Character> {// 最小进制public static final int MIN_RADIX = 2;// 最大进制public static final int MAX_RADIX = 36;// 最小char值public static final char MIN_VALUE = '\u0000';// 最大char值public static final char MAX_VALUE = '\uFFFF';...

Character 类的特点:

  • final 类:不能被继承
  • 包装 char 类型:将基本类型 char 包装为对象
  • 提供丰富的字符操作方法
  • 实现 ComparableSerializable 接口

Character 类创建:

// 方式1:使用构造函数(已过时,不推荐)
Character ch1 = new Character('A');// 方式2:使用valueOf()方法(推荐)
Character ch2 = Character.valueOf('B');// 方式3:自动装箱(最常用)
Character ch3 = 'C'; // 自动调用valueOf()// 拆箱
char primitiveChar = ch3; // 自动调用charValue()

Character 类常用常量:

System.out.println(Character.MIN_VALUE);  // '\u0000' (最小char值)
System.out.println(Character.MAX_VALUE);  // '\uffff' (最大char值)
System.out.println(Character.MIN_RADIX);  // 2 (最小进制)
System.out.println(Character.MAX_RADIX);  // 36 (最大进制)
5.3.2 Character 类判断方法

基本类型判断:

char ch = 'A';System.out.println(Character.isLetter(ch));      // true - 是否为字母
System.out.println(Character.isDigit(ch));       // false - 是否为数字
System.out.println(Character.isLetterOrDigit(ch)); // true - 是否为字母或数字
System.out.println(Character.isWhitespace(ch));  // false - 是否为空白字符
System.out.println(Character.isUpperCase(ch));   // true - 是否为大写字母
System.out.println(Character.isLowerCase(ch));   // false - 是否为小写字母
System.out.println(Character.isISOControl(ch));  // false - 是否为ISO控制字符

Unicode 相关判断:

char ch = '€'; // 欧元符号System.out.println(Character.isUnicodeIdentifierStart(ch)); // true
System.out.println(Character.isUnicodeIdentifierPart(ch));  // true
System.out.println(Character.isDefined(ch));     // true - 是否为定义的字符
System.out.println(Character.isValidCodePoint(ch)); // true - 是否为有效码点
5.3.3 Character 类字符转换方法

大小写转换:

char ch = 'a';System.out.println(Character.toUpperCase(ch));   // 'A'
System.out.println(Character.toLowerCase(ch));   // 'a'
System.out.println(Character.toTitleCase('hello')); // 'H' (首字母大写)

进制转换:

// 数字字符转数值
System.out.println(Character.digit('9', 10));    // 9
System.out.println(Character.digit('A', 16));    // 10 (十六进制)
System.out.println(Character.digit('Z', 36));    // 35 (三十六进制)// 数值转字符
System.out.println(Character.forDigit(9, 10));   // '9'
System.out.println(Character.forDigit(10, 16));  // 'a'
5.3.4 Character 类应用示例

验证字符串是否为纯字母:

public static boolean isAlphabetic(String str) {if (str == null || str.isEmpty()) {return false;}for (char c : str.toCharArray()) {if (!Character.isLetter(c)) {return false;}}return true;
}// 测试
System.out.println(isAlphabetic("Hello"));    // true
System.out.println(isAlphabetic("Hello123")); // false

统计字符串中各类字符数量:

public static void countCharacters(String str) {int letters = 0, digits = 0, spaces = 0, others = 0;for (char c : str.toCharArray()) {if (Character.isLetter(c)) {letters++;} else if (Character.isDigit(c)) {digits++;} else if (Character.isWhitespace(c)) {spaces++;} else {others++;}}System.out.println("字母: " + letters);System.out.println("数字: " + digits);System.out.println("空格: " + spaces);System.out.println("其他: " + others);
}// 测试
countCharacters("Hello 123 World!");
// 输出:
// 字母: 10
// 数字: 3
// 空格: 2
// 其他: 1

字符串首字母大写:

public static String capitalize(String str) {if (str == null || str.isEmpty()) {return str;}char firstChar = str.charAt(0);if (Character.isLowerCase(firstChar)) {return Character.toUpperCase(first

5.4 String 类

5.4.1 String 类介绍

String 类是 Java 中最常用和最重要的类之一,用于表示和操作字符串。它位于 java.lang 包中,因此无需导入即可使用。

String 类源码:

public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {...
}

String 类的特点:

  • 不可变性(Immutable):String 对象一旦创建,其内容就不能被修改
  • final 类:不能被继承
  • 实现接口:Serializable, Comparable<String>, CharSequence
  • 字符串常量池:JVM 维护的特殊内存区域,用于存储字符串字面量

String 类的创建方式:

// 创建方式1:字符串字面量,推荐使用的方式
String str1 = "Hello World";
String str2 = "Hello World"; // 会重用字符串常量池中的对象System.out.println(str1 == str2); // true(引用相同对象)// 创建方式2:使用 new 关键字
String str3 = new String("Hello World");
String str4 = new String("Hello World");System.out.println(str3 == str4);     // false(不同对象)
System.out.println(str3.equals(str4)); // true(内容相同)// 其他创建方式
// 从字符数组创建
char[] chars = {'H', 'e', 'l', 'l', 'o'};
String str5 = new String(chars);// 从字节数组创建
byte[] bytes = {72, 101, 108, 108, 111};
String str6 = new String(bytes);// 使用 StringBuilder 或 StringBuffer
String str7 = new StringBuilder().append("Hello").append(" ").append("World").toString();
5.4.2 String 类常用方法

获取 String 类的信息:

String str = "Hello World";// 获取长度
System.out.println(str.length()); // 11// 获取指定位置的字符
System.out.println(str.charAt(0)); // 'H'// 获取字符数组
char[] charArray = str.toCharArray();// 获取字节数组
byte[] byteArray = str.getBytes();// 获取长度
System.out.println(str.length()); // 11// 获取指定位置的字符
System.out.println(str.charAt(0)); // 'H'// 获取字符数组
char[] charArray = str.toCharArray();// 获取字节数组
byte[] byteArray = str.getBytes();java
String str = "Hello World";// 获取长度
System.out.println(str.length()); // 11// 获取指定位置的字符
System.out.println(str.charAt(0)); // 'H'// 获取字符数组
char[] charArray = str.toCharArray();// 获取字节数组
byte[] byteArray = str.getBytes();String str = "Hello World";// 获取长度
System.out.println(str.length()); // 11// 获取指定位置的字符
System.out.println(str.charAt(0)); // 'H'// 获取字符数组
char[] charArray = str.toCharArray();// 获取字节数组
byte[] byteArray = str.getBytes();

String 类比较操作:

String str1 = "hello";
String str2 = "HELLO";// 相等比较(区分大小写)
System.out.println(str1.equals(str2)); // false// 相等比较(不区分大小写)
System.out.println(str1.equalsIgnoreCase(str2)); // true// 比较大小(字典序)
System.out.println(str1.compareTo(str2)); // 正数(str1 > str2)
System.out.println(str1.compareToIgnoreCase(str2)); // 0(相等)// 检查前缀和后缀
System.out.println(str1.startsWith("he")); // true
System.out.println(str1.endsWith("lo")); // true

String 类查找操作:

String str = "Hello World";// 查找字符或子串位置
System.out.println(str.indexOf('o')); // 4(第一次出现)
System.out.println(str.lastIndexOf('o')); // 7(最后一次出现)
System.out.println(str.indexOf("World")); // 6
System.out.println(str.indexOf("Java")); // -1(未找到)// 检查是否包含
System.out.println(str.contains("World")); // true

String 类的字符串操作:

String str = "  Hello World  ";// 去除首尾空白
System.out.println(str.trim()); // "Hello World"// 大小写转换
System.out.println(str.toLowerCase()); // "  hello world  "
System.out.println(str.toUpperCase()); // "  HELLO WORLD  "// 替换操作
System.out.println(str.replace('l', 'L')); // "  HeLLo WorLd  "
System.out.println(str.replaceAll(" ", "_")); // "__Hello_World__"
System.out.println(str.replaceFirst(" ", "_")); // "_ Hello World  "// 截取子串
System.out.println(str.substring(6)); // "World  "
System.out.println(str.substring(6, 11)); // "World"

String 类字符串的分割和连接:

// 分割字符串
String sentence = "apple,banana,orange";
String[] fruits = sentence.split(",");
// fruits = {"apple", "banana", "orange"}// 使用正则表达式分割
String text = "one1two2three";
String[] parts = text.split("\\d");
// parts = {"one", "two", "three"}// 连接字符串(Java 8+)
String joined = String.join("-", "apple", "banana", "orange");
// joined = "apple-banana-orange"// 使用StringJoiner(更灵活)
StringJoiner joiner = new StringJoiner(",", "[", "]");
joiner.add("apple").add("banana").add("orange");
// joiner.toString() = "[apple,banana,orange]"
5.4.3 String 类的不可变性

一旦一个 String 对象被创建,它的值就不能被修改。任何看似“修改”字符串的操作,实际上都会创建一个新的 String 对象。

String s = "Hello";
s = s + " World";  // 看似修改,其实是创建新对象
System.out.println(s); // 输出:Hello World
  • 最初的 "Hello" 对象仍然存在,没有被修改。
  • s + " World" 创建了一个新对象 "Hello World"
  • 变量 s 现在指向这个新对象。

Java 设计者将 String 设计为不可变,是出于以下几个关键考虑:

  • 安全性:字符串常用于数据库连接 URL、文件路径、用户名/密码、网络地址。如果 String 可变,攻击者可能在你不知情的情况下修改这些关键信息,不可变性确保了敏感信息不会被篡改。
  • 字符串常量池优化:Java 使用 字符串常量池(在堆中的 String Pool)来缓存字符串字面量,避免重复创建相同内容的字符串。如果 String 可变,修改一个引用会影响所有共享该字符串的变量,导致严重 bug。
  • 线程安全:不可变对象天生就是线程安全的,因为它的状态不能改变,多个线程可以同时访问同一个 String 对象而无需同步,不可变性避免了并发编程中的竞争条件。
  • 哈希码缓存String 内部缓存了 hashCode,因为字符串内容不变,所以哈希码也永远不会变。
  • 类加载机制依赖:Java 的类加载器使用字符串作为类名,如果字符串可变,可能导致类加载错误或安全漏洞。
5.4.3 String 类不可变的实现原理

(1)使用 final 修饰类

使用 final 修饰的类不能被继承,可以防止子类破坏不可变性。

public final class String {...
}

(2)final 字符数组

存储字符串内容的字符数组是 final 修饰的,引用不能改变,虽然数组内容理论上可变,但 Java 通过不提供修改数组内容的方法来保证安全。

private final char value[];

(3)私有构造器与深拷贝

String 的构造器会对传入的字符数组进行拷贝,而不是直接引用外部数组。防止外部修改数组影响字符串内容。

public String(char[] value) {this.value = Arrays.copyOf(value, value.length);
}

(4)所有修改操作都返回新对象

String 类不可变性的缺点:频繁修改字符串效率低,针对这种情况,Java 也提供了另外两种可变字符串类:

  • StringBuilder:单线程频繁拼接,非线程安全,性能高
  • StringBuffer:多线程频繁拼接,线程安全(方法加 synchronized 修饰)
5.4.4 字符串常量池

字符串常量池是 JVM 中一块特殊的存储区域,用于缓存字符串字面量(String literals),目的是避免重复创建相同内容的字符串对象,从而节省内存、提高性能。

字符串常量池本质上是一个哈希表(HashTable),存储字符串内容到对象引用的映射。从 JDK 7 开始,字符串常量池从方法区(永久代,PermGen)移到了堆内存(Heap)中。

Java 中创建 String 对象主要有两种方式:

  • 字面量方式创建,这种方式是直接赋值给变量
  • new 关键字方式创建,这种方式一定会创建新对象

字面量方式创建 String 对象时,JVM 会先检查常量池中是否已有该字符串,如果有,直接返回引用;如果没有,创建新对象并放入常量池。

如下示例:s1 == s2 为 true,指向常量池中的同一个对象

String s1 = "Hello";
String s2 = "Hello";

new 关键字方式创建 String 对象时,new 一定会在堆中创建新的 String 对象,但创建的这个字面量如果在常量池中没有的情况下,该字面量仍会进入常量池。

如下示例:

String s3 = new String("Hello");
String s4 = new String("Hello");
  • s3 == s4 为 false(两个不同的对象)
  • s3.equals(s4) 为 true(内容相同)

String 类提供了一个 intern() 方法,用于手动将字符串放入常量池。intern() 方法的作用:

  • 如果常量池中已有相同内容的字符串,返回其引用;
  • 如果没有,将该字符串加入常量池,并返回引用。

intern() 方法语法:

public native String intern();

intern() 方法示例:

String s1 = new String("Hello");  // 在堆中创建新对象
String s2 = s1.intern();          // 将 "Hello" 入池,返回池中引用String s3 = "Hello";              // 字面量,从池中获取System.out.println(s1 == s2);     // false(s1 是 new 出来的)
System.out.println(s2 == s3);     // true(s2 和 s3 都指向常量池中的对象)
http://www.xdnf.cn/news/1316557.html

相关文章:

  • C语言---第一个C语言程序
  • FreeRTOS源码分析八:timer管理(一)
  • 基于遗传编程的自动程序生成
  • Java语法进阶之常用类
  • SQL Server 2019安装教程(超详细图文)
  • PERCEIVER IO:一种用于结构化输入与输出的通用架构
  • iSCSI服务配置全指南(含服务器与客户端)
  • 快速掌握Hardhat与Solidity智能合约开发
  • SCAI采用公平发射机制成功登陆LetsBonk,60%代币供应量已锁仓
  • Houdini 粒子学习笔记
  • C# Newtonsoft.Json 反序列化子类数据丢失问题
  • 音频分类标注工具
  • 矿物分类案列 (一)六种方法对数据的填充
  • Java零基础笔记20(Java高级技术:单元测试、反射、注解、动态代理)
  • RAC环境redo在各节点本地导致数据库故障恢复---惜分飞
  • 勾股数-洛谷B3845 [GESP样题 二级]
  • 平行双目视觉-动手学计算机视觉18
  • Linux应用软件编程---多任务(线程)(线程创建、消亡、回收、属性、与进程的区别、线程间通信、函数指针)
  • (一)React企业级后台(Axios/localstorage封装/动态侧边栏)
  • Android 对话框 - 基础对话框补充(不同的上下文创建 AlertDialog、AlertDialog 的三个按钮)
  • WPFC#超市管理系统(6)订单详情、顾客注册、商品销售排行查询和库存提示、LiveChat报表
  • C#WPF实战出真汁13--【营业查询】
  • [辩论] TDD(测试驱动开发)
  • ZKmall开源商城的移动商城搭建:Uni-app+Vue3 实现多端购物体验
  • Collections.synchronizedList是如何将List变为线程安全的
  • Trae 辅助下的 uni-app 跨端小程序工程化开发实践分享
  • 李宏毅NLP-11-语音合成
  • 在 Element UI 的 el-table 中实现某行标红并显示删除线
  • 【PHP】Hyperf:接入 Nacos
  • Centos中内存CPU硬盘的查询