Java API(Java Application Programming Interface)是Java应用程序编程接口的缩写,Java中的API,就是JDK提供的具有各种功能的Java类,灵活使用Java API能够大大提高使用Java语言编写程序的效率,本章对Java中提供的最常用的工具类进行介绍,包括Object、包装类、字符串处理类String、StringBuffer以及StringBuilder、Math类以及日期类。
重点:
(1) Object类及其常用方法
(2) 包装类的概念及其和基本数据类型、字符串之间的相互转换
(3) 三种不同的字符串类及其用法
(4) 日期类Date、Calendar及SimpleDateFormat的使用
难点:
(1) Object类的常用方法
(2) 包装类和基本数据类型、字符串之间的相互转换
(3) 字符串类的使用
(4) 日期类的使用
Java API(Java Application Programming Interface)是Java应用程序编程接口的缩写,Java中的API,就是JDK提供的具有各种功能的Java类,由于Java类库非常庞大,而且在不断壮大,本书不可能一一介绍所有类的使用方法,读者应该养成查阅Java API文档的习惯,就像查询字典一样,在需要用到某个类的时候,可以从Java API文档中获得这个类的详细信息。Java API的帮助文档可到http://docs.oracle.com/javase/8/docs/api/下载,灵活使用Java API能够提高使用Java语言编写程序的效率,下面对Java中提供的最常用的包进行介绍。
java.lang:Java语言包, 该包中提供了利用Java语言进行程序设计的基础类,比如String、Math、System类,在任何类中,该包中的类不需要使用import语句进行导入,都会被自动导入。
java.util:该包中主要包含一些实用的工具类,比如集合框架类、日期处理类、字符串解析类、随机数生成类等。
java.awt:该包中主要包含处理用户界面和绘制图形图像的各种类。
java.io:该包中主要包含处理输入、输出编程的各种类。
java.net:该包中主要包含处理网络编程的各种类。
java.sql:该包中主要包含处理数据库编程的各种类。
java.lang包中常用的类如表1-1所示。
表1-1 java.lang包中的常用类
java.util包中常用的类如表1-2所示。
表1-2 java.util包中的常用类
表1-3 java.io包中的常用类
java.net包中常用的类如表1-4所示。
在Java中,有这样一个类,它是所有类的祖先类,也就是说,任何类都是其子孙类,它就是java.lang.Object。如果一个类没有显式地指明其父类,那么它的父类就是Object,也就是说,下面两条语句的作用是一样的:
public class ClassName{…} 等价于 public class ClassName extends Object{…}
如同我们称自己为炎黄子孙一样,所有的类都可以称为Object子孙类,所以,在Object类中定义的方法,在所有类中都可以使用。同时,Object类也是Java语言中唯一一个没有父类的类。
做为一个超级祖先类,Object类为子类提供了一些public修饰的方法,便于子类覆盖来实现子类自己特定的功能,下面我们要详细介绍其中的equals()方法、hashCode()方法和toString()方法。
(1)public boolean equals(Object obj)
该方法在Object类中的作用是:比较两个引用所指向的对象是否是同一个对象,即两个引用所指向对象的地址是否相等。
注意,通常情况下,Object的任何子类均可以按照自己的需要对equals()方法进行覆盖,以改变此方法的含义,所以有的类中equals()方法是比较地址,有的类中该方法不是比较地址,具体的,就看子类中该方法是如何实现的。
【例1-1】 定义公民类Citizen,覆盖该类的equals()方法,该方法的定义为:如果两个公民的身份id相同,则为同一个公民。
public class Citizen {
private int id;
private String name;
public Citizen(int id, String name) {
this.id = id;
this.name = name;
}
//覆盖父类的equals()方法
public boolean equals(Object o) {
Citizen c = (Citizen) o;
if (c.id == this.id) {
return true;
} else {
return false;
}
}
//主方法,测试equals()方法
public static void main(String args[]) {
Citizen xiaoming = new Citizen(21000, "xiaoming");
Citizen mingming = new Citizen(21000, "mingming");
System.out.println(xiaoming.equals(mingming));
}
}
程序运行结果:true
程序分析:上例定义了一个Citizen类,此类包含了公民的两个属性id和name,同时覆盖了equals()方法,该方法实现为:当传入对象的id和当前对象的id相等时,返回true,否则返回false。所以在main()方法最后一行调用equals()方法时,调用的实际上是Citizen类的equals()方法,xiaoming和mingming对象的id都为21000,所以程序运行结果为true。而假设如果Citizen类没有覆盖equals()方法,则在最后一行调用equals()方法时,实际调用的Object类的equals()方法,该方法比较两个对象是否指向同一块地址,所以肯定返回false,读者可自行验证。
接下来说一下"“运算符和equals()方法的区别。”"是比较运算符,既能用于比较两个基本数据类型,也能用于比较两个引用数据类型,当比较基本数据类型时,判断两个基本数据类型的字面量是否相等,当比较两个引用数据类型时,判断两个"引用"的值是否相等,也就是两个"引用"是否指向同一个对象。而equals()方法只能用于比较引用数据类型,Object类的equals()方法比较两个对象引用的值是否相等,但equals()方法通常都会被子类覆盖,所以子类中equals()方法的含义,就要看子类中的具体实现了。
【例1-2】 == 和 equals()方法在String类中的区别
String str1 = "hello";
String str2 = new String("hello");
System.out.println(str1==str2);
System.out.println(str1.equals(str2));
程序运行结果:
false
true
程序分析:因为String是引用数据类型,使用"=="运算符比较两个引用地址是否相同,第二行使用关键字new重新生成了一个String对象,所以第三行输出为false。在String类中,覆盖了Object的equals()方法,该方法判断两个String对象的内容是否相等,所以第4行输出为true。
(2) public int hashCode()
该方法返回对象的哈希码,哈希码是一个代表对象的十六进制整数,好比对象的身份证号。在程序运行期间,每次调用同一个对象的hashCode()方法,返回的哈希码必定相同,但是多次执行同一个程序,程序的一次执行和下一次执行期间,同一个对象的哈希码不一定相同。实际上默认的哈希码是将对象的内存地址通过某种转换得到的,所以不同对象会有不同的哈希码。
在Java中有个规定:如果equals()方法返回两个对象是相等的,那这两个对象上调用hashCode()返回的整数必须相等,否则在使用Hash类型集合时就会产生错误,所以在我们覆盖equals()方法同时,还要记得覆盖hashCode()方法。需要说明,如果equals()返回两个对象不等,它们的hashCode()也可以返回相同的整数,但是最好让它们的hashCode()返回不同的整数,这有利于提高Hash类型集合的性能。
那么重写equals()方法时,一定要重写hashcode()方法吗?
先说说hashcode()方法调用的条件,如果你想往map里面放一个类作为map的键值,这个类又是你自己设计的,或者这个类不是你写的但是你修改了这个类的equals()方法,这个时候,你就要重写hashcode()方法,这样当你往map里放值的时候,系统会调用这个对象的hashcode()方法来生成相应的hash值,来映射相应的对象。
如果同一个类的两个对象的属性值相等,那么他们的hashcode()一定相等吗?这个要看你具体如何实现你的hashcode()方法,如果你希望他们的值一样hashcode()也一样,你就可以这样实现。但是hashcode的实现,一般要满足几个特征,比如自反性,传递性什么的。自反性,即对任意一个非空的指引值x,x.equals(x)永远返回true,传递性,当x.equals(y)返回true并且y.equals(z)返回true时,x.equals(z)也返回true。
(3)public String toString()
该方法返回对象的字符串表示,形如:类名@hashcode,toString()方法是一个从字面上就容易理解的方法,它的功能是得到一个能够代表该对象的一个字符串:类名+"@"+代表该对象的一个唯一的16进制数,例如下面这个例子:
【例1-3】 查看Object类和String类的toString()方法返回值。
public class ObjectSample {
public static void main(String args[]){
Object o = new Object();
System.out.println(o);
System.out.println(o.toString());
String s = new String("hello");
System.out.println(s);
}
}
程序运行结果:
java.lang.Object@1db9742
java.lang.Object@1db9742
hello
程序分析:前两个输出结果表示对象o在内存中的地址,事实上返回这样的字符串没有什么实际的意义。一般子类都会覆盖该方法,让它返回有意义的文本。例如上例中的对象s的输出为"hello",这是因为字符串String类对toString()进行了覆盖,让它返回此String的本身内容。
下面通过实例来看一下如何在自己编写的类中覆盖equals()方法和toString()方法。
【例1-4】 equals()方法和toString()的覆盖
//圆类
public class MyCircle {
private int radius;//半径
public MyCircle(int r) {
radius = r;
}
public int getRadius() {
return radius;
}
public void setRadius(int r) {
radius = r;
}
//覆盖Object中的equals()方法
public boolean equals(Object obj) {
MyCircle o = (MyCircle) obj;
if (o.getRadius() == this.radius)
return true;
else
return false;
}
//覆盖Object中toString方法
public String toString() {
return "radius = " + radius;
}
}
//测试类
public class Test {
public static void main(String[] args) {
MyCircle obj1 = new MyCircle(3);
System.out.println("obj1:" + obj1.toString());
MyCircle obj2 = new MyCircle(3);
System.out.println("obj2:" + obj2.toString());
if (obj1.equals(obj2))
System.out.println("the two objects are equal");
else
System.out.println("the two objects are not equal");
}
}
程序运行结果:
obj1:radius = 3
obj2:radius = 3
the two objects are equal
程序分析:从程序的运行结果来看,我们创建的两个MyCircle对象是相等的,因为MyCircle类中覆盖的equals()方法规定,当两个MyCircle对象的半径相等时,认为这两个对象相等。而我们在调用MyCircle类的构造方法创建对象时设定这两个MyCircle对象的半径均为3,所以obj1.equals(obj2)返回true。
出于对性能的考虑,Java编程语言不把基本数据类型看作对象。因为处理对象需要额外的系统开销,所以,如果将基本数据类型当作对象,就会给语言性能带来负面影响。然而,许多Java中的方法需要将对象作为参数,为了让基本数据类型的这些数据也具有面向对象的特性,Java 编程语言提供了包装类来将基本数据类型看作对象,基本类型和包装类型之间能够互相转换。
1.3.1包装类简介
包装类型和基本数据类型的名字基本相同,首字母变成了大写,但是int和char的包装类型为Integer和Character。基本数据类型不是对象层次结构的组成部分。有时需要像处理对象一样处理这些基本数据类型,可通过相应的“包装类”来将其“包装”。表1-5列出了基本数据类型及其包装类型。
表1-5基本数据类型及其包装类型
八种基本类型都有对应的包装类,图1-1是它们的继承层次结构。
基本数据类型的变量没有默认值,而包装类型的变量默认值是null。在这八个包装类中,除了Integer和Character类以外,其它六个类的类名和基本数据类型一致,只是类名的第一个字母大写即可。对于包装类说,这些类的用途主要包含两种:
a、作为和基本数据类型对应的类类型存在,方便涉及到对象的操作。
b、包含每种基本数据类型的相关属性如最大值、最小值等,以及相关的操作方法。
1.3.2 基本类型与包装类之间的转换
包装类有什么作用呢?包装类能够完成数据类型之间(除boolean)的相互转换,尤其是基本数据类型和String类型的转换。包装类中包含了对应基本数据类型的值,封装了String和基本数据类型之间相互转换的方法,还有一些处理这些基本数据类型时非常有用的属性和方法。
由于八个包装类的使用比较类似,下面以最常用的Integer类为例子介绍包装类的实际使用。
1、实现int和Integer类之间的转换
在实际转换时,使用Integer类的构造方法和Integer类内部的intValue()方法实现int和Interger类型之间的相互转换,实现的代码如下:
int n = 10;
//将int类型转换为Integer类型
Integer in = new Integer(n);
//将Integer类型的对象转换为int类型
int m = in.intValue();
2、Integer类内部的常用方法
在Integer类内部包含了一些和int操作有关的方法,下面介绍一些比较常用的方法:
a、parseInt方法
public static int parseInt(String s)
该方法的作用是将数字字符串转换为int数值。在界面编程中,将字符串转换为对应的int数字是一种比较常见的操作。使用示例如下:
String s = “123”;
int n = Integer.parseInt(s);
则int变量n的值是123,该方法实际上实现了字符串和int之间的转换,如果字符串包含非数字字符,则程序执行将出现异常。
另外一个parseInt方法:
public static int parseInt(String s, int radix)
则实现将字符串按照参数radix指定的进制转换为int,使用示例如下:
int n = Integer.parseInt(“120”,10);
//将字符串"120"按照十进制转换为int,则结果为120
int n = Integer.parseInt(“12”,16);
//将字符串"12"按照十六进制转换为int,则结果为18
int n = Integer.parseInt(“ff”,16);
//将字符串"ff"按照十六进制转换为int,则结果为255
这样可以实现更灵活的转换。
b、toString方法
public static String toString(int i)
该方法的作用是将int类型转换为对应的String类型。
使用示例代码如下:
int m = 1000;
String s = Integer.toString(m);
则字符串s的值是"1000"。
1.3.3 字符串与基本数据类型、包装类型转换
1包装类转换成字符串
几乎java.lang.Object类派生的所有类提供了toString()方法,即将该类转换为字符串。例如:Characrer、Integer、Float、Double、Boolean、Short等类的toString()方法分别用于将字符型、整型、浮点型、双精度浮点型、短整型等类转换为字符串。举例如下所示:
int i1=10;
float f1=3.14f;
double d1=3.1415926;
Integer i1 = new Integer(i1);//生成Integer类
Float f1 = new Float(f1); //生成Float类
Double d1 = new Double(d1); //生成Double类
//分别调用包装类的toString() 方法转换为字符串
String si1 = i1.toString();
String sf1 = f1.toString();
String sd1 = d1.toString();
Sysytem.out.println(“si1”+si1);
Sysytem.out.println(“sf1”+sf1);
Sysytem.out.println(“sd1”+sd1);
整数转换成字符串也可以采用如下方法:
int myInt = 1234;
String myString = “” + myInt;
其它数据类型可以利用同样的方法转换成字符串
2**、字符串转换**为基本数据类型
字符串转换成整数:
String myNumber =“1234”;
int myInt = Integer.parseInt(myNumber);
字符串转换成byte、shor、int、float、double、long 等数据类型,可以分别参考Byte、Short、Integer、Float、Double、Long 类的parseXXX() 方法。
其实,JDK自从5.0版本以后,就引入了自动拆装箱的语法,也就是在进行基本数据类型和对应的包装类转换时,系统将自动进行,这将大大方便程序员的代码书写。使用示例代码如下:
//int类型会自动转换为Integer类型
int m = 12;
Integer in = m;
//Integer类型会自动转换为int类型
int n = in;
所以在实际使用时的类型转换将变得很简单,系统将自动实现对应的转换。Java允许基本类型和包装类型之间进行自动转换。例如可以自动装箱将一个基本数据类型转换为对象。
Integer intObject=new Integer(2);等价于 Integer intObject=2; //自动装箱
将基本类型转换为包装类对象的过程称为装箱,相反的过程称为拆箱。如果一个基本类型出现在需要对象的环境中,编译器会将基本类型值进行自动装箱;如果一个对象出现在需要基本类型的环境中,编辑器将对象进行自动拆箱。考虑下面的例子:
1:Integer [] intArray ={1,2,3};
2:System.out.printLn(intArray[0] + intArray [1] + intArray[2]);
在第一行中,基本类型1、2、3被自动装箱成对象new Integer(1)、new Integer(2)、new Integer(3) ,在第二行中,对象intArray[0]、intArray[0]、intArray[0]被自动转换为int值,然后进行相加。
【例1-5】包装类、基本数据类型和字符串之间转换的综合案例。
public class TestWrapper {
public static void main(String ars[]){
Double obj_d = new Double(3.14); //基本数据类型转换为包装类
double d = obj_d.doubleValue(); //包装类转换为基本数据类型
Integer obj_i = new Integer("5"); //字符串转换为包装类
String s = obj_i.toString(); //包装类转换为字符串转换
double n = Double.parseDouble("5"); //字符串类转换为基本数据类型
String s = obj_j.toString(); //基本数据类型转换为字符串类型
Integer aa = 9; //自动装箱
int bb = aa; //自动拆箱
}
}
程序分析:通过以上案例可以看出,基本数据类型和字符串类型转换为包装类,使用包装类的构造器来完成;包装类转换为基本数据类型,调用包装类的xxxValue()方法来完成;包装类转换为字符串类型,调用包装类的toString()方法;字符串转换为基本数据类型,调用包装类的parseXXX()方法;基本数据类型转换为字符串类型,先把基本数据类型转换为包装类型,然后再调用包装类的toString()方法;装箱就是把基本类型用它们相应的包装类型包装起来,使其具有对象的性质。int包装成Integer、float包装成Float,拆箱和装箱相反,将包装类型的对象转化成基本类型类型的数据。
1.4 字符串类
字符串是我们在编程中最常使用的一种数据类型,Java中用类来描述字符串,其中最常用的字符串处理类是String,此外还有StringBuffer和StringBuilder。在本节,我们会了解每种字符串的特点,以便能在应用时选择合适的字符串类型。字符串不属于8种基本数据类型,而是一种引用类型。String对象代表一组不可改变的Unicode字符序列,对它的任何修改实际上又产生一个新的字符串,String类是final类型的类,所以String类对象的内容一旦被初始化就不能再改变。StringBuffer对象代表一组可改变的Unicode字符序列,StringBuilder是JDK5.0版本后引入的字符串处理类,其中的方法与StringBuffer类的相同。
1.4.1 String对象的创建
String是比较特殊的数据类型,它不属于基本数据类型,但是可以和使用基本数据类型一样直接赋值,也可以像引用数据类型一样,使用关键字new进行实例化。
String类型对象的实例化有两种方式:
–静态方式(常用):直接给变量赋值,如:String s1 = “abc”; String s2 = “abc”;
–动态方式:使用new运算符动态的给变量赋值,如:String s3 = new String(“abc”); String s4 = new String(“abc”);
那么这两种方式创建的字符串是同一个字符串对象吗?答案是否定的,这两种方式创建的字符串对象是有区别的。
区别在于:使用静态方式创建的字符串,如果前后两次创建的字符串内容相同,则在方法区的常量池中只会产生一个字符串对象,即两个引用指向同一块地址。而使用动态方式创建的字符串,不管前后两次创建的字符串内容是否相同,每创建一次,都会在堆内存中会产生出不同的对象,即两个引用指向不同的地址。
对于上面采用静态方式创建的字符串s1、s2与采用动态方式创建字符串s3和s4其内存空间分配方式示意如图1-3所示。
图1-3 字符串动态创建与静态创建示意图
动态创建String对象时需要用到构造方法,String类的常用的构造方法如下,更多构造方法请直接查阅Java API。
l 初始化一个新创建的String 对象,它表示一个空字符序列。
String 变量名 = new String() ;
初始化一个新创建的String对象,表示一个空字符串(" ");注意空字符串与null的区别,空字符串表示String对象的内容为空,而null表示String类的变量不指向任何的String对象。
l 初始化一个新创建的 String对象,表示一个与该参数相同的字符序列。
String 变量名 = new String (String value) ;
l String(char chars[]) 使用一个字符数组创建一个String对象。
另外String在使用的时候不需要用import语句导入。
注意,当使用"+“运算符进行运算时,如果参与运算的有字符串,则”+“的含义为进行字符串连接,当参与运算的没有字符串时,则”+"的含义为算术运算符加号。例如:
String str1 = "hello ";
String str2 = "world";
System.out.println (str1 + str2); //输出结果为"hello world"
System.out.println(5 + 6 + 'A'); //输出结果为76
System.out.println(5 + 6 + "A"); //输出结果为11A
System.out.println(5 + "A" +6); //输出结果为5A6
1.4.2 String 对象的不可变性
任何一个String对象在创建之后都不能对它的内容作出任何改变。对于连接、获得子串和改变大小写等操作,如果返回值同原字符串不同,实际上是产生了一个新的String对象,在程序的任何地方,相同的字符串字面常量都是同一个对象,下面的代码会改变字符串s的内容吗?
String s = “Java”;
s = “HTML”;
答案是不会。第一条语句创建了一个内容为"Java"的String对象,并将其引用赋值给s。第二条语句创建了一个内容为"HTML"的新String对象,并将其引用赋值给s。赋值后第一个String对象仍然存在,但是不能再访问它,因为变量s现在指向了新的对象HTML,如图1-4所示。
图1-4字符串是不可改变的,一旦创建,它们的内容不能修改
因为字符串在程序设计中是不可改变的,但同时又会被频繁地使用,所以Java虚拟机为了提高效率并节省内存,对具有相同字符串序列的字符串直接使用同一个实例。例如下面的语句:
String str1 = "hello";
String str2 = new String("hello");
String str3 = "hello";
System.out.println(str1==str2);
System.out.println(str1==str3);
程序运行结果:
false
true
1.4.3 字符串的比较
String类提供了多种对字符串比较的方法,具体如表1-6所示。
例如,下面的语句先显示true,然后显示false.
String s1 = new String("welcome to Java");
String s2 = "welcome to Java";
String s3 = "welcome to C++";
System.out.println(s1.equals(s2)); //true
System.out.println(s1.equals(s3));//false
【例1-5】字符串equals方法练习
String s1 = "abc";
String s2 = new String("abc");
String s3 = new String("abc");
String s4 = "abc";
System.out.println(s1.equals(s2)); //true
System.out.println(s1.equals(s4)); // true
System.out.println(s2.equals(s3)); //true
程序分析:equals方法用来比较两个字符串是否相等。
【例1-6】重写equals()方法,判断不同的点,是否是坐标系上的同一点。
//点类
public class Point {
private int x; //x坐标
private int y;//y坐标
public Point(int x,int y){
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
@Override
public String toString() {
return "("+x+","+y+")";
}
//如果x,y的值相同,就认为是坐标上的同一点
public boolean equals(Object obj) {
if(obj == null){
return false;
}
if(this == obj){
return true;
}
if(!(obj instanceof Point)){
return false;
} else {
Point p = (Point)obj;
if(p.x==x&&p.y==y){
return true;
} else {
return false;
}
}
}
}
//测试类
public class TestPoint {
public static void main(String[] args) {
Point p1 = new Point(55,66);
Point p2 = new Point(55,66);
Point p3 = new Point(22,33);
System.out.println(p1.equals(p2));
System.out.println(p1==p2);
System.out.println(p1.equals(p3));
System.out.println(p1==p3);
}
}
程序运行结果:
true
false
false
false
程序分析:上例测试中main()方法中实例化了3个点,分别使用equals方法与进行比较,因为Point类覆盖了父类的equals()方法,该方法判断如果两个Point对象的x坐标和y坐标相等,则返回true,所以第1行输出为true,""运算符比较引用数据类型时,判断两个引用是否指向同一个对象,p1,p2,p3都分别是不同的对象,所以第2行和第4行输出为false。
compareTo方法也可以用来对字符串进行比较。方法如下:
s1.compareTo(s2)
如果s1与s2相等,那么该方法返回值为0;如果按字典序(即以统一码的顺序)s1小于s2,那么方法返回值小于0;如果按字典序s1大于s2,方法返回值大于0。
方法compareTo返回的实际值是依据s1和s2从左到右数第一个不同字符之间的距离得出的,例如,假设s1为“abc”,s2为“abg”,那么s1.compareTo(s2)返回-4。首先比较的是s1与s2中第一个位置的字符(a与a)。因为它们相等,所以比较第二个位置的两个字符(b与b)。因为它们也相等,所以比较第三个位置的两个字符(c与g)。由于字符c比字符g小4,所以比较之后返回-4。如果使用像>、>=、<或<=这样的比较运算符比较两个字符串,就会发生错误,替代的方法就是使用s1.compareTo(s2)来进行比较。
如果两个字符串相等,equals方法返回true;如果不相等,方法返回false。compareTo方法会根据一个字符串是否等于、大于或小于另一个字符串,分别返回0、正整数或负整数。
字符串不是数组,但是字符串可以转换成数组,反之亦然。
(1)与字符数组之间的转换
为了将字符串转换成一个字符数组,可以使用toCharArray方法。例如,下述语句将字符串"Java "转换成一个字符数组:
Char[] chars= “Java”.toCharArray();
因此chars[0]是’J’,chars[1]是’a’,chars[2]是’v’,chars[3]是’a’。
还可以使用方法getChars(int srcBegin,int srcEnd,char[]dst,int dstBegin)将下标从srcBegin到srcEnd-1的子串复制到字符数组dst中下标从dstBegin开始的位置。例如,下面的代码功能是把字符串"CS3720"中下标从2到6-1的子串"3720"复制到字符数组dst中,赋值时下标从4开始的位置:
Char[] dst={‘j’,‘a’,‘v’,‘a’,‘1’,‘3’,‘0’,‘1’};
“CS3720”.getChars(2,6,dst,4);
这样,dst就变成了{‘j’,‘a’,‘v’,‘a’,‘3’,‘7’,‘2’,‘0’}。
为了将一个字符数组转换成字符串,应该使用构造方法String(char[])或者方法valueOf(char[])。例如,下面的语句使用String构造方法把一个字符数组构造成一个字符串:
String str = new String(new char[]{‘j’,‘a’,‘v’,‘a’});
下面的语句使用valueOf方法把一个字符数组构造成一个字符串:
String str = String.valueOf(new char[]{‘j’,‘a’,‘v’,‘a’});
(2)与字节数组之间的转换
Java中能够把字符串转换为字节数组,有3种形式。
形式1:public byte[] getBytes()
方法定义:以默认编码把字符串转换为字节数组
形式2:public byte[] getBytes(Charset charset)
方法定义:按照指定的字符集把字符串转换为字节数组
形式3:public byte[] getBytes(String charsetName)
方法定义:按照指定的字符集把字符串转换为字节数组
【例1-7】 使用平台的默认字符集,统计一个字符串所占用的字节数。
public class TestStringByte{
public static void main(String[] args) {
String str = "Java语言程序设计";
byte bytes[] = str.getBytes();
System.out.println(bytes.length);
}
}
程序运行结果:
16
程序分析:通过getBytes()方法把字符串转换成字节数组,字节数组的长度就是字符串所占的字节数。
【例1-8】通过字节数组创建字符串对象
public class TestStringCharset {
public static void main(String[] args) {
byte[] bName = new byte[10];
String name1 = "张三";
try{
bName = name1.getBytes("utf-8"); //这种编码方式一个中文占三个字节
String name2 = new String(bName,"utf-8");
System.out.println("name2="+name2);
for(int i = 0;i< bName.length;i++){
System.out.print(bname[i]);
}
}catch (UnsupportedEncodingException e){
e.printStackTrace();
}
}
}
程序运行结果:
name2=张三
-27-68-96-28-72-119
程序分析:getBytes()是将一个字符串转化为一个字节数组。String的getBytes()方法是得到一个系统默认的编码格式的字节数组。将一个String类型的字符串中包含的字符转换成byte类型并且存入一个byte数组中。在Java中的所有数据底层都是字节,字节数据可以存入到byte数组。存储字符数据时(字符串就是字符数据),会先进行查表,然后将查询的结果写入设备,读取时也是先查表,把查到的内容打印到显示设备上,getBytes()是使用默认的字符集进行转换,getBytes(“utf-8”)是使用UTF-8编码表进行转换。例如: byte [] b_Uf8 = “中国”.getBytes(“UTF-8”);//获得字节数组 String s_Utf8 = new String(b_utf8,“UTF-8”);//使用指定的UTF-8编码来将byte[]解析成字符串。
(3)String类与数组的转换示意图
字符串可以和字节数组与字符数组之间互相转换,
其转换过程如图1-5所示
String的一些常用方法如表1-7所示。
表1-7 String类的常用方法
下面对常用的一些方法进行详细说明,为了便于说明,方法中使用的示例字符串为:str=“this is a test!”;
(1)求长度
方法定义:public int length() 。
方法描述:获取字符串中的字符的个数。
例如:
str.length()
结果:
15
(2)获取字符串中的字符
方法定义:public char charAt(int index)。
方法描述:获取字符串中的第index个字符,从0开始。
例如:
str.charAt(3)
结果:
s
注意:是第4个字符。
【例1-9】 统计一个字符串中字符e出现的次数。
public class TestString {
public static void main(String[] args) {
String s = "abecedkjkacedjkdseddklj";
int num = 0;
for(int i=0; i<s.length(); i++){
char c = s.charAt(i);
if(c == 'e'){
num++;
}
}
System.out.println("该字符串中字符e出现"+num+"次");
}
}
ate类不支持国际化。现在我们更应该多使用Calendar类来实现日期和时间字段之间转换,使用DateFormat类来格式化和分析日期字符串,Date中的相应方法已废弃。
【例1-17】Date类常用方法练习
public class TestDate {
public static void main(String[] args) {
Date now = new Date();//获取当前系统时间
System.out.println(now); //获取1970年1月1日1000毫秒之后的时间
Date d1 = new Date(1000);
System.out.println(now.after(d1));
System.out.println(now.before(d1));
System.out.println(now.compareTo(d1));
}
}
程序运行结果:
true
false
1
程序分析:本程序主要练习日期类的几个常用方法,这几个方法的详细说明请参见表1-10。