乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • 学习路径
  • 第1章 Java概述与环境搭建

    • Java概述与环境搭建
    • Java语言概述
    • 解释型语言与编译型语言对比
    • JDK安装与配置
    • JDK、JRE、JVM 详解
    • HelloWorld程序详解
    • IDE 介绍
  • 第2章 标识符与基本数据类型

    • 章节导读
    • 变量概述
    • 常量概述
    • 基本类型与包装类
    • 字节型 byte
    • 短整型 short
    • 整型 int
    • 长整型 long
    • 单精度浮点型 float
    • 双精度浮点型 double
    • 字符型 char
    • 布尔型 boolean
    • 类型转换
  • 第3章 运算符与表达式

    • 章节导读
    • 算术运算符
    • 赋值运算符
    • 关系运算符
    • 逻辑运算符
    • 位运算符
    • 条件运算符
    • 运算符优先级
    • 表达式
  • 第4章 流程控制

    • 章节导读
    • 常见的程序运行流程
    • if-else 选择结构
    • switch 多分支选择
    • while 循环
    • do-while 循环
    • for 循环
    • break 与 continue
  • 第5章 数组

    • 章节导读
    • 一维数组
    • 多维数组
    • Arrays 工具类
  • 第6章 类与对象

    • 章节导读
    • 类与对象
    • 方法定义与调用
    • 构造方法
    • 封装
    • 访问修饰符
    • package 与 import
    • static 关键字
    • this 关键字
    • 参数传递 详解
    • 枚举
    • 成员内部类
    • 局部内部类
    • 静态内部类
    • 匿名内部类
  • 第7章 接口与继承

    • 章节导读
    • 继承
    • super 关键字
    • final 关键字
    • 多态
    • 向上转型与向下转型
    • 抽象类
    • 接口
    • 抽象类与接口对比
  • 第8章 注解

    • 章节导读
    • 注解基础
    • 元注解详解
    • 自定义注解
  • 第9章 常用类

    • 章节导读:Java 常用类
    • Object 类:万类之祖
    • 包装类:基本类型的对象化
    • String:不可变的字符串
    • StringBuffer:线程安全的可变字符串
    • StringBuilder:可变的字符串构建器
    • Math:数学运算工具类
    • Random:伪随机数生成器
    • 大数值运算 详解
    • 日期时间API 详解
  • 第10章 异常机制

    • 章节导读
    • 异常体系与分类
    • try-catch-finally
    • try-with-resources
    • throws 与 throw
    • 自定义异常
  • 第11章 泛型

    • 章节导读
    • 泛型基础
    • 通配符与PECS原则
    • 类型擦除
  • 第12章 集合框架

    • 章节导读
    • 集合框架概述
    • ArrayList
    • LinkedList
    • HashMap 详解
    • LinkedHashMap 详解
    • TreeMap 详解
    • HashSet
    • TreeSet 详解
    • TreeSet 与 Comparable
    • Collections 工具类详解
  • 第13章 IO流

    • 章节导读
    • IO流概述
    • 字节流
    • 字符流
    • 缓冲流
    • 转换流 详解
    • 序列化 详解
    • NIO与Files 详解
    • NIO与Files工具类
  • 第14章 多线程与并发

    • 第十六章 多线程与并发 —— 章节导读
    • 线程基础详解
    • synchronized 详解
    • Lock 与显式锁详解
    • volatile 详解
    • wait 与 notify 详解
    • ThreadLocal详解
    • 原子类详解
    • 并发工具类详解
    • 线程池详解
  • 第15章 反射

    • 章节导读
    • 反射概述与 Class 对象
    • Constructor 与对象创建
    • Field与Method详解
    • 反射应用详解
  • 第16章 JDK8新特性

    • 章节导读
    • Lambda 表达式
    • Stream API 基础
    • Stream API 高级详解
    • Optional 详解
    • 新日期时间API详解
  • 第17章 JDK9-11新特性

    • 章节导读
    • 模块化系统 — Project Jigsaw(JDK 9)
    • var 局部变量类型推断(JDK 10)
    • 集合工厂方法与增强(JDK 9 / 10 / 11)
    • 接口增强:private 方法(JDK 9)
    • Stream API 增强(JDK 9)
    • Optional 增强(JDK 9 / 10 / 11)
    • String 新增方法(JDK 11)
    • HTTP Client 与 Files 增强(JDK 11)
    • 直接运行 Java 源文件 — JEP 330(JDK 11)
  • 第18章 JDK12-17新特性

    • 章节导读
    • Switch 表达式(JDK 12 预览 / JDK 14 正式)
    • 文本块 Text Blocks(JDK 13 预览 / JDK 15 正式)
    • Records 记录类(JDK 14 预览 / JDK 16 正式)
    • 密封类 Sealed Classes(JDK 15 预览 / JDK 17 正式)
    • instanceof 模式匹配(JDK 14 预览 / JDK 16 正式)
    • Switch 模式匹配 — Pattern Matching for switch(JDK 17 预览 / JDK 21 正式)
    • Helpful NPE 与 String 增强(JDK 12 / JDK 14 / JDK 15)
    • Stream 增强(JDK 12 / JDK 16)
    • 日期时间增强 — Day Period 支持(JDK 16)
  • 第19章 JDK18-21新特性

    • 章节导读
    • 虚拟线程(JDK 19 预览 / JDK 20 第二预览 / JDK 21 正式)
    • 序列集合(JDK 21 正式)
    • Switch 模式匹配(JDK 17 预览 / JDK 18 第二预览 / JDK 20 第四预览 / JDK 21 正式)
    • Record 模式匹配(JDK 19 预览 / JDK 20 第二预览 / JDK 21 正式)
    • 未命名模式与变量(JDK 21 预览 / JDK 22 正式)
  • 第20章 JDK 22-25 新特性

    • 章节导读
    • 字符串模板(JDK 22 预览 / JDK 23 第二预览 / JDK 24 第三预览)
    • Stream Gatherers(JDK 22 预览 / JDK 24 第二预览)
    • 隐式声明类与实例方法(JDK 23 预览 / JDK 24 第二预览)
    • 原始类型模式匹配(JDK 24 预览)
  • 附录

    • Java 核心知识点
    • Java SE 专业术语
    • Java特性索引(JDK 8 → 25)

