Java常用API

总览

image

【注】关于工具类

工具类就是不需要实例化的类,其存在目的是为了使用里面的类方法

比如Math、System、Arrays都是工具类

工具类的设计思想:

  • 构造方法用private修饰,其目的是为了防止工具类被实例化,所以工具类也是有构造方法的,只是被private修饰了
  • 成员用public static修饰,其目的是可以直接通过类名直接调用工具类方法

总而言之,这两个举措都是为了编程的方便性,都是为了能够直接用类名调用方法,而不需要先创建对象再通过对象使用方法

【注】java.lang包不需要导包

1 Random

作用:用于产生一个随机数

使用步骤:

  1. 导包:import java.util.Random
  2. 创建对象:Random r = new Random();
  3. 获取随机数:int number = r.nextInt(10)//获取数据的范围:[0,10),即包括0不包括10

2 String

2.1 String概述

  • String类在java.lang 包下,所以使用的时候不需要导包
  • String类代表字符串,Java程序中的所有字符串文字(例如“abc”)都被实现为此类的实例也就是说,Java程序中所有的双引号字符串,都是String类的对象

字符串特点(不可变性:String类是final类型)

  • 字符串不可变,它们的值在创建后不能被更改
  • 虽然String的值是不可变的,但是它们可以被共享
  • 字符串效果上相当于字符数组(char[]),但是底层原理是字节数组( byte[])

2.2 String类构造方法

方法名 说明
public String() 创建一个空白字符串对象,不含有任何内容
public String(char[] chs) 根据字符数组的内容,来创建字符串对象
public String(byte[] bys) 根据字节数组的内容,来创建字符串对象
String s = "abc" 直接赋值的方式创建字符串对象,内容就是abc
package com.exception;

public class Application {
    public static void main(String[] args) {
        String s1 = new String();
        System.out.println("s1:"+s1);//s1:

        char[] chs  = {'a','b','c'};
        String s2 = new String(chs);
        System.out.println("s2:"+s2);//s2:abc

        byte[] byt = {97,98,99};
        String s3 = new String(byt);
        System.out.println("s3:"+s3);//s3:abc

        String s4 = "abc";
        System.out.println("s4:"+s4);//s4:abc
    }
}

2.3 String对象的特点

  1. 通过new创建的字符串对象,每一次new都会申请一个内存空间虽然内容相同,但是地址值不同
char[] chs = {'a','b','c'};
String s1 = new String(chs);
String s2 = new String(chs);

上面的代码中,JVM会首先创建一个字符数组,然后每一次new的时候都会有一个新的地址,只不过s1和s2参考的字符串内容是相同的。

  1. 以” “方式给出的字符串,只要字符串序列相同(顺序和大小写),无论在程序代码中出现几次,JVM都只会建立一个String对象,并在字符串池中维护。
String s3 = "abc";
String s4 = "abc";

在上面的代码中,针对第一行代码,JVM会建立一个String对象放在字符串池中,并给s3参考;第二行则让s4直接参考字符串池中的String对象,也就是说它们本质上是同一个对象,java中字符串的值是不可改变的,相同的字符串在内存中只会存一份。

代码示例:

package com.exception;

public class Application {
    public static void main(String[] args) {
        //构造方法的方式得到对象
        char[] chs = {'a','b','c'};
        String s1 = new String(chs);
        String s2 = new String(chs);
        //比较s1s2两个字符串对象地址是否相同
        System.out.println(s1==s2);//false

        //直接赋值的方式得到对象
        String s3 = "abc";
        String s4 = "abc";
        //比较s3s4两个字符串对象地址是否相同
        System.out.println(s3==s4);//true
        //比较s1s3两个字符串对象地址是否相同
        System.out.println(s1==s3);//false
    }
}

内存分析:

image

2.4 String类常用成员方法

方法名 说明
public char charAt(int index) 返回指定索引处的char值,字符串的索引也是从0开始
public int length() 返回此字符串的长度
public boolean equals(Object anObject) 比较字符串的内容,严格区分大小写
public static String valueOf(int/long/char... x) 将传递的int/long/char...型数值返回为字符串表示形式
public String[] split(String regex) 将字符串根据传入的字符将字符串分为若干部分存入数组中,返回此字符串数组

public static String valueOf(int/long/char... i)部分在8.2.3.1部分

public String[] split(String regex)部分在8.3部分

2.4.1 public char charAt(int index)

String str = "abcde";
System.out.println(str.charAt(0));//a
System.out.println(str.charAt(1));//b
System.out.println(str.charAt(2));//c

2.4.2 public int length()

String str = "abcde";
System.out.println(str.length());//5
  • 数组的长度:数组名.length
  • 字符串的长度:字符串对象.length()

2.4.3 public boolean equals(Object anObject)

字符串的比较

使用==作比较

  • 基本类型:比较的是数据值是否相同
  • 引用类型:比较的是地址值是否相同

字符串是对象,它比较内容是否相同,是通过equals()方法来实现的

  • public boolean equals(Object anObject):将此字符串与指定对象进行比较。由于我们比较的是字符串对象,所以参数直接传递一个字符串

代码示例:

package com.exception;

public class Application {
    public static void main(String[] args) {
        //构造方法的方式得到对象
        char[] chs = {'a','b','c'};
        String s1 = new String(chs);
        String s2 = new String(chs);

        //直接赋值的方式得到对象
        String s3 = "abc";
        String s4 = "abc";

        System.out.println(s1.equals(s2));//true
        System.out.println(s1.equals(s3));//true
        System.out.println(s3.equals(s4));//true
    }
}

2.5 案例:遍历字符串

需求:键盘录入一个字符串,使用程序实现在控制台遍历该字符串。

思路:

  1. 键盘录入一个字符串,用Scanner实现

  2. 遍历字符串,首先要能够获取到字符串的每一个字符

  3. 遍历字符串,其次要能够获取到字符串的长度

