8.1.1 包装类基本知识
我们经常用到的基本数据类型不是对象,但是我们在实际应用中经常需要将基本数据转化成对象,以便于操作。
比如:将基本数据类型存储到Object[]数组或集合中的操作等等。
为了解决这个不足,Java在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(Wrapper Class)。
包装类均位于java.lang包,八种包装类和基本数据类型的对应关系如表8-1所示:
int包装类是Integer
char包装类是Character类
其它六个类的类名和基本数据类型一致,类名的第一个字母大写。
除了Character和Boolean以外,其他包装类的都是“数字型”,“数字型”都是java.lang.Number的子类。
Number类是抽象类,因此它的抽象方法,所有子类都需要提供实现。
Number类提供了抽象方法:intValue()、longValue()、floatValue()、doubleValue(),
所有的“数字型”包装类都可以互相转型。
包装类
public class TestWrapperClass {
public static void main(String[] args) {
Integer i = new Integer(10);
Integer j = new Integer(50);
}
}
8.1.2包装类的用途
对于包装类来说,这些类的用途主要包含两种:
1. 作为和基本数据类型对应的类型存在,方便涉及到对象的操作,如Object[]、集合等的操作。
2. 包含每种基本数据类型的相关属性如最大值、最小值等,以及相关的操作方法(这些操作方法的作用是在基本数据类型、包装类对象、字符串之间提供相互之间的转化!)。
包装类的使用
public class TestWrappedClass {
public static void main(String[] args) {
//基本数据类型转成包装类对象
Integer a = new Integer(3);
Integer b = Integer.valueOf(30);
//把包装类对象转成基本数据类型
int c = b.intValue();
double d = b.doubleValue();
//把字符串转成包装类对象
Integer e = new Integer("9999");
Integer f = Integer.parseInt("999888");
//把包装类对象转成字符串
String str = f.toString();
//常见int类型相关的常量
System.out.println("int类型最大的整数:"+Integer.MAX_VALUE);
}
}
8.1.3 自动装箱和拆箱
自动装箱和拆箱就是将基本数据类型和包装类之间进行自动的互相转换。
Java引入了自动装箱(autoboxing)/拆箱(unboxing)。
自动装箱:基本类型的数据处于需要对象的环境中时,会自动转为“对象”。
自动拆箱:每当需要一个值时,对象会自动转成基本数据类型,无需再去显式调用intValue()、doubleValue()等转型方法。
自动装箱过程是通过调用包装类的valueOf()方法实现的;
自动拆箱过程是通过调用包装类的xxxValue()方法实现的(如intValue()、doubleValue())。
自动装箱和自动拆箱,包装类空指针异常问题
public class TestAutoBox {
public static void main(String[] args) {
//自动装箱
Integer i = 100;//Integer i = Integer.valueOf(100);
//自动拆箱
int j = i;//int b = a.intValue();
//空指针异常问题
Integer a = null;
int b = i;//int b = i.intValue();//抛空指针异常
//i没有指向任何对象的实体,不能操作intValue()方法,出现错误
}
}
8.1.4 包装类的缓存问题
8.2.1 String类
将String对象称为“不可变对象”,对象内部的成员变量的值无法再改变。
substring()是对字符串的截取操作,但本质是读取原字符串内容生成了新的字符串。
String测试代码
public class TestString1 {
public static void main(String[] args) {
String s1 = new String("abcdef");
String s2 = s1.substring(2, 4);
// 打印:ab199863
System.out.println(Integer.toHexString(s1.hashCode()));
// 打印:c61, 显然s1和s2不是同一个对象
System.out.println(Integer.toHexString(s2.hashCode()));
}
}
字符串拼接时的优化
public class TestString{
public static void main(String[] args) {
//编译器做了优化,直接在编译的时候将字符串进行拼接
String str1 = "hello" + " java";//相当于str1 = "hello java";
String str2 = "hello java";
System.out.println(str1 == str2);//true
String str3 = "hello";
String str4 = " java";
//编译的时候不知道变量中存储的是什么,所以没办法在编译的时候优化
String str5 = str3 + str4;
System.out.println(str2 == str5);//false
//做字符串比较时,使用equals
System.out.println(str2.equals(str5));//true
}
}
8.2.2 StringBuffer和StringBuilder
StringBuffer和StringBuilder非常类似,均代表可变的字符序列,称之为“可变字符序列”。
1.String:不可变字符序列;
2.StringBuilder:线程不安全,效率高,推荐使用;
3.StringBuffer:线程安全,效率低。
public class TestStringBuilder {
public static void main(String[] args) {
String str;
StringBuilder sb = new StringBuilder("abcdefg");
System.out.println(Integer.toHexString(sb.hashCode()));//1b6d3586
System.out.println(sb);//abcdefg
sb.setCharAt(2,'M');
System.out.println(Integer.toHexString(sb.hashCode()));//1b6d3586
System.out.println(sb);//abMdefg
}
}
常用方法列表
1.方法 public String toString() 返回此序列中数据的字符串表示形式。
2.append(…)方法,为该StringBuilder 对象添加字符序列,仍然返回自身对象。
3.reverse(),用于将字符序列逆序,仍然返回自身对象。
4.setCharAt(int index),替换此序列指定位置上的char,仍然返回自身对象。
5.insert(…)方法可以为该StringBuilder 对象在指定位置插入字符序列,仍然返回自身对象。
6.delete(int start,int end),可以删除从start开始到end-1为止的一段字符序列,仍然返回自身对象。
public class TestStringBuilder2 {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
for(int i=0;i<26;i++){
char temp = (char)('a'+i);
sb.append(temp);
}
//转换成String输出
System.out.println(sb.toString());
System.out.println(sb);//abcdefghijklmnopqrstuvwxyz
//逆序
sb.reverse();
System.out.println(sb);//zyxwvutsrqponmlkjihgfedcba
//替换
sb.setCharAt(3,'高');;
System.out.println(sb);//zyx高vutsrqponmlkjihgfedcba
//插入
sb.insert(0,'我');
System.out.println(sb);//我zyx高vutsrqponmlkjihgfedcba
//删除
sb.delete(4,7);
System.out.println(sb);//我zyxtsrqponmlkjihgfedcba
}
}
8.2.3 不可变和可变字符序列使用陷阱
String和StringBuilder在频繁字符串修改时效率测试
public class TestStringBuilder3 {
public static void main(String[] args) {
/**使用String进行字符串的拼接*/
String str8 = "";
//本质上使用StringBuilder拼接, 但是每次循环都会生成一个StringBuilder对象
long num1 = Runtime.getRuntime().freeMemory();//获取系统剩余内存空间
long time1 = System.currentTimeMillis();//获取系统的当前时间
for (int i = 0; i < 5000; i++) {
str8 = str8 + i;//相当于产生了10000个对象
}
long num2 = Runtime.getRuntime().freeMemory();
long time2 = System.currentTimeMillis();
System.out.println("String占用内存 : " + (num1 - num2));//String占用内存:6110984
System.out.println("String占用时间 : " + (time2 - time1));//String占用时间:84
/**使用StringBuilder进行字符串的拼接*/
StringBuilder sb1 = new StringBuilder("");
long num3 = Runtime.getRuntime().freeMemory();
long time3 = System.currentTimeMillis();
for (int i = 0; i < 5000; i++) {
sb1.append(i);
}
long num4 = Runtime.getRuntime().freeMemory();
long time4 = System.currentTimeMillis();
System.out.println("StringBuilder占用内存 : " + (num3 - num4));//StringBuilder占用内存:0
System.out.println("StringBuilder占用时间 : " + (time4 - time3));//StringBuilder占用时间:1
}
}
8.3 时间处理相关类
8.3.1 Date时间类(java.util.Date)
在标准Java类库中包含一个Date类。它的对象表示一个特定的瞬间,精确到毫秒。
1.Date() 分配一个Date对象,并初始化此对象为系统当前的日期和时间,可以精确到毫秒。
8.3.2 DateFormat类和SimpleDateFormat类
8.3.3 Calendar日历类
Calendar 类是一个抽象类,为我们提供了关于日期计算的相关功能,比如:年、月、日、时、分、秒的展示和计算。
注意月份的表示,一月是0,二月是1,以此类推,12月是11。
8.4 Math类
java.lang.Math提供了一系列静态方法用于科学计算;其方法的参数和返回值类型一般为double型。
8.5.1 File类的基本用法
文件的创建和访问属性
文件的创建
user.dir就是本项目的目录
public class TestFile1 {
public static void main(String[] args) throws IOException {
//File f = new File("d:/a.txt");//绝对路径
File f = new File("d:\\a.txt");//这两句作用相同
System.out.println(f);//d:\a.txt
f.renameTo(new File("d:a.txt"));
System.out.println(System.getProperty("user.dir"));//D:\JavaTest\idea08
File f2 = new File("gg.txt");//相对路径
//f2.createNewFile();//创建文件
}
}
File类访问属性的方法列表
import java.io.File;
import java.util.Date;
public class TestFile2 {
public static void main(String[] args) throws Exception {
File f = new File("d:/b.txt");
System.out.println("File是否存在:"+f.exists());
System.out.println("File是否是目录:"+f.isDirectory());
System.out.println("File是否是文件:"+f.isFile());
System.out.println("File最后修改时间:"+new Date(f.lastModified()));
System.out.println("File的大小:"+f.length());
System.out.println("File的文件名:"+f.getName());
System.out.println("File的目录路径:"+f.getPath());
//绝对路径
System.out.println("File的目录路径:"+f2.getAbsolutePath());
}
}
File类创建文件或目录的方法列表
mkdir创建目录
public class TestFile3 {
public static void main(String[] args) throws Exception {
File f = new File("d:/c.txt");
f.createNewFile(); // 会在d盘下面生成c.txt文件
f.delete(); // 将该文件或目录从硬盘上删除
File f2 = new File("d:/电影/华语/大陆");
boolean flag = f2.mkdir(); //目录结构中有一个不存在,则不会创建整个目录树
System.out.println(flag);//创建失败false
}
}
mkdirs创建目录
public class TestFile4 {
public static void main(String[] args) throws Exception {
File f = new File("d:/c.txt");
f.createNewFile(); // 会在d盘下面生成c.txt文件
f.delete(); // 将该文件或目录从硬盘上删除
File f2 = new File("d:/电影/华语/大陆");
boolean flag = f2.mkdirs();//目录结构中有一个不存在也没关系;创建整个目录树
System.out.println(flag);//创建成功true
}
}
8.5.2 递归遍历目录结构和树状展现
8.6 枚举
public class TestEnum {
public static void main(String[] args) {
System.out.println(Season.SPRING);
Season a = Season.AUTUMN;
switch(a){
case SPRING:
System.out.println("春天来了,播种的季节");
break;
case SUMMER:
System.out.println("夏天来了,游泳的季节");
break;
case AUTUMN:
System.out.println("秋天来了,收获的季节");
break;
case WINNER:
System.out.println("冬天来了,冬眠的季节");
break;
}
}
}
enum Season{
SPRING,SUMMER,AUTUMN,WINNER
}
enum Week{
星期一,星期二,星期三,星期四,星期五,星期六,星期日
}