Java中字符编码格式详解

一、前言

  在分析Comparable和Comparator的时候,分析到了String类的compareTo方法,String底层是用char[]数组来存放元素,在比较的时候是比较的两个字符串的字符,字符用char来存储,此时,突然想到,Java里面的char可以存放中文吗?后来发现是可以的,并且由此也引出了Java中字符的编码格式问题。

二、Java存储格式

  在Java中,如下代码获取了字符'张'的各种编码格式。

import java.io.UnsupportedEncodingException;
public class Test {
 public static String getCode(String content, String format) throws UnsupportedEncodingException {
  byte[] bytes = content.getBytes(format);
  StringBuffer sb = new StringBuffer();
  for (int i = 0; i < bytes.length; i++) {
   sb.append(Integer.toHexString(bytes[i] & 0xff).toUpperCase() + " ");
  }

  return sb.toString();
 }
 public static void main(String[] args) throws UnsupportedEncodingException {
  System.out.println("gbk : " + getCode("张", "gbk"));
  System.out.println("gb2312 : " + getCode("张", "gb2312"));
  System.out.println("iso-8859-1 : " + getCode("张", "iso-8859-1"));
  System.out.println("unicode : " + getCode("张", "unicode"));
    System.out.println("utf-16 : " + getCode("张", "utf-16"));
  System.out.println("utf-8 : " + getCode("张", "utf-8"));
  }
}

  运行结果:

gbk : D5 C5
gb2312 : D5 C5
iso-8859-1 : 3F
unicode : FE FF 5F 20
utf-16 : FE FF 5F 20
utf-8 : E5 BC A0 

  说明:从结果我们可以知道,字符'张'的gbk与gb2312编码是相同的,unicode与utf-16编码时相同的,但是其iso-8859-1、unicode、utf-8编码都是不相同的。那么,在JVM中,字符'张'是按照哪种编码格式进行存储的呢?下面开始我们的分析。

三、探秘思路

 1. 查看.class文件常量池的存储格式

  测试代码如下  

public class Test {
 public static void main(String[] args) {
  String str = "张";
 }
}

  使用javap -verbose Test.class进行反编译,发现常量池情况如下:

  再使用winhex打开class文件,发现字符'张'在常量池的存储如下

  说明:上面两张可以在class文件中是以utf-8的格式存储的。

  但是在运行时是否是utf-8格式呢?继续我们的探秘之旅。

  2. 在程序中一探究竟

  使用如下代码 

public class Test {
 public static void main(String[] args) {
  String str = "张";
  System.out.println(Integer.toHexString(str.codePointAt(0)).toUpperCase());
 }
}

  运行结果:

5F20

  说明:根据结果我们知道在运行时JVM是使用的utf-16格式进行存储,utf-16一般是使用2个字节进行存储,如果遇到两个字节无法表示的字符则会使用4个字节表示。之后会另外有篇幅进行介绍,并且我们查看Character类源码时,会发现就是使用的utf-16进行编码的,从两面都找到了我们想要的答案。

  3. char类型可以存放中文吗?

  根据上面的探索我们已经知道了Java的class文件中字符是以utf-8进行编码的,在JVM运行时则是以utf-16进行编码存储的。而字符'张'可以用两个字节来表示,而char在Java中也是两个字节,故可以存放。

四、总结

  经过上面的分析,我们知道:

  1. 字符在class文件中是以utf-8格式进行编码的,而在JVM运行时是采用utf-16格式进行编码的。

  2. char类型是两个字节,可以用来存放中文。

  在此次调用的过程中又查阅了好多关于字符方面的资料,受益匪浅,并且发现特别有意思,接下来会进行分享,所以特此预告下一篇将会进一步来介绍编码以及编码在Java中的问题。敬请期待

(0)