代码实现:

public void traversalString(){
    Scanner sc = new Scanner(System.in);
    System.out.println("请输入字符串:");
    String str = sc.nextLine();

    for (int i = 0; i < str.length(); i++) {
        System.out.print(str.charAt(i));
    }
}

2.6 案例:统计字符次数

需求:键盘录入一个字符串,统计该字符串中大写字母字符,小写字母字符,数字字符出现的次数(不考虑其他字符)

public void count(){
    int lowerCaseCount = 0;
    int capitalCount = 0;
    int numCount = 0;
    boolean flag = true;

    Scanner sc = new Scanner(System.in);
    System.out.println("请输入字符串:");
    String str = sc.nextLine();

    for (int i = 0; i < str.length(); i++) {
        char ch = str.charAt(i);

        if (ch >= 'a' && ch <= 'z'){
            lowerCaseCount++;
        }else if (ch >= 'A' && ch <= 'Z'){
            capitalCount++;
        }else if(ch >= '0' && ch <= '9') {
            numCount++;
        }else {
            flag = false;
            break;
        }
    }

    if (flag) {
        System.out.println("小写:"+lowerCaseCount+"次,大写:"+capitalCount+"次,数字:"+numCount+"次。");
    } else {
        System.out.println("输入有误!");
    }
}

2.7 案例:字符串拼接

需求:定义一个方法,功能是调用时传一个int数组,方法返回字符串,字符串格式为[数字1,数字2...]

public static void main(String[] args) {
    int[] a = {1,2,1,2,111};

    arrayToString(a);
}

public static void arrayToString(int[] a){
    String str = "";

    str += "[";

    for (int i = 0; i < a.length; i++) {
        if (i == a.length-1) {
            str += a[i];
        } else {
            str += a[i]+",";
        }
    }

    str += "]";

    System.out.println(str);
}

2.8 案例:字符串反转

需求:定义一个方法,实现字符串反转

public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    System.out.println("请输入字符串:");
    String str = sc.nextLine();

    System.out.println(reverse(str));
}

public static String reverse(String str){
    String reverseStr = "";

    for (int i = str.length()-1; i >= 0; i--) {
        reverseStr += str.charAt(i);
    }

    return reverseStr;
}

3 StringBuilder

  • 包路径:java.lang.StringBuilder

3.1 字符串拼接的内存分析

image

  • 最终控制台输出的内容是003内存的内容,001和002空间就被浪费掉了。
  • 如果对字符串进行拼接操作,每次拼接,都会构建一个新的String对象,既耗时,又浪费内存空间,而这种操作还不可避免。那么有没有一种比较子的方式可以解决这个问题呢?答案是肯定的,我们可以通过Java提供的StringBuilder类就来解决这个问题。
  • StringBuilder是一个可变的字符串类,我们可以把它看成是一个容器这里的可变指的是StringBuilder对象中的内容是可变的。

3.2 String和StringBuilder的区别

  • String:内容是不可变
  • StringBuilder:内容是可变

3.3 StringBuilder类构造方法

方法名 说明
public StringBuilder() 创建一个空白可变字符串对象,不含有任何内容
public StringBuilder(String str) 根据字符串内容,来创建可变字符串对象

代码示例:

package com.API;

public class test {
    public static void main(String[] args) {
        StringBuilder sb1 = new StringBuilder();
        StringBuilder sb2 = new StringBuilder("liam");

        System.out.println("sb1:"+sb1);//sb1:
        System.out.println("sb2:"+sb2);//sb2:liam
        System.out.println("sb1.length():"+sb1.length());//sb1.length():0
        System.out.println("sb2.length():"+sb2.length());//sb2.length():4
    }
}

3.4 StringBuilder类常用方法

方法名 说明
public StringBuilder append(任意类型) 添加数据,并返回对象本身
public StringBuilder reverse(String str) 返回相反的字符序列(返回的也是一个对象
public String toString() StingBuilder型转换成String

3.4.1 public StringBuilder append(任意类型)

作用:添加数据,并返回对象本身

package com.API;

public class test {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();

        StringBuilder sb2 = sb.append("hello");
        System.out.println("sb:"+sb);//hello
        System.out.println("sb2:"+sb2);//hello
        System.out.println(sb==sb2);//true
    }
}

这里没有直接对sb进行赋值,但此时sb和sb2都是hello,且两对象地址一样,说明sb调用append()方法返回了对象本身,所以sb.append("hello")这一个整体也是一个对象,所以可以用链式编程

package com.API;

public class test {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();

        sb.append("hello");
        sb.append("world");
        sb.append("java");
        sb.append(100);
        System.out.println(sb);//helloworldjava100
    }
}

以上代码可以用链式编程:

package com.API;

public class test {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();

        sb.append("hello").append("world").append("java").append(100);
        System.out.println(sb);//helloworldjava100
    }
}

3.4.2 public StringBuilder reverse(String str)

返回相反的字符序列(返回的也是一个对象

package com.API;

public class test {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();

        sb.append("hello").append("world").append("java").append(100);
        System.out.println(sb);//helloworldjava100
        sb.reverse();
        System.out.println(sb);//001avajdlrowolleh
    }
}

3.5 StringBuilder和String相互转换

为什么要将两个类相互转换?

为了让String类使用StringBuilder中两个方便的方法append()reverse()

3.5.1 StringBuilder→String

public String toString():通过toString就可以实现把StringBuilder转换为String。

package com.API;

public class test {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();

        sb.append("hello");
        String str = sb.toString();
        System.out.println(str);//hello
    }
}

3.5.2 String→StringBuilder

public StringBuilder(String s):通过构造方法可以实现把String转换为StringBuilder。

package com.API;

