zoukankan      html  css  js  c++  java
  • 字符和字符串在Java中的旅程

    以下是个人对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            // u0001u0001
      #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               u0001u0001
      #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知道,字符和字符串的输出,先根据平台默认的字符集将输出的字符或编码成一个或多个字节,然后将这些字节输出到终端。

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

  • 相关阅读:
    Python学习之路(一)之Python基础1
    【第十一课】Tomcat原理解析【转】
    【第十课】Tomcat入门
    【第九课】MriaDB密码重置和慢查询日志
    【第八课】php-fpm.conf配置文件解析
    【第七课】Nginx反向代理和负载均衡
    【第六课】Nginx常用配置下详解
    maven项目中更新了核心库后导致一些包提示未定义,如:The import org.json cannot be resolved
    js代码突然在花括号回车自动多加了一个大括号
    SQL0419N 十进制除法运算无效,因为结果将有一个负小数位。 SQLSTATE=42911
  • 原文地址:https://www.cnblogs.com/yvkm/p/10400856.html
Copyright © 2011-2022 走看看