相关推荐

  • 基于Java字符编码的使用详解

    1,什么是字符编码? 字符(Character)是文字与符号的总称,包括文字.图形符号.数学符号等.一组抽象字符的集合就是字符集(Charset).字符集的出现是为了信息进行传播储存提供方便.目前常用到字符集有:ASCII,ISO 8859-1,Unicode,GB2312 2,各种编码集有哪些特点? ASCII: ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统. 包含内容:

  • Java字符编码解码的实现详解

     字符集基础: Character set(字符集)          字符的集合,也就是,带有特殊语义的符号.字母"A"是一个字符."%"也是一个字符.没有内在数字价值,与 ASC II ,Unicode,甚至是电脑也没有任何的直接联系.在电脑产生前的很长一段时间内,符号就已经存在了. Coded character set(编码字符集)          一个数值赋给一个字符的集合.把代码赋值给字符,这样它们就可以用特定的字符编码集表达数字的结果.其他的编码字符

  • Java字符编码原理(动力节点Java学院整理)

    Java开发中,常常会遇到乱码的问题,一旦遇到这种问题,常常比较烦恼,大家都不愿意承认是自己的代码有问题.其实编码问题并没有那么神秘,那么不可捉摸,搞清Java的编码本质过程就真相大白了. 先看个图: 其实,编码问题存在两个方面:JVM之内和JVM之外. 1.Java文件编译后形成class 这里Java文件的编码可能有多种多样,但Java编译器会自动将这些编码按照Java文件的编码格式正确读取后产生class文件,这里的class文件编码是Unicode编码(具体说是UTF-16编码). 因此

  • Java反转字符串和相关字符编码的问题解决

    复制代码 代码如下: public String reverse(char[] value){       for (int i = (value.length - 1) >> 1; i >= 0; i--){           char temp = value[i];           value[i] = value[value.length - 1 - i];           value[value.length - 1 - i] = temp;       }     

  • Java中的字符编码问题处理心得总结

    当面对一串字节流的时候,如果不指定它的编码,其实际意义是无法知道的. 这句话应该也是我们面对"字符转字节,字节转字符"问题时候时刻记在脑子里的.否则乱码问题可能就接踵而至. 其实乱码问题的本质就是Encoding和Decoding用的不是一个编码,明白了这个道理就很好解决乱码问题了. Java中常见的时候有如下: 1. String类使用byte[]的构造函数 String(byte[] bytes),String类同时提供了两个重载 (1)String(byte[] bytes, C

  • Java中字符编码格式详解

    一.前言 在分析Comparable和Comparator的时候,分析到了String类的compareTo方法,String底层是用char[]数组来存放元素,在比较的时候是比较的两个字符串的字符,字符用char来存储,此时,突然想到,Java里面的char可以存放中文吗?后来发现是可以的,并且由此也引出了Java中字符的编码格式问题. 二.Java存储格式 在Java中,如下代码获取了字符'张'的各种编码格式. import java.io.UnsupportedEncodingExcept

  • java中正则表达式实例详解

    Java中正则表达式运用实例(参看java中正则表达式运用详解): 测试代码 package test; /** * 在String的matches()方法,split()方法中使用正则表达式. * @author fhd001 */ public class RegexTest { public static void main(String[] args) { /* * 普通字符 */ String str1 = "abc45abc345"; String[]arr1 = str1

  • Java中的静态内部类详解及代码示例

    1. 什么是静态内部类 在Java中有静态代码块.静态变量.静态方法,当然也有静态类,但Java中的静态类只能是Java的内部类,也称为静态嵌套类.静态内部类的定义如下: public class OuterClass { static class StaticInnerClass { ... } } 在介绍静态内部类之前,首先要弄清楚静态内部类与Java其它内部类的区别. 2. 内部类 什么是内部类?将一个类的定义放在另一个类的内部,就是内部类.Java的内部类主要分为成员内部类.局部内部类.

  • Java中初始化块详解及实例代码

    Java中初始化块详解 在Java中,有两种初始化块:静态初始化块和非静态初始化块. 静态初始化块:使用static定义,当类装载到系统时执行一次.若在静态初始化块中想初始化变量,那仅能初始化类变量,即static修饰的数据成员. 非静态初始化块:在每个对象生成时都会被执行一次,可以初始化类的实例变量. 非静态初始化块会在构造函数执行时,且在构造函数主体代码执行之前被运行. 括号里的是初始化块,这里面的代码在创建Java对象时执行,而且在构造器之前执行! 其实初始化块就是构造器的补充,初始化块是

  • Java中的HashSet详解和使用示例_动力节点Java学院整理

    第1部分 HashSet介绍 HashSet 简介 HashSet 是一个没有重复元素的集合. 它是由HashMap实现的,不保证元素的顺序,而且HashSet允许使用 null 元素. HashSet是非同步的.如果多个线程同时访问一个哈希 set,而其中至少一个线程修改了该 set,那么它必须 保持外部同步.这通常是通过对自然封装该 set 的对象执行同步操作来完成的.如果不存在这样的对象,则应该使用 Collections.synchronizedSet 方法来"包装" set.

  • java 中cookie的详解及简单实例

    java 中cookie的详解 Java对cookie的操作比较简单,主要介绍下建立cookie和读取cookie,以及如何设定cookie的生命周期和cookie的路径问题. 建立一个无生命周期的cookie,即随着浏览器的关闭即消失的cookie,代码如下 HttpServletRequest request HttpServletResponse response Cookie cookie = new Cookie("cookiename","cookievalue&

  • Java中final关键字详解

    谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法. 主要介绍:一.final关键字的基本用法.二.深入理解final关键字 一.final关键字的基本用法 在Java中,final关键字可以用来修饰类.方法和变量(包括成员变量和局部变量).下面就从这三个方面来了解一下final关键字的基本用法. 1.修饰类 当用final修饰一个类时,表明这个类不能

  • Java 中的HashMap详解和使用示例_动力节点Java学院整理

    第1部分 HashMap介绍 HashMap简介 HashMap 是一个散列表,它存储的内容是键值对(key-value)映射. HashMap 继承于AbstractMap,实现了Map.Cloneable.java.io.Serializable接口. HashMap 的实现不是同步的,这意味着它不是线程安全的.它的key.value都可以为null.此外,HashMap中的映射不是有序的. HashMap 的实例有两个参数影响其性能:"初始容量" 和 "加载因子&quo

  • java 中归并排序算法详解

    java 中归并排序算法详解 归并排序算法,顾名思义,是一种先分再合的算法,其算法思想是将要排序的数组分解为单个的元素,每个元素就是一个单个的个体,然后将相邻的两个元素进行从小到大或从大到小的顺序排序组成一个整体,每个整体包含一到两个元素,然后对相邻的整体继续"合"并,因为每个整体都是排过序的,因而可以采用一定的算法对其进行合并,合并之后每个整体包含三到四个元素,继续对相邻的整体进行合并,直到所有的整体都合并为一个整体,最终得到的整体就是将原数组进行排序之后的结果. 对于相邻的整体,其

  • java中参数传递方式详解

    java中参数传递方式详解 java新手入门面临的一个经典的话题,本文意在终结这个话题,java中有说法:Java里面参数传递都是按值传递,怎么理解这句话?用文字说明恐怕不容易说明白,说明白恐怕也难以想明白. 前提 先明确一下,按值还是按引用的概念,它是来自c++语言,引用不是汉语词典中的一个词,而是c++的概念--"&"这个符号还记得吧? 为什么有这个话题呢?其一,是对按引用传递理解不透彻:其二,诸多java书籍及讨论论点并没有切中要害. 一句话概括,按值传参还是按引用传参,

随机推荐