字符型 char

本章定位:char是Java的16位Unicode字符类型,基于UTF-16编码,取值范围0~65535(\u0000~\uFFFF)。在飞翔科技的中文网站系统中,从"飞""翔""中""文""网"到"F""E""I""X""I""A""N""G",每一个字符都是char。小崔曾因不了解增补字符(Supplementary Characters)导致emoji被截断,白歌给他补了一课Unicode。


定义与语法

属性说明
关键字char(字符型)
位数16 bits(2字节)
编码UTF-16(Unicode字符集的16位编码单元)
取值范围\u0000 ~ \uFFFF(即 0 ~ 65535,无符号)
默认值\u0000(空字符,不是空格)
包装类java.lang.Character
字面量单引号括起:'A'、'飞'、'\u0041'、'\n'、65(int字面量)

基本声明

char productGrade = 'A';       // 商品等级A
char fuelType = 'X';           // 油品类型X=汽油
char salaryGrade = 'B';        // 工资等级
char scenicLevel = 'A';        // 景区A级
char houseType = '三';         // 三室一厅
char seatRow = 'F';            // F排座位

深度原理:char与Unicode

Java char 的 Unicode 本质

关键认知:

  • Java中char是16位无符号整数,本质上等同于UTF-16编码的一个代码单元(code unit)
  • 基本多文种平面(BMP)中的字符(U+0000~U+FFFF)用一个char表示
  • 增补字符(U+10000~U+10FFFF,如大部分emoji)需要两个char(代理对)
  • 这意味着:一个char不一定等于一个完整字符!

char的多种表示法