public class test {
    public static void main(String[] args) {
        String str = "hello";
        StringBuilder sb = new StringBuilder(str);
        System.out.println(sb);//hello
    }
}

3.6 案例:字符串拼接2.0

需求见2.7 案例:字符串拼接,2.7这种方法既耗时又浪费空间,在这里使用StringBuilder来节省空间以及提高效率。

package com.API;

public class test {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4};

        System.out.println(arrayToString(arr));
    }

    public static String arrayToString(int[] arr){
        StringBuilder sb = new StringBuilder();

        sb.append("[");

        for (int i = 0; i < arr.length; i++) {
            if (i==arr.length-1){
                sb.append(arr[i]);
            }else {
                sb.append(arr[i]+",");
            }
        }

        sb.append("]");

        return sb.toString();
    }
}

3.7 案例:字符串反转2.0

需求见2.8 案例:字符串反转,这里将String字符串转换成StingBuilder再调用reverse()方法实现字符串反转。

package com.API;

import java.util.Scanner;

public class test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入字符串:");
        String str = sc.nextLine();

        System.out.println(arrayReverse(str));
    }

    public static String arrayReverse(String str){
//        StringBuilder sb = new StringBuilder(str);
//        sb.reverse();
//        return sb.toString();
        return new StringBuilder(str).reverse().toString();//可以直接一行代码解决
    }
}

4 Math

  • 包路径:java.lang.Math
  • Math包含执行基本数学运算的方法
  • Math类是工具类,构造方法被private修饰,无法实例化,其成员都是静态的,所以可以直接使用类名就能调用Math类的成员

4.2 Math类常用方法

方法名 说明
public static int abs(int a) 返回参数的绝对值
public static double ceil(double a) 返回大于或等于参数的最小double值,等于一个整数
public static double floor(double a) 返回小于或等于参数的最大double值,等于一个整数
public static int round(float a) 按照四舍五入返回最接近参数的int
public static int max(int a,int b) 返回两个int值中的较大值
public static int min(int a,int b) 返回两个int值中的较小值
public static double pow(double a,double b) 返回a的b次幂的值
public static double random() 返回值为double的随机正值,取值范围是[0.0,1.0)

4.3 Math类常用方法示例

package com.API;

public class test {
    public static void main(String[] args) {
        //1. public static int abs (int a):返回参数的绝对值
        System.out.println(Math.abs(88));//88
        System.out.println(Math.abs(-88));//88
        System.out.println("====================");

        //2. public static double ceil(double a):返回大于或等于参数的最小double值,等于一个整数
        System.out.println(Math.ceil(12.22));//13.0
        System.out.println(Math.ceil(19.21));//20.0
        System.out.println("====================");

        //3. public static double floor(double a):返回小于或等于参数的最大double值,等于一个整数
        System.out.println(Math.floor(12.33));//12.0
        System.out.println(Math.floor(8.22));//8.0
        System.out.println("====================");

        //4. public static int round(float a):按照四舍五入返回最接近参数的int
        System.out.println(Math.round(2.33));//2
        System.out.println(Math.round(9.5));//10
        System.out.println("====================");

        //5. public static int max(int a,int b):返回两个int值中的较大值
        System.out.println(Math.max(2,9));//9
        System.out.println("====================");

        //6. public static int min(int a,int b):返回两个int值中的较小值
        System.out.println(Math.min(3,5));//3
        System.out.println("====================");

        //7. public static double pow(double a,double b):返回a的b次幂的值
        System.out.println(Math.pow(2.0,3.0));
        System.out.println("====================");//8.0

        //8. public static double random():返回值为double的随机正值,取值范围是[0.0,1.0)
        System.out.println(Math.random());
        System.out.println((int)(Math.random()*100));
    }

}

5 System

  • 包路径:java.lang.System
  • System类包含几个有用的类字段和方法
  • System类是工具类,构造方法被private修饰,无法实例化,其成员都是静态的,所以可以直接使用类名就能调用System类的成员

5.1 System类的常用方法

方法名 说明
public static void exit(int status) 终止当前运行的Java虚拟机,非零表示异常终止
public static long currentTimeMillis() 返回当前时间与1970年1月1日0时0分0秒之间的毫秒时间间隔

5.1.1 public static void exit(int status)

作用:终止当前运行的Java虚拟机,非零表示异常终止

package com.API;

public class test {
    public static void main(String[] args) {
        System.out.println("开始");//输出了“开始”
        System.exit(0);
        System.out.println("结束");//未输出“结束”
    }

}

5.1.2 public static long currentTimeMillis()

  • 作用:返回当前时间与1970年之间的毫秒时间间隔
  • 应用:可以计算一个代码块的运行时间

currentTimeMillis()计算1970年距今多少年

package com.API;

public class test {
    public static void main(String[] args) {
        System.out.println("1970年距今"+System.currentTimeMillis()*1.0/1000/3600/24/365+"年");
        //1970年距今52.355059927733386年
    }
}

currentTimeMillis()计算一个代码块的运行时间

package com.API;

public class test {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();

        for (int i = 0; i < 10000; i++) {
            System.out.println(i);
        }

        long end = System.currentTimeMillis();

        System.out.println("共耗时:"+(end-start)+"毫秒");
    }
}

6 Object

Object类是类层次结构的根,每个类都有Object作为超类(超类:被继承的类),所有类都直接或者间接的继承该类,所有对象(包括数组)都实现了这个类的方法。

6.1 Object类构造方法

构造方法 说明
public Object() 构造一个新对象

Object类只有一个无参构造,面向对象中,子类访问父类的构造方法默认第一行是super(),即默认访问的是父类的无参构造方法,原因就是因为他们的老祖宗Object类只有无参构造方法。

6.2 Object类常用方法

方法名 说明
public String toString() 返回对象的字符串表示形式
public boolean equals(Object obj) 指示是否有其他对象“等于”这一个

