以下是个人对java中字符和字符串的见解,如有疏漏之处,还请不吝赐教。

下面通过一个简单的程序来说明字符和字符串在Java中的旅程。

以字符 ' 中 '为例, 它的GBK编码是2个字节:0xd6d0, UTF-16 编码是2个字节:0x4e26,UTF-8编码是3个字节: 0xe4b8ab

public class CharacterInJava {
public static void main(String[] args) {
char c = '中';
     String s = "我是一个中国人";
System.out.println(c + "" + c1 + s);
    }
}

当编辑完成CharacterInJava.java,您会选择保存文件。这时,CharacterInJava.java会保存在磁盘上。在保存的过程中,文本编辑器会帮我们将这个文件中的字符编码,我们可以指定编码,比如选择GBK编码时,字符 '中'会编码为 0xd6d0,如果是UTF-8的话,则会编码为 0xe4b8ab。下面是两种不同的编码保存文件的16进制表示:

GBK:                                                                                    UTF-8:

    

然后,我们接着要做的是编绎CharacterInJava.java, 在命令行输入javac -encoding GBK -d . CharacterInJava.java,即可编绎文件。这时可能会发生如下的错误:

错误的原因是,javac 通过-encoding 参数知道 CharacterInJava.java 是GBK编码的,因此使用GBK对源码进行解读。但其实,源码是用UTF-8编码的,因此发生了不可映射字符错误。通过更改为-encoding为UTF-8,即可编绎成功。也就是说,源文件是什么编码,程序员应该要清楚。

编绎完成后,生成了一个类文件:CharacterInJava.class,对文件进行反编绎:

Classfile /E:/JavaTutorial/IO/CharacterInJava.class
Last modified 2019年2月19日; size 914 bytes
MD5 checksum 5c174b19c95e5b26e64051fb06137319
Compiled from "CharacterInJava.java"
public class CharacterInJava
minor version: 0
major version: 53
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #6 // CharacterInJava
super_class: #7 // java/lang/Object
interfaces: 0, fields: 0, methods: 2, attributes: 3
Constant pool:
#1 = Methodref #7.#16 // java/lang/Object."<init>":()V
#2 = String #17 // 我是一个中国人
#3 = Fieldref #18.#19 // java/lang/System.out:Ljava/io/PrintStream;
#4 = InvokeDynamic #0:#23 // #0:makeConcatWithConstants:(CLjava/lang/String;)Ljava/lang/String;
#5 = Methodref #24.#25 // java/io/PrintStream.println:(Ljava/lang/String;)V
#6 = Class #26 // CharacterInJava
#7 = Class #27 // java/lang/Object
#8 = Utf8 <init>
#9 = Utf8 ()V
#10 = Utf8 Code
#11 = Utf8 LineNumberTable
#12 = Utf8 main
#13 = Utf8 ([Ljava/lang/String;)V
#14 = Utf8 SourceFile
#15 = Utf8 CharacterInJava.java
#16 = NameAndType #8:#9 // "<init>":()V
#17 = Utf8 我是一个中国人
#18 = Class #28 // java/lang/System
#19 = NameAndType #29:#30 // out:Ljava/io/PrintStream;
#20 = Utf8 BootstrapMethods
#21 = MethodHandle 6:#31 // REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
#22 = String #32 // \u0001\u0001
#23 = NameAndType #33:#34 // makeConcatWithConstants:(CLjava/lang/String;)Ljava/lang/String;
#24 = Class #35 // java/io/PrintStream
#25 = NameAndType #36:#37 // println:(Ljava/lang/String;)V
#26 = Utf8 CharacterInJava
#27 = Utf8 java/lang/Object
#28 = Utf8 java/lang/System
#29 = Utf8 out
#30 = Utf8 Ljava/io/PrintStream;
#31 = Methodref #38.#39 // java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
#32 = Utf8 \u0001\u0001
#33 = Utf8 makeConcatWithConstants
#34 = Utf8 (CLjava/lang/String;)Ljava/lang/String;
#35 = Utf8 java/io/PrintStream
#36 = Utf8 println
#37 = Utf8 (Ljava/lang/String;)V
#38 = Class #40 // java/lang/invoke/StringConcatFactory
#39 = NameAndType #33:#44 // makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
#40 = Utf8 java/lang/invoke/StringConcatFactory
#41 = Class #46 // java/lang/invoke/MethodHandles$Lookup
#42 = Utf8 Lookup
#43 = Utf8 InnerClasses
#44 = Utf8 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
#45 = Class #47 // java/lang/invoke/MethodHandles
#46 = Utf8 java/lang/invoke/MethodHandles$Lookup
#47 = Utf8 java/lang/invoke/MethodHandles
{
public CharacterInJava();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0 public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=3, args_size=1
0: sipush 20013
3: istore_1
4: ldc #2 // String 我是一个中国人
6: astore_2
7: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
10: iload_1
11: aload_2
12: invokedynamic #4, 0 // InvokeDynamic #0:makeConcatWithConstants:(CLjava/lang/String;)Ljava/lang/String;
17: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
20: return
LineNumberTable:
line 3: 0
line 4: 4
line 6: 7
line 8: 20
}

