以下是个人对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. JAVA的第一次作业

    读后感:这个学期开始接触一门新的学科就是JAVA,老师对这么学科介绍了很多,我也从中了解到了许多,它可能是相对于C语言而已可能要更加方便一些,也是现在世界上所用最多的语音(软件方面),C语言都是排在它 ...

  2. python练习题-day18

    1.匹配一行文字中的所有开头的字母内容 import re s="i love you not because of who you are, but because of who i am ...

  3. MATLAB关系运算符和逻辑运算符

    1 关系运算符 关系运算符用来比较两个数之间的大小关系,在Matlab中的关系运算符包括: <  小于 <= 小于或等于 >        大于 >=      大于或等于 = ...

  4. 细说@Html.ActionLink()的用法(转)

    细说@Html.ActionLink()的用法   一.@Html.ActionLink()概述 在MVC的Rasor视图引擎中,微软采用一种全新的方式来表示从前的超链接方式,它代替了从前的繁杂的超链 ...

  5. python [[1,2],[3,4],[5,6]]一行代码展开该列表,得出[1,2,3,4,5,6]

    #1)利用推导式运行过程:for i in a ,每个i是[1,2],[3,4],[5,6],for j in i,每个j就是1,2,3,4,5,6,合并后就是结果 a=[[1,2],[3,4],[5 ...

  6. 微信小程序之回调函数

    在微信小程序中众所周知在js里面得方法都是异步执行,我最近再做项目得时候也遇到了这个问题,再方法里面调用另一个方法里面的接口数据,第一次是调取不到的, 因为两个方法是同时开始执行得,所以怎么都取不到值 ...

  7. winrar目录穿越漏洞

    地址: 参考: https://research.checkpoint.com/extracting-code-execution-from-winrar/ POC: https://github.c ...

  8. powerdesigner的PDM模型name和comment相互复制替换

    在[Tools]-[Execute Commands]-[Edit/Run Script] 下.输入以下命令,这些命令也可以保存起来,扩展名为 vbs ,以便下次使用. 1.name的值复制到comm ...

  9. python模块学习之hashlib模块学习

    # 加密模块 import hashlib # md5 加密 md5 # 1.初始化md5模块 生成md5对象 # 2.引入要加密的数据 update # 3.获取加密值 hexdigest m = ...

  10. Elasticsearch从入门到精通之Elasticsearch集群内的原理

    上一章节我介绍了Elasticsearch安装与运行,本章节及后续章节将全方位介绍 Elasticsearch 的工作原理 在这个章节中,我将会再进一步介绍 cluster . node . shar ...