6.2.1 Object类的public String toString()方法

现有Animal类,有私有属性name和age,现创建一个对象animal,将name和age赋值,然后在main方法直接输出animal对象,具体代码如下:

Animal类:

package com.oop.demo05;

public class Animal {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

main方法:

package com.oop;

import com.oop.demo05.Animal;

public class Application {
    public static void main(String[] args) {
        Animal animal = new Animal();

        animal.setName("旺财");
        animal.setAge(5);
        System.out.println(animal);//输出“com.oop.demo05.Animal@4554617c”
    }
}
  • 这时发现直接输出对象的内容不可读

现在看IDEA中printLn()方法的实现,大致可简化成如下代码:

public void println(Object x) {
    String s = String.valueOf(x);
    synchronized (this) {
        print(s);
        newLine();
    }
}

public static String valueOf(Object obj) {
        return (obj == null) ? "null" : obj.toString();
    }

public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
  • 若直接传对象给printLn()printLn()方法中会调用valueOf()valueOf()会调用toString(),而toString()默认会返回一个不可读的内容,即return getClass().getName() + "@" + Integer.toHexString(hashCode());,所以重写toString()方法,在直接输出对象的时候就可以输出可读的有效内容。
  • alt+insert选中toString()即可重写toString()方法

重写toString()后直接输出对象版本如下:

Animal类:

package com.oop.demo05;

public class Animal {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Animal{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

main方法:

package com.oop;

import com.oop.demo05.Animal;

public class Application {
    public static void main(String[] args) {
        Animal animal = new Animal();

        animal.setName("旺财");
        animal.setAge(5);
        System.out.println(animal);//输出结果为“Animal{name='旺财', age=5}”
        System.out.println(animal.toString());//输出结果为“Animal{name='旺财', age=5}”
    }
}

以后写子类的时候最好重写一下Object类的toString()方法,这样调用toString()时直接传对象进去输出的就是看得懂的字符串

6.2.2 Object类的public boolean equals(Object obj)方法

如果想要比较两个对象的内容是否相等,用==来判断只能得出两对象的地址是否相等,若用equals()来判断,但Object类中的equals()方法默认也是比较两个值地址是否相等,所以此时需要重写Object父类中的equals()方法,来达到比较两对象内容是否相等的目的,只需alt+insert再选中equals and hashcode,再把hashcode()方法重写的部分删除即可。

例:现有Animal类:

package com.oop.demo05;

public class Animal {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

main方法:

package com.oop;

import com.oop.demo05.Animal;

public class Application {
    public static void main(String[] args)
    {
        Animal a1 = new Animal();
        a1.setAge(2);
        a1.setName("旺财");

        Animal a2 = new Animal();
        a2.setAge(2);
        a2.setName("旺财");

        System.out.println(a1.equals(a2));//未进行equals()方法重写的比较结果:false
    }
}

Object类默认equals()方法原码:equals()默认比较的是两个对象的地址是否相等

public boolean equals(Object obj) {
    return (this == obj);//this➡a1   obj➡a2
}

在Animal类中重写equals()方法(该重写内容是自动生成的,无需自己写):以此来达到比较两对象内容是否相等的目的

重写后的代码解析:

