Java基本的程序结构设计 字符类型

字符型

从概念上讲,java的字符型就是unicode字符序列。

不可变:

一旦定义了一个字符串,就没有方法修改它。java没有提供修改字符串的方法,对于C程序来说,字符串相当于是个数组,你可以改变任何一个下标的值。但是Java不可以。

如果要对java字符串修改下标,只能新建一个字符串,然后通过substring和拼接来实现,这样一定程度上效率很低。

但是java设计者认为字符串修改操作很少,对于字符串的操作,大多是比较,和合并等操作。所以java设计者将字符串设置为不可变,然后实现了共享。

没有字符串是可变的,就不能实现共享:

可以想象将字符串放在一个公共的池中,字符串变量指向池中的值,如果复制一个字符串,源字符串和复制的字符串共享相同的位置。

java设计者认为共享带来的高效率远远胜过可修改的字符串。

检测相等:

因为不可变,所以不能用==,只能用equals。

因为String是对象,对于对象的比较,==在java中是用来比较对象指向的堆栈中的位置是否相同。

虽然如此,如果我们用=比较对象指向堆栈中的位置是否一样,也是不可以。

  1. package com.zjf;
  2.  
  3. public class Test {
  4.  
  5.    public static void main(String[] args) {
  6.  
  7.       String s1 = "zhang";
  8.       String s2 = "zhang";
  9.       System.out.println(s1 == s2);
  10.    }
  11. }

结果为true。对我们来说,并没有做s1=s2的操作,结果却是true,这不是我们想要的结果。虽然说Sting a = b;那么用a == b是可以的,但是如果没有a=b,也可以a==b,这样对我们来说,会有不可预知的结果。

那么如果我们想用=来比较两个字符串的内容是否一致呢?也不行。

  1. package com.zjf;
  2.  
  3. public class Test {
  4.  
  5.    public static void main(String[] args) {
  6.  
  7.       String s1 = "zhang";
  8.       String s2 = "zhangjianfeng".substring(0, 5);
  9.       System.out.println(s1);
  10.       System.out.println(s2);
  11.       System.out.println(s1 == s2);
  12.    }
  13. }

结果为:

zhang

zhang

false

两个字符串都是zhang,使用=却没有比较成功。

原因是因为java虚拟机只对字符串常量进行共享,对于+和substring等操作产生的结果,是不会共享的。

使用==进行字符串比较,程序会出现bug,而且这种bug在一定程度上是随机的。不要使用。

代码点和代码单元

Java字符串由char序列组成,char是采用UTF-16编码表示Unicod代码点的代码单元。

代码点就是我们生活中面对的一个字,因为UTF-16的存储方式,对于某些代码点需要32位,也就是说两个代码单元来存储,在java中,一个char是一个代码单元。

这样就会造成一些误解。

首先,length方法返回的是代码单元的数量。而不是代码点的数量。

其次,charAt方法获取的是代码单元,不是代码点。如果想获取代码点,string提供的有codepoint方法,

如下代码:

作者说,避免使用char,因为这太低级了。其实,虽然很少见到这些特殊字符,使用char的场景还是要慎重。

构建字符串:

使用较短的字符串构建字符串:

  • StringBuilder
  • StringBuffer 线程安全

包引入问题

像Sting,Integer,StringBuilder这种包,位于java.lang目录下,不需要import引入,也能识别。

读取输入:

java.util.Scanner

一个可以使用正则表达式来分析基本类型和字符串的简单文本扫描器。

了解:

Scanner 使用分隔符模式将其输入分解为标记,默认情况下该分隔符模式与空白匹配。然后可以使用不同的 next 方法将得到的标记转换为不同类型的值。

例如,以下代码使用户能够从 System.in 中读取一个数:

Scanner sc = new Scanner(System.in);

int i = sc.nextInt();

再看一个例子,以下代码使 long 类型可以通过 myNumbers 文件中的项分配:

Scanner sc = new Scanner(new File("myNumbers"));

while (sc.hasNextLong()) {

long aLong = sc.nextLong();

}

扫描器还可以使用不同于空白的分隔符。下面是从一个字符串读取若干项的例子:

String input = "1 fish 2 fish red fish blue fish";

Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");

System.out.println(s.nextInt());

System.out.println(s.nextInt());

System.out.println(s.next());

System.out.println(s.next());

s.close();

输出为:

1

2

red

blue

以下代码使用正则表达式同时分析所有的 4 个标记,并可以产生与上例相同的输出结果:

String input = "1 fish 2 fish red fish blue fish";

Scanner s = new Scanner(input);

s.findInLine("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)");

MatchResult result = s.match();

for (int i=1; i<=result.groupCount(); i++)

