JAVA 常用类知识整理

常用类

一、包装类

Java 是面向对象的语言,但并不是“纯面向对象”的,因为我们经常用到的基本数据类型就不是对象。但是我们在实际应用中经常需要将基本数据转化成对象,以便于操作。比如:将基本数据类型存储到 Object[] 数组或集合中的操作等等。

​ 为了解决这个不足,Java 在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类 (Wrapper Class)。

基本数据类型 包装类
byte Byte
boolean Boolean
short Short
char Character
int Integer
long Long
float Float
double Double

在这八个类名中,除了 Integer 和 Character 类以外,其它六个类的类名和基本数据类型一致,只是类名的第一个字母大写而已。

​ 在这八个类中,除了 Character 和 Boolean 以外,其他的都是“数字型”,“数字型”都是 java.lang.Number 的子类。Number 类是抽象类,因此它的抽象方法,所有子类都需要提供实现。Number 类提供了抽象方法:intValue()、longValue()、floatValue()、doubleValue(),意味着所有的“数字型”包装类都可以互相转型。

public class WrapperClassTest {
    public static void main(String[] args) {
        Integer i = new Integer(10);
        Integer j = new Integer(50);
    }
}

二、包装类的用途

对于包装类来说,这些类的用途主要包含两种:

​ 1. 作为和基本数据类型对应的类型存在,方便涉及到对象的操作,如 Object[]、集合等的操作。

  1. 包含每种基本数据类型的相关属性如最大值、最小值等,以及相关的操作方法 (这些操作方法的作用是在基本数据类型、包装类对象、字符串之间提供相互之间的转化!)。
public class Test {
    /** 测试Integer的用法,其他包装类与Integer类似 */
    void testInteger() {
        // 基本类型转化成Integer对象
        Integer int1 = new Integer(10);
        Integer int2 = Integer.valueOf(20); // 官方推荐这种写法
        // Integer对象转化成int
        int a = int1.intValue();
        // 字符串转化成Integer对象
        Integer int3 = Integer.parseInt("334");
        Integer int4 = new Integer("999");
        // Integer对象转化成字符串
        String str1 = int3.toString();
        // 一些常见int类型相关的常量
        System.out.println("int能表示的最大整数:" + Integer.MAX_VALUE); 
    }
    public static void main(String[] args) {
        Test test  = new Test();
        test.testInteger();
    }
}

三、自动装箱和拆箱

自动装箱和拆箱就是将基本数据类型和包装类之间进行自动的互相转换。JDK1.5 后,Java 引入了自动装箱 (autoboxing)/ 拆箱 (unboxing)。

自动装箱:

​ 基本类型的数据处于需要对象的环境中时,会自动转为“对象”。

​ 我们以 Integer 为例:在 JDK1.5 以前,这样的代码 Integer i = 5 是错误的,必须要通过 Integer i = new Integer(5) 这样的语句来实现基本数据类型转换成包装类的过程; 而在 JDK1.5 以后,Java 提供了自动装箱的功能,因此只需 Integer i = 5 这样的语句就能实现基本数据类型转换成包装类,这是因为 JVM 为我们执行了 Integer i = Integer.valueOf(5) 这样的操作,这就是 Java 的自动装箱。

自动拆箱:

​ 每当需要一个值时,对象会自动转成基本数据类型,没必要再去显式调用 intValue()、doubleValue() 等转型方法。

​ 如 Integer i = 5;int j = i; 这样的过程就是自动拆箱。

​ 我们可以用一句话总结自动装箱 / 拆箱:

​ 自动装箱过程是通过调用包装类的 valueOf()方法实现的,而自动拆箱过程是通过调用包装类的 xxxValue()方法实现的 (xxx 代表对应的基本数据类型,如 intValue()、doubleValue()等)。

​ 自动装箱与拆箱的功能事实上是编译器来帮的忙,编译器在编译时依据您所编写的语法,决定是否进行装箱或拆箱动作。

自动装箱

Integer i = 100;//自动装箱
//相当于编译器自动为您作以下的语法编译:
Integer i = Integer.valueOf(100);//调用的是valueOf(100),而不是new Integer(100)

自动拆箱

Integer i = 100;
int j = i;//自动拆箱
//相当于编译器自动为您作以下的语法编译:
int j = i.intValue();
  • 自动装箱调用的是 valueOf()方法,而不是 new Integer() 方法。
  • 自动拆箱调用的 xxxValue() 方法。
  • 包装类在自动装箱时为了提高效率,对于 -128~127 之间的值会进行缓存处理。超过范围后,对象之间不能再使用 == 进行数值的比较,而是使用 equals 方法。