        @Override
    public boolean equals(Object o) {
        /*
            this --- a1
            o    --- a2
        */

        // 1.比较地址是否相同,如果相同,直接返回true
        if (this == o) return true;

        // 2.参数为null 或者 两对象不来自同一类,返回false
        if (o == null || getClass() != o.getClass()) return false;
		//※※※因为调用equals()的对象其一定不为null,那么此对象肯定不等于为null的o,所以返回false※※※
        //※※※(调用equals的对象若为null则会提示NullPointerException空指针报错)※※※
        
        //向下转型
        Animal animal = (Animal) o;//animal = a2;

        // 3.比较年龄是否相同
        if (age != animal.age) return false;

        // 4.比较姓名内容是否相同,这里的equals()是String类里的equals(),用于比较字符串的内容是否相等
        return name != null ? name.equals(animal.name) : animal.name == null;
        //若a1的name不为空,则返回a1与a2的name值是否相同的比较结果
        //若a1的name为空,则返回a2的name值是否为空的比较结果
    }

重写后再调用equals()即可让System.out.println(a1.equals(a2));输出为ture

关于重写equals()后代码的第2.步的判断: Java中类对象为空的含义以及只有非null对象可以调用equals()的说明※

Java中类对象为空的含义部分:

针对6.2.2中重写euqals()中判断对象是否为空的部分,专门说明Java中类对象为空到底是什么意思

package com.oop;

class Person {
    int age;//默认为0
    String name;//默认为null
    Person(){
    }
}

class Course{
    String coursename;//默认为null
    Course(){
    }
}

public class Application {
    public static void main(String[] args) {
        //1. 只定义对象但不对其进行实例化
//        Person p1;//此处没有报错
//        if(p1==null)//此处报错,提示p1为进行初始化
//            System.out.println("Object is empty");
//        else
//            System.out.println("Object is not empty");
        //结论1:在这种情况下,对对象进行是否为空的判断中系统会报错,所以此情况并不是“对象为空”的真正含义

        //2. 直接令对象为null
        Person p2=null;
        if(p2==null)
            System.out.println("Object is empty");//输出此句
        else
            System.out.println("Object is not empty");
        //结论2:直接令对象为null,那么此对象为空,所以此情况就是“对象为空”的真正含义

        //3. 实例化对象但不进行赋值操作
        Person p3=new Person();//实例化了Person类对象person
        System.out.println(p3.age);//直接输出未被赋值的age,为0
        System.out.println(p3.name);//直接输出未被赋值的name,为null
        if(p3==null)
            System.out.println("Object is empty");//未输出此句,因为person定义了且实例化,就不为空,哪怕它的一个或多个属性为空
        else
            System.out.println("Object is not empty");//输出此句
        //结论3:只要类对象用new实例化那么它就不为空,所以此情况并不是“对象为空”的真正含义
        // 若没有对int属性进行赋值,那么默认为0,若没有对Sting属性进行赋值,那么默认为null

        //4. 当对象所有属性为null值的情况
        Course course=new Course();//实例化一个Course类对象,并且不进行赋值操作,其所有属性的值(只有一个String型属性)默认都是null
        System.out.println(course.coursename);//直接输出未被赋值的coursename,为null
        if(course==null)
            System.out.println("Object is empty");//未输出此句,因为person定义了且实例化,就不为空,哪怕它所有属性都为空
        else
            System.out.println("Object is not empty");//输出此句
        //结论4:当一个对象进行了实例化操作未进行赋值,其所有属性(String型属性)默认为null,即使对象的所有属性为null,这个对象也不为空,
        //所以此情况并不是“对象为空”的真正含义
    }
}

综上四种情况的举例说明,只要进行了类的实例化,对象就不为空;只有将对象直接赋值为null时(例:Person person = null;),对象才为空


只有非null对象可以调用equals()部分:

①当null对象a1调用equals()方法进行和null对象a2进行比较:

public class Application {
    public static void main(String[] args) {
        Animal a1 = null;
        Animal a2 = null;
        System.out.println(a1.equals(a2));//提示NullPointerException空指针报错
    }
}

②当null对象a3调用equals()方法进行和非null对象a4进行比较:

public class Application {
    public static void main(String[] args) {
        Animal a3 = null;
        Animal a4 = new Animal();
        System.out.println(a3.equals(a4));//提示NullPointerException空指针报错
    }
}

③当非null对象a5调用equals()方法进行和null对象a6进行比较:

public class Application {
    public static void main(String[] args) {
        Animal a5 = new Animal();
        Animal a6 = null;
        System.out.println(a5.equals(a6));//false
    }
}

所以:只有不为null的对象可以调用equals()

6.3 关于Object类用于参数的传递

Object类是所有类的直接父类或间接父类,也就是说是所有类的根父类,这个可以运用于参数的传递

package com.oop;

public class Application {
    public static void main(String[] args)
    {
        A a=new A();
        B b=new B();
        C c=new C();
        D d=new D();
        speak(a);
        speak(b);
        speak(c);
        speak(d);
    }
    // instanceof 关键字是用于比较类与类是否相同,相同返回true,不同返回false
    //※※※当你不清楚你需要的参数是什么类型的,可以用Object来代替,Object可以代替任何类※※※
    static void speak(Object obj)
    {
        if(obj instanceof A)//意思是:如果参数是 A 类,那么就执行一下语句
        {
            A aobj=(A)obj;//这里是向下转换,需要强制转换
            aobj.axx();
        }
        else if(obj instanceof B)
        {
            B bobj=(B)obj;
            bobj.bxx();
        }
        else if(obj instanceof C)
        {
            C cobj=(C)obj;
            cobj.cxx();
        }
    }
}

	//这里举了四个类,他们的函数都不同,但都是 Object 类的子类
    class A
    {
        void axx()
        {
            System.out.println("Good morning!");
            System.out.println("This is A");
        }
    }

    class B
    {
        void bxx()
        {
            System.out.println("Holle!");
            System.out.println("This is B");
        }
    }

    class C
    {
        void cxx()
        {
            System.out.println("Look!");
            System.out.println("This is C");
        }
    }

    class D
    {
        void dxx()
        {
            System.out.println("Oh!Bad!");
            System.out.println("This is D");
        }
    }

运行结果:

Good morning!
This is A
Holle!
This is B
Look!
This is C

7 Arrays

  • 包路径:java.util.Arrays
  • Arrays类包含对数组进行操作的方法
  • Arrays类是工具类,构造方法被private修饰,无法实例化,其成员都是静态的,所以可以直接使用类名就能调用Arrays类的成员

7.1 Arrays类常用方法

方法名 说明
public static String toString(int[] a) 传入整型数组,以字符串的表示形式返回数组的内容
public static void sort(int[] a) 按照数字顺序排列传入的数组
public static fill(int[] a,int val) 选择一个数组,让其被某一个数值填满
public static fill(int[] a,int fromIndex,int toIndex,int val) 选择一个数组,输入起始下标,输入一个数值,结果是让起始下标中间的数值被输入的数值填满

7.1.1 通过public static String toString(int[] a)打印数组内容public

  • toString()打印数组元素
package com.liam.array;

import java.util.Arrays;

public class ArrayDemo04 {
    public static void main(String[] args) {
        int[] a = {1,2,44,555,675,3345,2323};

        //打印数组元素方法Arrays.toString()
        System.out.println(Arrays.toString(a));
        printArrays(a);
    }

    public static void printArrays(int[] arrays){//自己编写的打印数组元素算法
        for (int i = 0; i < arrays.length; i++) {
            if (i==0){
                System.out.print("[");
            }else if(i==arrays.length-1){
                System.out.print(arrays[i]+"]");
                break;
            }

            System.out.print(arrays[i]+", ");
        }
    }
}

7.1.2 数组元素排序方法public static void sort(int[] a)

  • sort()将数组元素排序
int[] a = {1,2,44,555,675,3345,2323};

Arrays.sort(a);
System.out.println(Arrays.toString(a));
//输出结果:[1, 2, 44, 555, 675, 2323, 3345]

7.1.3 数组填充方法Arrays.fill