System.out.println(result.group(i);

s.close();

扫描器所使用的默认空白分隔符通过 Character.isWhitespace 来识别。

关于File的相对目录:

了解:

如果在创建一个File的时候,使用了相对目录,那么:

相对路径名必须使用来自其他路径名的信息进行解释。默认情况下,java.io 包中的类总是根据当前用户目录来分析相对路径名。此目录由系统属性 user.dir 指定,通常是 Java 虚拟机的调用目录。

也就是说相对于user.dir的目录。所以我们尽量不会使用相对目录,这里遇到了,所以标注下,了解下。

文本输出:

java.io.PrintWriter

向文本输出流打印对象的格式化表示形式。此类实现在 PrintStream 中的所有 print 方法。它不包含用于写入原始字节的方法,对于这些字节,程序应该使用未编码的字节流进行写入。

这个类的作用是把内存中的对象,以格式化文本的方式,输出到流中。它的api如下:

java.io.PrintStream和java.io.PrintWriter的api基本一样,只不过一个是通过字节的方式来输出,一个是字符的方式,不过这都是内部实现上。

这两个类很少使用,因为System.out使用的是PrintStream,我们这里了解一下。

时间: 2024-08-05 17:50:41

Java基本的程序结构设计 字符类型的相关文章

Java基本的程序结构设计 基本类型的输入输出

读取输入: java.util.Scanner 一个可以使用正则表达式来分析基本类型和字符串的简单文本扫描器. 了解: Scanner 使用分隔符模式将其输入分解为标记,默认情况下该分隔符模式与空白匹配.然后可以使用不同的 next 方法将得到的标记转换为不同类型的值. 例如,以下代码使用户能够从 System.in 中读取一个数: Scanner sc = new Scanner(System.in); int i = sc.nextInt(); 再看一个例子,以下代码使 long 类型可以通

Java Web 应用程序的字符编码问题

  Java Web 应用程序经常会出现乱码的情况,这里可以通过 Servlet API 中的标准 Filter 来实现,也可以在 Web 容器配置 URIEncoding.这些都依赖于浏览器的请求方式. 在 Web 容器的配置文件中配置 URIEncoding = "UTF-8" 使用 Servlet API 的标准 Filter 结果 地址栏中直接输入链接(含汉字) √ × 失败(编码成功) 地址栏中直接输入链接(含汉字) × √ 失败(编码成功) 地址栏中直接输入链接(含汉字)

Java基本的程序结构设计 大数操作

大数操作 BigInteger 不可变的任意精度的整数.所有操作中,都以二进制补码形式表示 BigInteger(如 Java 的基本整数类型).BigInteger 提供所有 Java 的基本整数操作符的对应物,并提供 java.lang.Math 的所有相关方法.另外,BigInteger 还提供以下运算:模算术.GCD 计算.质数测试.素数生成.位操作以及一些其他操作. 个人理解:可以理解为BigInteger内部维护了一个int数组,这个数组可以无限大.java在对BigInteger进

Java基本的程序结构设计 数组

声明数组: int[] a; int a[]; 两种方式.一般选择第一种,比较一目了然. 初始化,必须指定长度: int[] a = new int[10]; int[] a = {1,2,3}; 初始化: package com.zjf;   import java.util.Arrays;   import com.zjf.spring.mybatis.model.Person;   public class Test {      public static void main(Strin

Java基本的程序结构设计 控制流程

控制流程 java的控制流程和C和C++基本一致,只是不能使用goto语句,不过break语句可以带标签,实现从内层循环跳出的目的.标签可以放在for或者while前面.如下: package com.zjf;   import java.io.Console; import java.util.Scanner;   public class Test {      public static void main(String[] args) {       outer: for(int i=0

JAVA输入/输出流程序例题(文件和目录、字节流、字符流)

一.文件和目录 1.显示文件的基本信息. 2.显示目录的基本信息. 3.在指定目录下创建单个文件. 4.指定目录下创建多个临时文件. 二.字节流 1.生成ZIP压缩文件 2.解压缩zip文件 3.生成Excel文件 4.读取excel文件 5.生成PDF文件 6.读取PDF文件中的内容 7.利用poi读取Word文件中的内容. 三.字符流 1.追加文件内容 2.读取jar包内容 3文件的加密/解密操作 JAVA加包+++右键项目+BuildPath+Add External Achievees.

java 基础 字符类型

1.char类型的字面量可以是一个英文字母.字符或一个汉字,并且由单引号包括. 2.Java底层使用一个16位的整数来处理字符类型,该数值是一个字符的unicode编码值. unicode: 1.unicode编码是全球范围内的编码方法. 2.unicode编码的英文部分与ASCII码兼容(ASCII表示范围0~128), 同时英文字符和数字是连续编码的. 3.Java在处理char类型的数据时,在底层是按unicode码来处理的. 编码是什么? 计算机硬件系统只能用0和1表示数,我们人为地做了

MySQL常用指令,java,php程序员,数据库工程师必备。程序员小冰常用资料整理

MySQL常用指令,java,php程序员,数据库工程师必备.程序员小冰常用资料整理 MySQL常用指令(备查) 最常用的显示命令: 1.显示数据库列表. show databases; 2.显示库中的数据表: use mysql; show tables; 3.显示数据表的结构: describe 表名; 4.建库: create database 库名; 5.建表: use 库名: create table 表名 (字段设定列表): 6.删库和删表: drop database 库名; dr

理解隐式类型、对象初始化程序和匿名类型

在C# 3.0中,几乎每个新特性都是为LINQ服务的.所以,本文将介绍下面几个在C# 3.0中引入的新特性: 自动实现的属性 隐式类型的局部变量 对象和集合初始化程序 隐式类型的数组 匿名类型 其实这几个特性都是比较容易理解的,对于这几个特性,编译器帮我们做了更多的事情(想想匿名方法和迭代器块),从而简化我们的代码. 自动实现的属性 在C# 3.0以前,当我们定义属性的时候,一般使用下面的代码 public class Book { private int _id; private string