下面的程序从一个字节序列创建了一个字符串,然后迭代遍历字符串中的字符,并将它们作为数字打印。请描述一下程序打印出来的数字序列:
public class StringCheese {
public static void main(String[] args) {
byte bytes[] = new byte[256];
for (int i = 0; i < 256; i++)
bytes[i] = (byte)i;
String str = new String(bytes);
for (int i = 0, n = str.length(); i < n; i++)
System.out.println((int)str.charAt(i) + " ");
}
}
首先,byte数组用从0到255每一个可能的byte数值进行了初始化,然后这些byte数值通过String构造器被转换成了char数值。最后,char数值被转型为int数值并被打印。打印出来的数值肯定是非负整数,因为char数值是无符号的,因此,你可能期望该程序将按顺序打印出0到255的整数。
如果你运行该程序,可能会看到这样的序列。但是在运行一次,可能看到的就不是这个序列了。我们在四台机器上运行它,会看到四个不同的序列,包括前面描述的那个序列。这个程序甚至都不能保证会正常终止,比打印其他任何特定字符串都要缺乏这种保证。它的行为完全是不确定的。
这里的罪魁祸首就是String(byte[])构造器。有关它的规范描述道:“在通过解码使用平台缺省字符集的指定byte数组来构造一个新的String时,该新String的长度是字符集的一个函数,因此,它可能不等于byte数组的长度。当给定的所有字节在缺省字符集中并非全部有效时,这个构造器的行为是不确定的”[Java-API]。
到底什么是字符集?从技术角度上讲,它是“被编码的字符集合和字符编码模式的结合物”[Java-API]。换句话说,字符集是一个包,包含了字符、表示字符的数字编码以及在字符编码序列和字节序列之间来回转换的方式。转换模式在字符集之间存在着很大的区别:某些是在字符和字节之间做一对一的映射,但是大多数都不是这样。ISO-8859-1是唯一能够让该程序按顺序打印从0到255的整数的缺省字符集,它更为大家所熟知的名字是Latin-1[ISO-8859-1]。
J2SE运行期环境(JRE)的缺省字符集依赖于底层的操作系统和语言。如果你想知道你的JRE的缺省字符集,并且你使用的是5.0或更新的版本,那么你可以通过调用java.nio.charset.Charset.defaultCharset()来了解。如果你使用的是较早的版本,那么你可以通过阅读系统属性“file.encoding”来了解。
幸运的是,你没有被强制要求必须去容忍各种稀奇古怪的缺省字符集。当你在char序列和byte序列之间做转换时,你可以且通常是应该显式地指定字符集。除了接受byte数字之外,还可以接受一个字符集名称的String构造器就是专为此目的而设计的。如果你用下面的构造器去替换在最初的程序中的String构造器,那么不管缺省的字符集是什么,该程序都保证能够按照顺序打印从0到255的整数:
String str = new String(bytes, "ISO-8859-1");
这个构造器声明会抛出UnsupportedEncodingException异常,因此你必须捕获它,或者更适宜的方式是声明main方法将抛出它,要不然程序不能通过编译。尽管如此,该程序实际上不会抛出异常。Charset的规范要求Java平台的每一种实现都要支持某些种类的字符集,ISO-8859-1就位列其中。
这个谜题的教训是:每当你要将一个byte序列转换成一个String时,你都在使用某一个字符集,不管你是否显式地指定了它。如果你想让你的程序的行为是可预知的,那么就请你在每次使用字符集时都明确地指定。对API的设计者来说,提供这么一个依赖于缺省字符集的String(byte[])构造器可能并非是一个好主意。
分享到:
相关推荐
根据提供的文件信息,“Java解惑 清晰版带书签”这一标题暗示这是一本深入探讨Java编程语言中常见问题及解决方案的专业书籍。该书由《Effective Java》的作者所著,因此我们可以推断出这本书将包含许多实用的Java...
### Java解惑知识点详解 #### 一、表达式谜题 **谜题1:奇数性** - **描述**:程序看似应该返回一个布尔值,表明一个数字是否为奇数,但结果却出乎意料。 - **解惑**:在进行模运算时,需要注意负数的情况。当输入...
在Java中,字符(char)类型是Unicode编码的,所以当两个char类型相加时,它们实际上是进行Unicode码点的加法。例如,'a' + 'b' 的结果是 'c',因为'a'的Unicode码点是97,'b'是98,两者相加得到99,对应的字符是'c'。...
以下就是针对标题"java解惑(罗列了95个容易让你迷惑的java知识点)"中提及的一些关键知识点的详细解释。 1. **Java内存模型**:Java内存模型(JMM)规定了线程如何共享和访问数据,包括主内存、工作内存以及内存间的...
不过,可以按照给定的要求,基于标题“Java解惑中文”和描述“本书特写了95个有关Java或其类库的陷阱和缺陷的谜题,看完后会对Java加深理解”,来构建一些知识点。 标题《Java解惑中文》很可能是某本专注于解决Java...
Java中字符以Unicode编码,因此处理字符时需要理解Unicode的特性。例如,`'\u0061'`表示字符'a',而单引号内的字符不是字符串,而是字符常量。此外,字符和字符串的操作有特定的方法,如`charAt()`用于获取字符串中...
### Java基础知识 #### 1. Java的基本数据类型与String类型的区别 - **基本数据类型**:Java中的基本数据类型包括`byte`, `short`, `int`, `long`, `float`, `double`, `char`, `boolean`。它们是值类型,直接存储...
- 《Java解惑》:解答Java中的疑难问题,增进对语言特性的理解。 - 《分布式Java应用:基础与实践》:淘宝架构师的经验分享,对分布式系统有深入阐述。 在学习过程中,除了阅读书籍,实践是必不可少的。尝试编写...
Java Web编程宝典-十年典藏版.pdf 是PDF电子书,不是源码。共分2个包。 《Java Web编程宝典(十年典藏版)》是一本集技能、范例、项目和应用为一体的学习手册,书中介绍了应用Java Web进行程序开发的各种技术、技巧。...
- **解惑释疑 Java 难点和疑点**:针对常见的问题和困惑进行解答,帮助学员克服学习障碍。 #### 适用人群 - **Java 初学者**:适合完全没有接触过 Java 或者仅有初步了解的学员。 - **有经验的 Java 程序员**:对于...
总的来说,《IT学生解惑真经》是一本全方位指导IT学习者的经典之作,它不仅提供了丰富的知识,还可能包含实践案例和习题,帮助学生将理论与实际相结合,提升问题解决能力。通过阅读这本书,IT学生们将能够建立起坚实...
3. **MyBatis**:这是一个持久层框架,它允许开发者用简单的Java代码来操作数据库,避免了大量SQL的硬编码,提高了开发效率。 4. **Thymeleaf**或JSP:作为视图解析技术,它们负责将后端的数据渲染成用户可见的网页...
总的来说,理解和掌握`String`类的`length()`方法、字符数组与字符串的区别以及Unicode编码在Java中的应用,是Java程序员必备的基础技能,也是面试中常见的问题。对于处理中文字符,需要特别注意字符编码的细节,以...
13. **问题解决与支持**:由于项目提供了助教老师协助,说明在实际使用中遇到问题时,有专业人员提供技术支持和答疑解惑。 总的来说,这个JavaWeb仓库管理系统项目涵盖了Java编程、Web开发、数据库管理和项目实践等...
《Java 解惑》 - **推荐理由**: - 特写95个有关Java或其类库的陷阱和缺陷的谜题; - 采用短程序的方式展示问题,以及如何避免这些陷阱和缺陷; - 适合具备一定Java知识的学习者和有经验的Java程序员。 #### 5....
为了进入这些高收入领域,学生需要掌握相关的编程语言和技术框架,如Java、Python、机器学习算法等,并通过实践项目不断积累经验。 #### 程序员如何踏上社会 对于即将毕业的学生而言,如何顺利从校园过渡到职场是...