  • fill(int[] a,int val)
int[] a = {1,2,44,555,675,3345,2323};

Arrays.fill(a,0);//选择一个数组,让其被某一个数值填满
System.out.println(Arrays.toString(a));//输出结果:[0, 0, 0, 0, 0, 0, 0]
  • fill(int[] a,int fromIndex,int toIndex,int val)
int[] a = {1,2,44,555,675,3345,2323};

Arrays.fill(a,3,5,0);//选择一个数组,输入起始下标,输入一个数值,结果是让起始下标中间的数值被输入的数值填满
System.out.println(Arrays.toString(a));//[1, 2, 44, 0, 0, 3345, 2323]

8 基本类型包装类

8.1 基本类型包装类概述

将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据

常用的操作之一:用于基本数据类型与字符串之间的转换

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

例:调用Integer类中的常量MIN_VALUE和MAX_VALUE

public class Application {
    public static void main(String[] args) {
        //public static final int   MIN_VALUE
        //public static final int   MAX_VALUE
        System.out.println(Integer.MIN_VALUE);//-2147483648
        System.out.println(Integer.MAX_VALUE);//2147483647
    }
}

8.2 Integer类的概述和使用

  • 包路径:java.lang.Integer
  • Integer:包装一个对象中的原始类型int的值

8.2.1 Integer类构造方法(过时)

方法名 说明
public Integer(int value) 根据int值创建Integer对象(已过时)
public Integer(String s) 根据String值创建Integer对象(已过时)

用已过时的构造方法得到对象举例:

public class Application {
    public static void main(String[] args) {
        Integer i1 = new Integer(100);
        System.out.println(i1);//100
        Integer i2 = new Integer("100");
        System.out.println(i2);//100
//        Integer i3 = new Integer("abc");
//        System.out.println(i3);//报错提示NumberFormatException
    }
}

8.2.2 Integer类常用方法

方法名 说明
public static Integer valueOf(int i) 返回表示指定的int值的Integer实例
public static Integer valueOf(Sting s) 返回一个保存指定值的Integer对象String
public int intValue() Integer类型的数值转换为int
public static int parseInt(String s) 将传递的字符串返回为int型表示形式

public int intValue()public static int parseInt(String s)部分在8.2.3.2部分

valueOf()得到对象举例:

public class Application {
    public static void main(String[] args) {
        Integer i1 = Integer.valueOf(100);
        System.out.println(i1);
        Integer i2 = Integer.valueOf("100");
        System.out.println(i2);
//        Integer i3 = Integer.valueOf("abc");
//        System.out.println(i3);//报错提示NumberFormatException
    }
}

8.2.3 intString的相互转换

基本类型包装类的最常见操作就是:用于基本类型和字符串之间的相互转换

涉及到以下方法:

所属类 方法名 说明
String public static String valueOf(int i) 将传递的int型数值返回为字符串表示形式
Integer public int intValue() Integer类型的数值转换为int
Integer public static int parseInt(String s) 将传递的字符串返回为int型表示形式

8.2.3.1 intString

方式一:(显得不专业,一般用方式二)

将双引号和int型进行拼接

public class Application {
    public static void main(String[] args) {
        int i = 100;
        String s = "" + i;
        System.out.println(s);
    }
}

方式二:

利用String类中的 public static String valueOf(int i)int型直接转换为String

public class Application {
    public static void main(String[] args) {
        int i = 100;
        String s = String.valueOf(i);
        System.out.println(s);
    }
}

8.2.3.2 Stringint

方式一: StringIntegerint(麻烦,一般用方式二)

  • 先将String型用Integer类中的public static Integer valueOf(Sting s)转换为Integer
  • 再通过Integer类中的public int intValue()Integer型转换为int
public class Application {
    public static void main(String[] args) {
        String s = "100";
        Integer itg = Integer.valueOf(s);
        int i = itg.intValue();
        System.out.println(i);
    }
}

方式二:

利用Integer类中的public static int parseInt(String s)方法将String型直接转换为int

public class Application {
    public static void main(String[] args) {
        String s = "100";
        int i = Integer.parseInt(s);
        System.out.println(i);
    }
}

8.3 案例:字符串中的数据排序

需求:有一个字符串"82:21:33:1:3:34",编写程序实现最终输出结果是:"1:3:21:33:34:82"

涉及以下方法:

方法名 说明
public String[] split(String regex) 将字符串根据传入的字符将字符串分为若干部分存入数组中,返回此字符串数组

例,字符串"boo:and:foo",当传入的字符不一样时,返回的字符串数组也不一样:

regex result
: {"boo","and","foo"}
o {"b","",":and:f"}

实现步骤:

public class Application {
    public static void main(String[] args) {
        String s = "82:21:33:1:3:34";
        //第一步:用`public String[] split(String regex)`将初始字符串转换成字符串数组
        String[] strArray = s.split(":");

        //第二步:将字符串数组内的各个元素通过`public static int parseInt(String s)`转化成若干整型,再将这些整型寄存在整型数组中
        int[] iArray = new int[strArray.length];
        for (int i = 0; i < strArray.length; i++) {
            iArray[i] = Integer.parseInt(strArray[i]);
        }

        //第四步:将整型数组的元素重新排序
        Arrays.sort(iArray);

        //第五步:利用`public StringBuilder append(任意类型)`将整型数组的元素进行字符串拼接
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < strArray.length; i++) {
            if (i == strArray.length-1){
                sb.append(iArray[i]);
            }else {
                sb.append(iArray[i]).append(":");
            }
        }