表示法格式示例说明
直接字符'A'char c = 'A';ASCII字符
中文字符'飞'char c = '飞';BMP中的CJK字符
Unicode转义'\uXXXX'char c = '\u98DE';4位十六进制
八进制转义'\0'~'\377'char c = '\101';八进制(A的ASCII码=101₈)
特殊转义'\n' '\t' '\\'char tab = '\t';控制字符
整数赋值65char c = 65;字面量在char范围内

完整代码示例

示例一:飞翔中文网——中文与Unicode转义

/**
 * 飞翔科技 - char 类型演示
 * 场景:飞翔中文网的中文字符处理
 */
public class CharChineseDemo {
    public static void main(String[] args) {
        // 中文字符数组
        char[] chineseName = {'飞', '翔', '中', '文', '网'};
        char[] englishName = {'F', 'E', 'I', 'X', 'I', 'A', 'N', 'G', '.', 'N', 'E', 'T'};
        char[] year = {'2', '0', '1', '8'};  // 成立年份
        
        // Unicode 转义形式
        char feiChar = '\u98DE';  // 飞的Unicode编码
        char xiangChar = '\u7FD4'; // 翔的Unicode编码
        
        System.out.print("中文名称:");
        for (char c : chineseName) {
            System.out.print(c);
        }
        System.out.println();
        
        System.out.print("英文名称:");
        for (char c : englishName) {
            System.out.print(c);
        }
        System.out.println();
        
        System.out.print("成立年份:");
        for (char c : year) {
            System.out.print(c);
        }
        System.out.println();
        
        // Unicode验证
        System.out.println("\n【Unicode编码验证】");
        System.out.println("\\u98DE = " + feiChar);
        System.out.println("\\u7FD4 = " + xiangChar);
        System.out.println("'飞' == \\u98DE ? " + ('飞' == '\u98DE'));
        
        // char的本质是整数
        System.out.println("\n【char的整数本质】");
        System.out.println("'A'的数值:" + (int) 'A');           // 65
        System.out.println("'飞'的数值:" + (int) '飞');          // 39134
        System.out.println("'翔'的十六进制:" + Integer.toHexString('翔')); // 7fd4
    }
}
运行输出:
中文名称:飞翔中文网
英文名称:FEIXIANG.NET
成立年份:2018

【Unicode编码验证】
\u98DE = 飞
\u7FD4 = 翔
'飞' == \u98DE ? true

【char的整数本质】
'A'的数值:65
'飞'的数值:39134
'翔'的十六进制:7fd4

示例二:飞翔教育——成绩等级判定

/**
 * 飞翔科技 - char 等级判定演示
 * 场景:飞翔大学的成绩等级系统
 */
public class CharGradeDemo {
    public static void main(String[] args) {
        // 成绩等级
        char scoreRank = 'A';      // 成绩A等
        char gradeLevel = '甲';     // 班级等级
        char bloodType = 'O';      // 血型O
        
        System.out.println("【飞翔大学 - 成绩单】");
        System.out.println("成绩等级:" + scoreRank + "等");
        System.out.println("班级等级:" + gradeLevel + "班");
        System.out.println("血型:" + bloodType + "型");
        
        // char的比较(本质是整数比较)
        System.out.println("\n【等级比较】");
        char rank1 = 'A';
        char rank2 = 'B';
        char rank3 = 'C';
        System.out.println("'A' < 'B' ? " + (rank1 < rank2));  // true(65 < 66)
        System.out.println("'B' < 'C' ? " + (rank2 < rank3));  // true
        
        // char参与算术运算
        System.out.println("\n【char运算】");
        char base = 'A';
        char next = (char) (base + 1);
        System.out.println("'A' + 1 = " + next);  // B
        
        // 判断字符类型
        System.out.println("\n【字符类型判断】");
        System.out.println("'A'是字母?" + Character.isLetter('A'));
        System.out.println("'5'是数字?" + Character.isDigit('5'));
        System.out.println("'飞'是字母?" + Character.isLetter('飞'));  // true!(CJK字符算字母)
        System.out.println("' '是空白?" + Character.isWhitespace(' '));
        System.out.println("'\\n'是空白?" + Character.isWhitespace('\n'));
    }
}
运行输出:
【飞翔大学 - 成绩单】
成绩等级:A等
班级等级:甲班
血型:O型