四、String 类

  String 类对象代表不可变的 Unicode 字符序列,因此我们可以将 String 对象称为“不可变对象”。

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 TestString2 {
    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
    }
}

​ 1. String 类的下述方法能创建并返回一个新的 String 对象: concat()、 replace()、substring()、 toLowerCase()、 toUpperCase()、trim()。

​ 2. 提供查找功能的有关方法: endsWith()、 startsWith()、 indexOf()、lastIndexOf()。

​ 3. 提供比较功能的方法: equals()、equalsIgnoreCase()、compareTo()。

  1. 其它方法: charAt()、length()。

StringBuffer 和 StringBuilder

StringBuffer 和 StringBuilder 非常类似,均代表可变的字符序列。 这两个类都是抽象类 AbstractStringBuilder 的子类,方法几乎一模一样。

StringBuilder 和 StringBuffer 称之为“可变字符序列”。那两者有什么区别呢?

​ 1. StringBuffer JDK1.0 版本提供的类,线程安全,做线程同步检查, 效率较低。

​ 2. StringBuilder JDK1.5 版本提供的类,线程不安全,不做线程同步检查,因此效率较高。 建议采用该类。

· 常用方法列表:

​ 1. 重载的 public StringBuilder append(…) 方法

​ 可以为该 StringBuilder 对象添加字符序列,仍然返回自身对象。

​ 2. 方法 public StringBuilder delete(int start,int end)

​ 可以删除从 start 开始到 end-1 为止的一段字符序列,仍然返回自身对象。

​ 3. 方法 public StringBuilder deleteCharAt(int index)

​ 移除此序列指定位置上的 char,仍然返回自身对象。

​ 4. 重载的 public StringBuilder insert(…) 方法

​ 可以为该 StringBuilder 对象在指定位置插入字符序列,仍然返回自身对象。

​ 5. 方法 public StringBuilder reverse()

​ 用于将字符序列逆序,仍然返回自身对象。

​ 6. 方法 public String toString() 返回此序列中数据的字符串表示形式。

  1. 和 String 类含义类似的方法:
public int indexOf(String str)
public int indexOf(String str,int fromIndex)
public String substring(int start)
public String substring(int start,int end)
public int length() 
char charAt(int index)

StringBuffer/StringBuilder 基本用法

public class TestStringBufferAndBuilder 1{
    public static void main(String[] args) {
        /**StringBuilder*/
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 7; i++) {
            sb.append((char) ('a' + i));//追加单个字符
        }
        System.out.println(sb.toString());//转换成String输出
        sb.append(", I can sing my abc!");//追加字符串
        System.out.println(sb.toString());
        /**StringBuffer*/
        StringBuffer sb2 = new StringBuffer("中华人民共和国");
        sb2.insert(0, "爱").insert(0, "我");//插入字符串
        System.out.println(sb2);
        sb2.delete(0, 2);//删除子字符串
        System.out.println(sb2);
        sb2.deleteCharAt(0).deleteCharAt(0);//删除某个字符
        System.out.println(sb2.charAt(0));//获取某个字符
        System.out.println(sb2.reverse());//字符串逆序
    }
}

 执行结果 :

abcdefg
abcdefg, I can sing my abc!
我爱中华人民共和国
中华人民共和国
人
国和共民人

· String 使用的陷阱

​ String 一经初始化后,就不会再改变其内容了。对 String 字符串的操作实际上是对其副本 (原始拷贝) 的操作,原来的字符串一点都没有改变。比如:

​ String s =“a”; 创建了一个字符串

​ s = s+“b”; 实际上原来的 "a" 字符串对象已经丢弃了,现在又产生了另一个字符串 s+“b”(也就是 "ab")。 如果多次执行这些改变串内容的操作,会导致大量副本字符串对象存留在内存中,降低效率。如果这样的操作放到循环中,会极大影响程序的时间和空间性能,甚至会造成服务器的崩溃。

​ 相反,StringBuilder 和 StringBuffer 类是对原字符串本身操作的,可以对字符串进行修改而不产生副本拷贝或者产生少量的副本。因此可以在循环中使用。

五、时间处理相关类

在计算机世界,我们把 1970 年 1 月 1 日 00:00:00 定为基准时间,每个度量单位是毫秒。