        //第六步:利用`public String toString()`将StringBuilder型转换为String型
        String str = sb.toString();
        System.out.println(str);//1:3:21:33:34:82
    }
}

8.4 自动装箱和自动拆箱

装箱:基本数据类型→对应的包装类类型

拆箱:包装类类型→对应的基本数据类型

8.4.1 装箱、自动装箱

装箱,即基本数据类型→对应的包装类类型(基本类型→引用类型)Integer i = Integer.valueOf(100);

这里将int型100转换成了Integer

自动装箱:Integer ii = 100;

此步骤系统无报错提示,这里之所以叫自动装箱是因为自动将int型直接转换成了Integer型,在底层其实是进行了装箱操作的,即Integer ii = Integer.valueOf(100);

8.4.2 拆箱、自动拆箱

拆箱,即包装类类型→对应的基本数据类型(引用类型→基本类型)int temp = ii.intValue();

这里将Integerii转换成了int

自动拆箱:

ii += 200;,这个操作中隐含了自动的拆箱操作以及自动的装箱操作

此操作系统是不会报错的,其在底层的逻辑是:ii = ii.intValue() + 200

其中:

  1. ii.intValue()是拆箱,此步就是被隐含的自动拆箱
  2. 等号右边是int型,等号左边是Integer型,把右边赋值给左边就是隐含的自动装箱

【注】在对对象进行操作前需进行是否为null的判断

在使用包装类类型的时候,想进行操作,最好先判断其是否为null,只要是对象,在使用前就必须进行不为null的判断

例:

public class Application {
    public static void main(String[] args) {
        Integer itg = null;
        itg += 100;
        System.out.println(itg);//报错NullPointerException
    }
}

进行判断是否为null的操作可以避免报错:

public class Application {
    public static void main(String[] args) {
        Integer itg = null;
        if (itg != null){
            itg += 100;
            System.out.println(itg);
        }
    }
}

9 日期类

9.1 Date

  • 包路径:java.util.Date
  • Date代表了一个特定的时间,精确到毫秒

9.1.1 Date类构造方法

方法名 说明
public Date() 分配一个Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒
public Date(long date) 传入一个毫秒数,返回从1970年1月1日00:00:00增加传入毫秒后的时间
package com.oop;

import java.util.Date;

public class Application {
    public static void main(String[] args) {
        Date d1 = new Date();
        System.out.println(d1);//输出“Sun Jun 19 11:30:45 CST 2022”,即现在的时间,CST是中国标准时间

        long date = 1000*60*60;//1秒=1000毫秒,date是传入的毫秒数,即1小时
        Date d2 = new Date(date);
        System.out.println(d2);//输出“Thu Jan 01 09:00:00 CST 1970”,即1970年1月1日00:00:00增加1小时后的时间,
                               //之所以不是1点而是9点,是因为跟中国时区不一样
    }
}

9.1.2 Date类常用方法

方法名 说明
public long getTime() 获取的是日期对象从1970年1月1日00:00:00到现在的毫秒值
public void setTime(long time) 设置时间,传入一个毫秒数,返回从1970年1月1日00:00:00增加传入毫秒后的时间
package com.oop;

import java.util.Date;

public class Application {
    public static void main(String[] args) {
        //`public long getTime()
        Date d = new Date();
        System.out.println("1970年距今"+d.getTime()*1.0/1000/60/60/24/365+"年");//1970年距今52.49906972574202年

        //public void setTime(long time)
        long date = 1000*60*60;
        d.setTime(date);
        System.out.println(d);//Thu Jan 01 09:00:00 CST 1970

        //与System.currentTimeMillis()联动
        long date2 = System.currentTimeMillis();//获取当前距1970年的毫秒数
        d.setTime(date2);//将 当前距1970年的毫秒数 设置为 1970年增加的毫秒数
        System.out.println(d);//输出为“Sun Jun 19 11:58:55 CST 2022“,即当前时间
    }
}

9.2 SimpleDateFormat

  • 包路径:java.text.SimpleDateFormat
  • SimpleDateFormat是一个具体的类,用于以区域设置敏感的方式格式化解析日期。需重点学习日期格式化和解析
  • 日期和时间格式由日期和时间模式字符串指定,在日期和时间模式字符串中,从 'A' 到 ' Z' 以及从 'a' 到 'z' 引号的字母被解释为表示日期或时间字符串的组件的模式字母

常用的模式字母及对应关系如下:

字母 解释
y
M
d
H
m
s

9.2.1 SimpleDateFormat类构造方法

方法名 说明
public SimpleDateFormat() 构造一个SimpleDateFormat,使用默认模式和日期格式
public SimpleDateFormat(String pattern) 构造一个SimpleDateFormat使用给定模式和默认的日期格式

9.2.2 SimpleDateFormat类的格式化和解析日期

  1. 格式化(从Date到String)public final String format(Date date):将日期格式化成日期/时间字符串
  2. 解析(从String到Date)public Date parse(String source):从给定字符串的开始解析文本以生成日期

9.2.2.1 格式化:从Date到String

无参构造,使用默认模式和日期格式:

package com.oop;

import java.text.SimpleDateFormat;
import java.util.Date;

public class Application {
    public static void main(String[] args) {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat();
        String s = sdf.format(date);
        System.out.println(s);//22-6-19 下午6:55
    }
}

有参构造,使用给定模式和默认的日期格式:

package com.oop;

import java.text.SimpleDateFormat;
import java.util.Date;

public class Application {
    public static void main(String[] args) {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
        String s = sdf.format(date);
        System.out.println(s);//2022年06月19日 19时00分02秒
    }
}

9.2.2.2 解析:从String到Date

所谓解析,就是把字符串的内容解析出来以Date形式表现出来,即String→Date

package com.oop;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Application {
    public static void main(String[] args) throws ParseException {
        String s = "2022年06月19日 18时55分00秒";
        //SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 这里给定的显示日期的格式要跟字符串匹配
        //否则会报错,提示PareseException解析错误,这里已经跟上面的字符串内容不匹配,所以解析错误

        //现给出正确匹配字符串的给定模式,如下:
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
        Date date = sdf.parse(s);
        System.out.println(date);//输出“Sun Jun 19 18:55:00 CST 2022”,没有报错
    }
}

案例:日期工具类

需求:定义一个日期工具类(DateUtils),包含两个方法:把日期转换为指定格式的字符串;把字符串解析为指定格式的日期,然后定义一个测试类(DateDemo),测试日期工具类的方法

【注意】在写工具类时,应将构造方法私有,成员方法静态

DateUtils类部分:

package com.API;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtils {

    private DateUtils(){}

    public static String dateToString(Date date,String format){
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        String s = sdf.format(date);
        return s;
    }

    public static Date stringToDate(String s,String format) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date date = sdf.parse(s);
        return date;
    }

}

DateDemo类部分:

package com.API;

import java.text.ParseException;
import java.util.Date;

public class DateDemo {
    public static void main(String[] args) throws ParseException {
        Date date = new Date();
        String s = DateUtils.dateToString(date,"yyyy月MM月dd日 E HH时mm分ss秒");
        System.out.println(s);
        System.out.println("--------------------------------");

        String s1 = "2022-6-19 20:23:00";
        Date date1 = null;
        date1 = DateUtils.stringToDate(s1,"yyyy-MM-dd HH:mm:ss");
        System.out.println(date1);
    }
}

9.3 Calendar

