以下是个人对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. hive时间日期函数及典型场景应用

    1.hive取得当前日期时间: 1.1) 取得当前日期: select current_date(); 1.2) 取得当前日期时间: select current_timestamp(); 1.3) ...

  2. 新人上手:如何做好一个App的推广?

    App推广是现在所有公司都绕不开的槛,而一般App推广又分为线上线下两个方面,其中,App线上推广是互联网时代运营人员接触最多的一种推广方式.一款App应用推广的最终目的是为了吸引目标用户,为推销的产 ...

  3. webrtc如何进行错误恢复

    视频的压缩方法:(三种帧) 为了视频尽可能的保持高效,视频数据通过不同的编码进行压缩.以帧为单位进行压缩,按照压缩中的不同作用可分类为:内帧(Intra-frames,I帧),预测帧(Predicti ...

  4. YOLO V3 错误总结

    问题1 TypeError: function takes exactly 1 argument (3 given) 报错说PIL库中的函数只接收到一个参数,应该给三个,自己在这里记录下解决方法,出错 ...

  5. golang的包管理---vendor/dep等

    首先关于vendor 1 提出问题 我们知道,一个工程稍大一点,通常会依赖各种各样的包.而Go使用统一的GOPATH管理依赖包,且每个包仅保留一个版本.而不同的依赖包由各自的版本工具独立管理,所以当所 ...

  6. 关于Eureka客户端连接服务端报错问题Cannot execute request on any known server

    对于Eureka包这个错误问题:Cannot execute request on any known server,总的原因就是连接Eureka连接服务端的Url地址不对,Url地址不对很很多情况. ...

  7. python 小试一题

    a = 66count = 1while count <=3 : b = int(input("猜测这个数字:")) if b < a: print("猜测的 ...

  8. Java 基础 多线程和线程池基础

    一,多线程 1.1 多线程介绍 进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能. 线程:线程是进程中的一个执行单元,负 ...

  9. 【Pattern】-NO.150.Pattern.1 -【Pattern UML】

    Style:Mac Series:Java Since:2018-09-10 End:2018-09-10 Total Hours:1 Degree Of Diffculty:5 Degree Of ...

  10. hook

    hook的定义 hook,钩子,勾住系统的程序逻辑. 在某段SDK源码逻辑执行的构成中,通过代码手段拦截执行该程序,加入自己的代码逻辑 使用价值 hook是安卓面向切面(aop)编程的基础,可以让我们 ...