我们用 long 类型的变量来表示时间,从基准时间往前几亿年,往后几亿年都能表示。如果想获得现在时刻的“时刻数值”,可以使用:

long now = System.currentTimeMillis();

Date 时间类 (java.util.Date)

在标准 Java 类库中包含一个 Date 类。它的对象表示一个特定的瞬间,精确到毫秒。

​ 1. Date()分配一个 Date 对象,并初始化此对象为系统当前的日期和时间,可以精确到毫秒)。

  1. Date(long date) 分配 Date 对象并初始化此对象,以表示自从标准基准时间 (称为“历元(epoch)”,即 1970 年 1 月 1 日 00:00:00 GMT) 以来的指定毫秒数。

​ 3. boolean after(Date when) 测试此日期是否在指定日期之后。

​ 4. booleanbefore(Date when) 测试此日期是否在指定日期之前。

​ 5. boolean equals(Object obj) 比较两个日期的相等性。

​ 6. long getTime() 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。

​ 7. String toString() 把此 Date 对象转换为以下形式的 String:

​ dow mon dd hh🇲🇲ss zzz yyyy 其中: dow 是一周中的某一天 (Sun、 Mon、Tue、Wed、 Thu、 Fri、 Sat)。

DateFormat 类和 SimpleDateFormat 类

·DateFormat 类的作用

​ 把时间对象转化成指定格式的字符串。反之,把指定格式的字符串转化成时间对象。

​ DateFormat 是一个抽象类,一般使用它的的子类 SimpleDateFormat 类来实现。

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TestDateFormat {
    public static void main(String[] args) throws ParseException {
        // new出SimpleDateFormat对象
        SimpleDateFormat s1 = new SimpleDateFormat("yyyy-MM-dd hh🇲🇲ss");
        SimpleDateFormat s2 = new SimpleDateFormat("yyyy-MM-dd");
        // 将时间对象转换成字符串
        String daytime = s1.format(new Date());
        System.out.println(daytime);
        System.out.println(s2.format(new Date()));
        System.out.println(new SimpleDateFormat("hh🇲🇲ss").format(new Date()));
        // 将符合指定格式的字符串转成成时间对象.字符串格式需要和指定格式一致。
        String time = "2007-10-7";
        Date date = s2.parse(time);
        System.out.println("date1: " + date);
        time = "2007-10-7 20:15:30";
        date = s1.parse(time);
        System.out.println("date2: " + date);
    }
}

执行结果:

2019-03-28 08:29:32
2019-03-28
08:29:32
date1: Sun Oct 07 00:00:00 GMT+08:00 2007
date2: Sun Oct 07 20:15:30 GMT+08:00 2007

Calendar 日历类

Calendar 类是一个抽象类,为我们提供了关于日期计算的相关功能,比如:年、月、日、时、分、秒的展示和计算。

​ GregorianCalendar 是 Calendar 的一个具体子类,提供了世界上大多数国家 / 地区使用的标准日历系统。

雷区

​ 注意月份的表示,一月是 0,二月是 1,以此类推,12 月是 11。 因为大多数人习惯于使用单词而不是使用数字来表示月份,这样程序也许更易读,父类 Calendar 使用常量来表示月份:JANUARY、FEBRUARY 等等。

import java.util.*;
public class TestCalendar {
    public static void main(String[] args) {
        // 得到相关日期元素
        GregorianCalendar calendar = new GregorianCalendar(2999, 10, 9, 22, 10, 50);
        int year = calendar.get(Calendar.YEAR); // 打印:1999
        int month = calendar.get(Calendar.MONTH); // 打印:10
        int day = calendar.get(Calendar.DAY_OF_MONTH); // 打印:9
        int day2 = calendar.get(Calendar.DATE); // 打印:9
        // 日:Calendar.DATE和Calendar.DAY_OF_MONTH同义
        int date = calendar.get(Calendar.DAY_OF_WEEK); // 打印:3
        // 星期几 这里是:1-7.周日是1,周一是2,。。。周六是7
        System.out.println(year);
        System.out.println(month);
        System.out.println(day);
        System.out.println(day2);
        System.out.println(date);
        // 设置日期
        GregorianCalendar calendar2 = new GregorianCalendar();
        calendar2.set(Calendar.YEAR, 2999);
        calendar2.set(Calendar.MONTH, Calendar.FEBRUARY); // 月份数:0-11
        calendar2.set(Calendar.DATE, 3);
        calendar2.set(Calendar.HOUR_OF_DAY, 10);
        calendar2.set(Calendar.MINUTE, 20);
        calendar2.set(Calendar.SECOND, 23);
        printCalendar(calendar2);
        // 日期计算
        GregorianCalendar calendar3 = new GregorianCalendar(2999, 10, 9, 22, 10, 50);
        calendar3.add(Calendar.MONTH, -7); // 月份减7
        calendar3.add(Calendar.DATE, 7); // 增加7天
        printCalendar(calendar3);
        // 日历对象和时间对象转化
        Date d = calendar3.getTime();
        GregorianCalendar calendar4 = new GregorianCalendar();
        calendar4.setTime(new Date());
        long g = System.currentTimeMillis();
    }
    static void printCalendar(Calendar calendar) {
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int date = calendar.get(Calendar.DAY_OF_WEEK) - 1; // 星期几
        String week = "" + ((date == 0) ? "日" : date);
        int hour = calendar.get(Calendar.HOUR);
        int minute = calendar.get(Calendar.MINUTE);
        int second = calendar.get(Calendar.SECOND);
        System.out.printf("%d年%d月%d日,星期%s %d:%d:%d\n", year, month, day,  
                        week, hour, minute, second);
    }
}