  • 包路径:java.lang.Calendar
  • Calendar为某一时刻和一组日历字段之间的转换提供了一些方法,并为操作日历字段提供了一些方法

9.3.1 Calendar类获取对象的方法

  • Calendar是抽象类,所以不可实例化,但其成员方法大部分都没有static修饰,所以需要有一个它的对象来调用方法,其对象的创建方法是由它的类方法getInstance来实现的
  • Calendar提供了一个类方法getInstance用于获取Calendar对象,其日历字段已使用当前日期和时间初始化
  • Calendar rightNow = Calendar.getInstance();

9.3.1.1关于Calendar.getInstance();这一获取对象方法的解析:

Calendar rightNow = Calendar.getInstance();

首先:Calendar创建对象是以多态的形式呈现的

  • 等号左边是Calendar,右边则是Calendar的直接子类或间接子类

  • 因为Calendar是抽象类,所以其不能实例化,getInstance会返回一个Calendar的直接子类或间接子类

    查看源码得知:

    1. getInstance会返回createCalendar返回的对象
    2. createCalendar会返回Calendar类型的cal对象
    3. cal则会被赋值给BuddhistCalendarGregorianCalendar子类,即Calendar间接子类)/JapaneseImperialCalendarCalendar直接子类)/GregorianCalendarCalendar直接子类)
    4. 最终getInstance会返回Calendar的直接子类或间接子类,所以Calendar创建对象是以多态的形式呈现的

9.3.2 Calendar类常用方法

方法名 说明
public static Calendar getInstance() 获得一个Calendar对象
public int get(int field) 返回给定日历字段的值
public abstract void add(int field,int amount) 根据日历的规则,将指定的时间量添加或减去给定的日历字段
public final void set(int year,int month,int date) 设置当前日历的年月日

9.3.2.1 public int get(int field)

当创建好Calendar对象后,发现直接用sout输出对象的语句可读性不好,Calendar类中有很多静态字段,所以可以用get(int field)来获取日历字段的值

package com.API;

import java.util.Calendar;

public class Application {
    public static void main(String[] args) {
        //获取Calendar对象
        Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH) + 1;//默认的月份是从0月开始的,所以要进行+1操作
        int date = c.get(Calendar.DATE);
        System.out.println(year + "年" + month + "月" + date + "日");//2022年6月19日
    }
}

9.3.2.2 public abstract void add(int field,int amount)

package com.API;

import java.util.Calendar;
import java.util.Date;

public class Application {
    public static void main(String[] args) {
        Calendar c = Calendar.getInstance();
        //需求1:3年前的今天
//        c.add(Calendar.YEAR, -3);
//        int year = c.get(Calendar.YEAR);
//        int month = c.get(Calendar.MONTH) + 1;
//        int date = c.get(Calendar.DATE);
//        System.out.println(year + "年" + month + "月" + date + "日");//2019年6月19日

        //需求2:10年后的7天后
        c.add(Calendar.YEAR,10);
        c.add(Calendar.DATE,7);
        int year1 = c.get(Calendar.YEAR);
        int month1 = c.get(Calendar.MONTH) + 1;
        int date1 = c.get(Calendar.DATE);
        System.out.println(year1 + "年" + month1 + "月" + date1 + "日");2032年6月26日
    }
}

9.3.2.3 public final void set(int year,int month,int date)

package com.API;

import java.util.Calendar;
import java.util.Date;

public class Application {
    public static void main(String[] args) {
        Calendar c = Calendar.getInstance();
        c.set(2024, 5, 19);
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH) + 1;//注意这里加了1
        int date = c.get(Calendar.DATE);
        System.out.println(year + "年" + month + "月" + date + "日");
    }
}

案例:二月天

需求:获取任意一年的二月有多少天

思路:

  1. 将从用户获取的年份传入二月天方法,用set()设置成当年的3月1日,需注意应该设置月份为2,因为月份是从0开始的,即0月是1月,2月是3月
  2. add()减去一天,得到当年的2月最后一天的日子
  3. get()获取当年2月最后一天的日子
package com.API;

import java.util.Calendar;
import java.util.Scanner;

public class Application {
    public static void main(String[] args) {
        System.out.println("请输入年份:");
        Scanner scanner = new Scanner(System.in);
        int year = scanner.nextInt();
        System.out.println(year+"年有:"+feb(year)+"天");
    }

    public static int feb(int year){
        Calendar c = Calendar.getInstance();
        c.set(year,2,1);
        c.add(Calendar.DATE,-1);
        int date = c.get(Calendar.DATE);
        return date;
    }
}
posted @ 2022-06-20 20:15  雪碧锅仔饭  阅读(303)  评论(0)    收藏  举报