从常量池中看到,字符串是用UTF-8编码的。从main函数中第一行sipush 20013指令看到,字符 ' 中 '是用UTF-16编码的。

也就是说,class文件的字符按照UTF-16编码,大多数的字符都是用一个代码单元就可以表示的。字符串按照UTF-8编码。下面直接在

class文件中找出这些对应的编码。0xe6 88 91 对应于 我,0x4e2d 对应于 中

接下来是运行class文件:

  查阅printfln的API知道,字符和字符串的输出,先根据平台默认的字符集将输出的字符或编码成一个或多个字节,然后将这些字节输出到终端。

整个过程大致如上,知道字符和字符串的编码,应该不易出现乱码。

字符和字符串在Java中的旅程的更多相关文章

  1. 字符编码介绍及java中的应用

    字符编码,就是对日常的控制符号.文字和常用符号的二进制表示.为了准确的表示如何编号,怎么生产八位字节流,Unicode Technical Report (UTR) #17提出现代编码模型的5个层次: ...

  2. 对字符串进行简单的字符数字统计 探索java中的List功能

    题目: 统计一个字符串中数字和字符串的个数,并分别进行排列,要求 1.数字,字符串可以从键盘获取. 2.储存在list 3.统计数字个数,字符串个数 4.把数字和字符串按从小到大的顺序输出 5.不能使 ...

  3. 对上次“对字符串进行简单的字符数字统计 探索java中的List功能 ”程序,面向对象的改进

    之前的随笔中的程序在思考后发现,运用了太多的static 函数,没有将面向对象的思想融入,于是做出了一下修改: import java.util.ArrayList; import java.util ...

  4. 字符串分割--Java中String.split()用法

    转载自:http://blog.163.com/zs_note/blog/static/199386112201110804233558/ 在java.lang包中有String.split()方法, ...

  5. json数据格式字符串在java中的转移

    说明:项目中遇到请求的json数据字符串,打印出来没有问题,但是想加入到代码中,就需要进行转移 原数据为(用src代替)(没有写完): {"adjust_fee":"0. ...

  6. java中的字符串简介,字符串的优化以及如何高效率的使用字符串

    简介 String最为java中最重要的数据类型.字符串是软件开发中最重要的对象之一,通常,字符串对象在内存中总是占据着最大的空间块.所以,高效处理字符串,将提高系统的整个性能. 在java语言中,S ...

  7. java中如何忽略字符串中的转义字符--转载

    原文地址:http://my.oschina.net/u/1010578/blog/366252 起因     这几天工作上需要跟另一个同事联调rest接口,我这边是java他是php,返回报文是js ...

  8. 理解Java中的字符串类型

    1.Java内置对字符串的支持: 所谓的内置支持,即不用像C语言通过char指针实现字符串类型,并且Java的字符串编码是符合Unicode编码标准,这也意味着不用像C++那样通过使用string和w ...

  9. java中字符串编码转换

    Java 正确的做字符串编码转换 字符串的内部表示? 字符串在java中统一用unicode表示( 即utf-16 LE) , 对于 String s = "你好哦!"; 如果源码 ...

随机推荐

  1. linux CentOS 安装 nginx+tomcat+java+mysql运行环境

    本文介绍了CentOS7 64 Java,Tomcat,MySQL,Maven热部署等服务器环境的搭建过程. 服务器: 已经将所需要的工具(Xshell,Xftp.FileZilla等sftp上传工具 ...

  2. 20164320 王浩 Exp1 PC平台逆向破解

    一.逆向及Bof基础实践说明 1.1实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. 手工修 ...

  3. Map集合转成json数据

    maven项目需要导入一下依赖: <dependency> <groupId>net.sf.json-lib</groupId> <artifactId> ...

  4. pandas(一)

    import numpy as py import pandas as pd Series对象 data= pd.Series([0.25,0.5,0.75,1.0])   默认索引是数字 data= ...

  5. PL_SQL学习

    打印输出: dbms_output.put_line('AA'); 显示服务器输出信息  set serveroutput on; 打印出eid=1的员工姓名: declare v_name varc ...

  6. js比较两个单独的数组或对象是否相等

    所谓js的中的传值,其实也就是说5种基本数据类型(null,undefind,boolean,number,string) 传引用也就是说的那个引用数据类型,(array和object) 基本数据类型 ...

  7. 使用@Autowired时,取值为null

    如果取不到,可以考虑其他方式 场景: @Autowired private StringRedisTemplate redisTemplate; 想使用redisTemplate,但是使用时为null ...

  8. 【LeetCode每天一题】Edit Distance(编辑距离)

    Given two words word1 and word2, find the minimum number of operations required to convert word1 to  ...

  9. spring IOC 分析及实现

    什么是IOC Inversion of Control,控制反转,也成依赖倒置. 反转: 依赖对象的创建被反转,使用IOC之前,对象由自己创建,反转后,由IOC容器获取 IOC容器的工作: 负责创建, ...

  10. 使用nginx做反向代理和负载均衡效果图

    连续请求nginx服务器,响应如图: 参考文章:https://segmentfault.com/a/1190000007495181