六、Math 类

Math 类的常用方法:

​ 1. abs 绝对值

​ 2. acos,asin,atan,cos,sin,tan 三角函数

​ 3. sqrt 平方根

​ 4. pow(double a, double b) a 的 b 次幂

​ 5. max(double a, double b) 取大值

​ 6. min(double a, double b) 取小值

​ 7. ceil(double a) 大于 a 的最小整数

​ 8. floor(double a) 小于 a 的最大整数

​ 9. random() 返回 0.0 到 1.0 的随机数

​ 10. long round(double a) double 型的数据 a 转换为 long 型 (四舍五入)

​ 11. toDegrees(double angrad) 弧度 -> 角度

​ 12. toRadians(double angdeg) 角度 -> 弧度

import java.util.Random;
public class TestRandom {
	public static void main(String[] args) {
		Random rand = new Random();
		//随机生成[0,1)之间的double类型的数据
		System.out.println(rand.nextDouble());
		//随机生成int类型允许范围之内的整型数据
		System.out.println(rand.nextInt());
		//随机生成[0,1)之间的float类型的数据
		System.out.println(rand.nextFloat());
		//随机生成false或者true
		System.out.println(rand.nextBoolean());
		//随机生成[0,10)之间的int类型的数据
		System.out.print(rand.nextInt(10));
		//随机生成[20,30)之间的int类型的数据
		System.out.print(20 + rand.nextInt(10));
		//随机生成[20,30)之间的int类型的数据(此种方法计算较为复杂)
		System.out.print(20 + (int) (rand.nextDouble() * 10));
	}
}

执行结果:

0.5847664737337768
1650245478
0.11396235
true
72128

七、File 类的基本用法

 java.io.File 类:代表文件和目录。 在开发中,读取文件、生成文件、删除文件、修改文件的属性时经常会用到本类。

File 类的常见构造方法:public File(String pathname)

​ 以 pathname 为路径创建 File 对象,如果 pathname 是相对路径,则默认的当前路径在系统属性 user.dir 中存储

import java.io.File;
public class TestFile1 {
    public static void main(String[] args) throws Exception {
        System.out.println(System.getProperty("user.dir"));
        File f = new File("a.txt"); //相对路径:默认放到user.dir目录下面
        f.createNewFile();//创建文件
        File f2 = new File("d:/b.txt");//绝对路径
        f2.createNewFile();
    }
}

在 eclipse 项目开发中,user.dir 就是本项目的目录。因此,执行完毕后,在本项目和 D 盘下都生成了新的文件 (如果是 eclipse 下,一定按 F5 刷新目录结构才能看到新文件)。

通过 File 对象可以访问文件的属性:

方法 说明
public boolean exists 判断 File 是否存在
public boolean isDirectory() 判断 File 是否是目录
public boolean isFile() 判断 File 是否是文件
public long lastModified() 返回 File 最后修改时间
public long length() 返回 File 大小
public String getName() 返回文件名
public String getPath() 返回文件的目录路径
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());
    }
}

执行结果:

File是否存在:false
File是否是目录:false
File是否是文件:false
File最后修改时间:Thu Jan 01 08:00:00 GMT+08:00 1970
File的大小:0
File的文件名:b.txt
File的目录路径:d:\b.txt