【等级比较】
'A' < 'B' ? true
'B' < 'C' ? true

【char运算】
'A' + 1 = B

【字符类型判断】
'A'是字母?true
'5'是数字?true
'飞'是字母?true
' '是空白?true
'\n'是空白?true

易错场景

反例一:char的空字符 vs 空格

// ❌ 易混淆:默认值 \u0000 不是空格 ' '
char ch;  // 成员变量,默认值为 \u0000
// System.out.println(ch == ' ');     // false!\u0000 不是空格
// System.out.println(ch == '\u0000'); // true

// \u0000 是空字符(null character),打印时不可见
// ' ' 是空格,ASCII码32

反例二:char不能表示所有Unicode——emoji陷阱

// ❌ 危险:emoji长度超过1个char
// char emoji = '😀';  // 编译错误!emoji(U+1F600)超出BMP范围

// ✅ 正确:emoji需要2个char(代理对)
String emoji = "😀";
System.out.println("emoji长度:" + emoji.length());      // 2(两个char!)
System.out.println("emoji码点数:" + emoji.codePointCount(0, emoji.length()));  // 1

// Unicode 代理对范围
// 高代理:\uD800 ~ \uDBFF
// 低代理:\uDC00 ~ \uDFFF

反例三:char运算自动提升为int

// ❌ 易错:char + char 结果是 int
char a = 'A';
char b = 'B';
int sum = a + b;      // 131(65 + 66)
// char result = a + b;  // 编译错误!需要强转
char result = (char) (a + b);  // 强制转换(不推荐)

// char 会自动提升:char → int → long → float → double

反例四:'A' 和 "A" 的混淆

// ❌ 类型错误:单引号是char,双引号是String
char ch = "A";   // 编译错误!String不能赋给char
char ch2 = 'A';  // ✅ 正确

// char 是基本类型,String 是引用类型
// char 用 == 比较值,String 用 equals() 比较内容

常见转义字符表

转义序列含义Unicode数值
'\n'换行\u000A10
'\r'回车\u000D13
'\t'制表符Tab\u00099
'\\'反斜杠\u005C92
'\''单引号\u002739
'\"'双引号\u002234
'\0'空字符\u00000

面试考点

Q1:Java的char为什么是2字节?

Java设计于1990年代中期,当时Unicode 1.0只有16位编码空间(U+0000~U+FFFF),因此Java将char设计为16位无符号整数,使用UTF-16编码。后来Unicode扩展到U+10FFFF(需要21位),超出BMP的字符需要用两个char(代理对)表示。这一设计决策成为Java的"历史包袱"——char不能完整表示所有Unicode字符。

Q2:char c = '中'; 在内存中存的是什么?

存储的是'中'的Unicode码点值20013(即十六进制\u4E2D),在16位内存中为01001110 00101101。char本质上是一个16位无符号整数(0~65535),可以参与算术运算和比较。

Q3:String.length()和String.codePointCount()有什么区别?

length()返回char单元的数量(UTF-16 code units),对于增补字符(如emoji),一个码点占2个char单元,所以length()可能大于实际字符数。codePointCount()返回Unicode码点的数量(即"真正"的字符数)。例如:"😀".length()=2,"😀".codePointCount(0,2)=1。

Q4:char类型能存中文吗?能存emoji吗?

能存BMP内的中文(U+4E00~U+9FFF,即常用汉字),因为它们的Unicode码点≤U+FFFF,一个char足够。不能直接存emoji(大部分emoji在U+1F300~U+1F9FF),因为它们的码点>U+FFFF,需要两个char(代理对),单个char变量无法表示。要完整处理Unicode,应使用String和codePointAt()等API。

上一页
双精度浮点型 double
下一页
布尔型 boolean