第四节 Java常见API和异常

1.API

API(Application Progranmming Interface,应用程序编程接口)指就是JDK中提供各种功能的Java类,这些类将底层的实现封装了起来,我们不需要知道这些类是如何实现的,我们只需要学习这些类该如何使用,比如生成随机数、控制台输出等JDK官方的一些类库。我们可以通过帮助文档来学习API的使用方法。

例如,生成一个0~100(包含)以内的整数,代码如下:

public class Test {
  public static void main(String[] args) {
//       生成随机数
      Random random = new Random();
      int i = random.nextInt();//随机生成一个整数
      int a = random.nextInt(2);//生成一个0~指定值(不包括)的整数。
      System.out.println(i);
      System.out.println(a);
  }
}

java.lang不需要导包,JDK官方提供的类库都在rt.jar包中。JDK提供了非常多的类库

 

2.帮助文档的使用

按照帮助文档学习Scanner类的使用,并实现键盘录入一个字符串,输出在控制台。代码如下:

public class Test2 {
  public static void main(String[] args) {
      //创建Scanner
      Scanner sc = new Scanner(System.in);
      System.out.println("请录入一个字符串值:");
      //接收 用户输入的字符串
      String a = sc.nextLine();
      System.out.println("你录入的值是:"+a);
  }
}

 

3.Object类

如果类没有继承其它类,那么它默认间接地继承了Object类。默认Object类中是无参构造方法,因此作为父类,其子类默认都是继承了无参构造方法。

Object类中有哪些方法呢?

  • ①clone()——克隆方法(复制对象)
  • ②equals(Object obj)——比较两个对象是否相等
  • ③getClass()——获取该对象的class
  • ④hashCode()——返回该对象的哈希值。
  • ⑤notify()——唤醒正在此对象监视器上等待的单个线程。
  • ⑥notifyAll()—— 唤醒等待此对象监视器的所有线程。
  • ⑦toString()——返回对象的字符串表示形式

 

4.控制台输出对象原理

public class Test2 {
  public static void main(String[] args) {
      Student stu = new Student();
      stu.setName("mayikt");
      stu.setAge(22);
//       创建的stu到底什么意思? 可查看java源代码。
      System.out.println(stu);
//       结果:该类的完整路径地址@哈希值(@符号仅作拼接显示)
//       com.mayikt2.days17.Student@1e643faf
  }
}

 

5.重写Object类的toString方法

toString()方法其目的就是给我们对象重写的,输出对象中所有成员属性值。

//Student类
@Override
public String toString() {
  return "Student{" +
          "name='" + name + '\'' +
          ", age=" + age +
          '}';
}
​
//Test2类
public class Test2 {
  public static void main(String[] args) {
      Student stu = new Student();
      stu.setName("mayikt");
      stu.setAge(22);
      //调用重写后的toString()方法
      System.out.println(stu.toString());
  }
}

 

6.String字符串原理

public class Test {
  public static void main(String[] args) {
      //char只能保存单个字符,而String可保存多个字符(即字符串)。
      //String的底层,实质就是通过char数组来保存字符串。
      String str = "mayikt";
      System.out.println("普通字符串:"+str);
      char[] value = {'m','a','y','i','k','t'};
      System.out.println(value);
  }
}

 

7.String类的equals方法

7.1 基本概念

equals()方法用于比较两个字符串的值是否相等,相等返回ture,否则返回false。注意,使用该方法时前面的字符串不能为空(null,后面的可以为空),否则会报空指针错误。

public class Test {
  public static void main(String[] args) {
      String s1 = "mayikt1";
      String s2 = "mayikt2";
      String s3 = null;
      boolean r1 = s1.equals(s2);
      boolean r2 = s1.equals(s3);//换成s3.equals(s1)就会报错!
      System.out.println(r1);
      System.out.println(r2);
  }
}

7.2 案例——用户登录

需求:已知用户名和密码,用程序实现模拟用户登录,总共给3次机会,登录之后给出相应提示。

思路:①已知用户名和密码。②键盘输入要登录的用户名和密码,用Scanner。③对已知和输入的内容(字符串)比较,用equals()方法。④用循环实现多次机会(最多3次),可采用for循环;登录成功时,用break结束循环。

代码如下:

//第一步
//方案一,没有实现多次机会
public class login {
  public static void main(String[] args) {
      //定义正确的用户名和密码
      String userName = "admin";
      String userPwd = "123456";
      Scanner scanner = new Scanner(System.in);
      System.out.println("请输入用户名:");
      String user = scanner.nextLine();
      System.out.println("请输入密码:");
      String pwd = scanner.nextLine();
      if (userName.equals(user)&&userPwd.equals(pwd)){
          System.out.println("用户名和密码正确,登录成功!");
      }else {
          System.out.println("用户名和密码错误,登录失败!");
      }
  }
}
​
//方案二,简单优化,把登录写进方法中
public class Login2 {
  public static void main(String[] args) {
      Scanner scanner = new Scanner(System.in);
      System.out.println("请输入用户名:");
      String user = scanner.nextLine();
      System.out.println("请输入密码:");
      String pwd = scanner.nextLine();
      login(user,pwd);
​
  }
  public static void login(String user, String pwd){
      //定义正确的用户名和密码
      String userName = "admin";
      String userPwd = "123456";
      if (userName.equals(user)&&userPwd.equals(pwd)){
          System.out.println("用户名和密码正确,登录成功!");
      }else {
          System.out.println("用户名和密码错误,登录失败!");
      }
  }
}
​
//方案三,进一步优化,使用三元运算符
public class Login3 {
  public static void main(String[] args) {
      Scanner scanner = new Scanner(System.in);
      System.out.println("请输入用户名:");
      String user = scanner.nextLine();
      System.out.println("请输入密码:");
      String pwd = scanner.nextLine();
      System.out.println(login(user,pwd)?"用户名和密码正确,登录成功!":"用户名和密码错误,登录失败!");
  }
  //返回布尔类型
  public static boolean login(String user, String pwd){
      //定义正确的用户名和密码
      String userName = "admin";
      String userPwd = "123456";
      return userName.equals(user)&&userPwd.equals(pwd);
  }
}
​
//第二步,加上3次机会
public class Login4 {
  public static void main(String[] args) {
      //定义正确的用户名和密码
      String userName = "fumin";
      String userPwd = "123456";
      //机会次数
      int chance = 3;
      for (int i = 0; i <chance; i++) {
          Scanner scanner = new Scanner(System.in);
          System.out.println("请输入用户名:");
          String user = scanner.nextLine();
          System.out.println("请输入密码:");
          String pwd = scanner.nextLine();
          int remainChance = chance-i-1;
          //循环判断
          if(userName.equals(user)&&userPwd.equals(pwd)){
              System.out.println("用户名和密码正确,登录成功!");
              //结束循环
              break;
          }if(remainChance == 0){
              System.out.println("你已3次输错密码,账户已冻结!");
          }
          else{
              System.out.println("用户名和密码错误!您剩余:"+ remainChance +"次机会!");
          }
      }
​
  }
}

 

8.Object类的equals方法

Object类中的equals()方法默认是比较两个对象的内存地址是否相同,即直接判断this 和obj本身的值是否相等;只有重写了Object类中的equals()方法后,才能比较两个对象成员属性值是否相同。

注意:双等于号(==)默认也是比较两个对象的内存地址是否相同。

//第一个类Student
public class Student extends Object{
    private String name;
    private int age;

    //构造方法
    public Student(){

    }
    //通过有参构造方法给成员属性赋值
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    //重写equals方法,以比较两个成员属性的值
    @Override
    public boolean equals(Object obj) {
        //1.两个对象内存地址相同,this指参数s1,obj指参数s2
        if (this==obj){
            return true;
        }
        //2.两个对象类型是否相同
        if (obj==null||this.getClass()!=obj.getClass()){
            return false;
        }
        //比较两个对象属性值
        //String类型中的equals方法默认是比较属性值的大小。
        Student object = (Student) obj;
        return this.age==object.age && this.name.equals(object.name);
    }
}

//第二个类Test5
public class Test5 {
    public static void main(String[] args) {
        Student s1 = new Student("mayikt",22);
        Student s2 = new Student("mayikt",22);
        Mayikt mayikt = new Mayikt();
        //没有重写equals方法前,默认比较两个对象内存地址是否相同(结果肯定是false),重写后就是比较两个对象的属性值是否相同了。
        System.out.println(s1.equals(s2));
        System.out.println(s1.equals(mayikt));
    }
}

 

9.instanceof 关键字

instanceof 通过返回一个布尔值来指出,某个对象是否是某个特定类或该特定类的子类的一个实例。应用于防止类型强转时,程序抛出异常,保证代码的安全性。

如果 ojbect 是 class 的一个实例/实现类,则 instanceof 运算符返回 true。如果 ojbect 不是指定类的一个实例或 object 为 null,则返回 false。class 可以是类,也可以是接口。

instanceof 在Java 的编译和运行阶段有区别。在编译状态,class可以是object对象的父类、自身类、子类,均不会报错。如:cat instanceof AnimalParent(父类)或者cat instanceof Cat(自身类)均不报错。在运行状态,class是object对象的父类、自身类,不能是子类。前两种情况下result的结果为true,最后一种为false。但是class为子类时,在编译阶段不会报错(因为无法识别),但在程序运行阶段就会报错了,运行结果为false。

 

10.String类的replace方法

public class Test02 {
   public static void main(String[] args) {
       String str1 = "mayiktmeite1111";
       String str2 = "mayiktmeite1111mayiktmeite1111";
       //replace -替换指定内容(str1中的“1111”)
       String s1 = str1.replace("1111","yushengjun");
       System.out.println(s1);
       //replaceFirst -替换首次匹配的内容(str2前面部分的“1111”)
       String s2 = str2.replaceFirst("1111","ysj");
       System.out.println(s2);
  }
}

 

11.String类的split方法

public class Test03 {
   public static void main(String[] args) {
       String str = "武汉|孝感|北京|上海";
       //通过“|”符号(前面加\\作转义,防止出错)分割字符串,并返回数组类型的多个城市。
       //注意“|、*、\、^、:、.”符号都要转义。
       String[] arrays = str.split("\\|");
       System.out.println(arrays[0]);
       System.out.println(arrays[1]);
       System.out.println(arrays[2]);
       System.out.println(arrays[3]);
  }
}

 

12.ASCII码字符对照表

12.1 概念

ASCII码全称“美国信息交换标准代码,”简称“阿斯克码”,其作用是将字母、字符、数字、标点转换成计算机能识别的二进制。记住A和a就行了,其它的可依次推算(十进制)。

字符 十进制 二进制
A 65 01000001
a 97 01100001
0 48 00000000

 

12.2 实例

键盘录入一个字符串,统计该字符串中的大写字母、小写字母和数字出现的次数,不考虑其它字符。

思路:用ASCII码判断。如果是大写字母(A-Z)对应65-90;如果是小写字母(a-z)对应97-122;如果是数字字符(0-9)对应48-57。

代码:

public class Test02 {
  public static void main(String[] args) {
      /**
        * 思路:用ASCII码判断。
        * 如果是大写字母(A-Z)对应65-90;
        * 如果是小写字母(a-z)对应97-122;
        * 如果是数字字符(0-9)对应48-57。
        */
      Scanner sc = new Scanner(System.in);
      System.out.println("请在下面输入一段字符串,可统计大小写字母和数字出现的次数:");
      String str = sc.nextLine();
      int bigCount = 0;
      int smaCount = 0;
      int numCount = 0;
      for (int i = 0; i < str.length(); i++) {
          char ch = str.charAt(i);//用charAt()方法来获取字符串中的每个字符
          if (ch >=65 && ch <=90){
              //是大写字母
              bigCount++;
          } else if (ch >=97 && ch<=122) {
              //小写字母
              smaCount++;
          } else if (ch >=48 && ch<=57) {
              //是数字
              numCount++;
          }
      }
      System.out.println("大写字母出现的次数为:" + bigCount);
      System.out.println("小写字母出现的次数为:" + smaCount);
      System.out.println("数字出现的次数为:" + numCount);
​
  }
}

 

13.indexOf方法

public class Test5 {
   public static void main(String[] args) {
       String str = "mayiktmeiteAndmeite";
       //查找指定字符一次出现的下标(如果没找到则返回“-1”)
       System.out.println(str.indexOf("meite"));
       //看字符的长度
//       System.out.println("mayiktmeite".length());
       //从指定的下标(11)开始,查找指定字符(meite)的下标
       System.out.println(str.indexOf("meite",11));
  }
}

public class Test6 {
  public static void main(String[] args) {
      //indexOf要查找的字符 也可以是字符的ASCII码
      String str = "MaA66";
      //例如查找大写字母A(ASCII码为65)的下标
      System.out.println(str.indexOf(65));
  }
}

 

14.toLowercase方法

public class Test7 {
  public static void main(String[] args) {
      String str = "MasaMZ";
      System.out.println("将字符串中的大写字母转为小写:"+str.toLowerCase());
      System.out.println("将字符串中的小写字母转为大写:"+str.toUpperCase());
  }
}

 

15.String的底层实现

JDK1.8 String类型的底层实现基于char类型数组;而JDK1.9 String类型的底层实现基于byte类型数组。为什么要改呢?答:节省String占用jvm的内存空间。

 

16.java元空间

JDK1.8之前,称作“方法区、永久代”,JDK1.8开始,称作“元空间”。用于存放静态变量、class信息。new对象均存放在“堆内存”中。JDK1.7开始,字符串常量池 从“方法区”移动到了堆中存放。

 

17.Math类

17.1 概念

定义了许多执行基本数字运算的方法。它不能创建对象,因为它的构造方法是私有。但可以通过“类名.方法”调用其内部的静态方法。

17.2 常见方法

public class Test1 {
  public static void main(String[] args) {
      //abs:返回绝对值,结果为13
      System.out.println(Math.abs(-13));
      System.out.println("------Math.ceil-----");
      //ceil:传入一个小数,返回一个比它稍大的整数
      System.out.println(Math.ceil(6.6));//结果7.0
      System.out.println(Math.ceil(6.0));//结果6.0
      System.out.println(Math.ceil(-6.6));//结果-6.0
      System.out.println("------Math.floor-----");
      //floor:传入一个小数,返回一个比它稍小的整数
      System.out.println(Math.ceil(6.6));//结果6.0
      System.out.println(Math.ceil(6.0));//结果6.0
      System.out.println(Math.ceil(-6.6));//结果-7.
      System.out.println("------Math.round------");
      //floor:传入一个小数,返回一个四舍五入的整数(int类型)
      System.out.println(Math.round(6.6));//7
      System.out.println(Math.round(6.3));//结果6
      System.out.println("------Math.max/min------");
      //max/min:传入2个数字,返回其中较大或较小的那个数
      System.out.println(Math.max(6,66));//结果66
      System.out.println(Math.min(6,66));//结果6
      System.out.println("------Math.pow------");
      //pow:传入2个数字a和b,返回a的b次幂(也就是a的b次方)
      System.out.println(Math.pow(2,3));//结果8.0
      System.out.println("------Math.random------");
      //random:不传入数字,随机返回一个0与1之间的数字(不包括1)
      System.out.println(Math.random());
      //生成一个1~100之间的随机数(包含1和100),下面有2种方式
      System.out.println(Math.floor(Math.random()*100+1));
      System.out.println((int)(Math.random()*100+1));
  }
}

 

18.System类

System类由final修饰,无法被继承。

public class Test2 {
  public static void main(String[] args) {
      //exit:终止java虚拟机,0表示正常退出,其它表示异常退出
//       System.out.println("正常运行代码");
//       System.exit(0);
​
      //currentTimeMillis:获取当前系统时间,从1970/1/1开始计算,以ms为单位。
      //1s=1000ms 1min=60s
      long start = System.currentTimeMillis();
      for (int i = 0; i < 100000; i++) {
          System.out.println("mayikt");
      }
      long end = System.currentTimeMillis();
      System.out.println("执行100000次循环,耗时:"+(end-start)+" 毫秒");
  }
}

 

19.Arrays类(工具类)

19.1 设计思想

①构造方法用private修饰,外部无法new;②成员方法用public static 修饰,可用“类名.方法名”访问;③所有方法均为静态方法。

19.2 常用方法

//sort方法:可将字符类型数组按abc的顺序排列,可将数字类型数组从小到大排列
public class Test4 {
  public static void main(String[] args) {
      int[] arrs = {44,55,66,77,88};
       
      System.out.println(arrs);//默认是输出内存地址,不能这样写
​
      //调用MayiktArrays中自定义的sort方法,将数组中的数字从大到小排列并输出
      MayiktArrays.sort(arrs);
  }
}
​
//toString方法:将数组转化为字符串
public class Test5 {
  public static void main(String[] args) {
      char[] ch ={'d','c','b','a'};
      int[] num ={22,77,11,4,88,55};
      Arrays.sort(ch);
      Arrays.sort(num);
      System.out.println(Arrays.toString(ch));//结果:[a, b, c, d]
      System.out.println(Arrays.toString(num));//结果:[4, 11, 22, 55, 77, 88]
  }
}

 

20.基本数据类型包装类

20.1 包装类

用于基本数据类型与字符串之间的转化。每种基本数据类型都对应一个包装类。(提示:除了int和char特殊外,其余的包装类大写第一个字母即可)

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

20.2 实例1:Integer取值范围

public class Test6 {
  public static void main(String[] args) {
      //int类型的范围(最小和最大值)?使用Integer包装类中的方法计算
      //int是基本数据类型,Integer包装了int类型
      System.out.println("int最小值:"+Integer.MIN_VALUE);
      System.out.println("int最大值:"+Integer.MAX_VALUE);
  }
}

 

20.3 int/boolean 类型转 String 类型— valueOf

public class Test7 {
  public static void main(String[] args) {
      //通过有参构造方法传递“数字形式”的字符串
      Integer a = new Integer("666");
      System.out.println(a);
      System.out.println("------------");
      //Integer包装类中的valueOf方法,可将“数字形式”的字符串转为数字
      Integer b = Integer.valueOf("6666");
      System.out.println(b);
  }
}
​
public class Test8 {
  public static void main(String[] args) {
      //1.如何将int类型转化为String类型?
      int a = 66;
      //方法一:用空字符串与int拼接
      System.out.println(""+a);
      //方法二:用valueOf方法
      String a2 = String.valueOf(a);
      System.out.println(a2);
       
      //2.布尔类型转为String类型?
      boolean flag = true;
      String f = String.valueOf(flag);
      System.out.println(f);
  }
}

 

20.4 String类型转int/boolean类型

public class Test9 {
  public static void main(String[] args) {
  //1.String → int
      //将String转化为int,注意只有数字形式的String才能转化!
      String str = "123";
       
      //方法一:valueOf与intValue一起用
      Integer num = Integer.valueOf(str);
      System.out.println(num);
      //如果要直接返回int类型呢?
      int num1 = num.intValue();
      System.out.println(num1);
      System.out.println("-----分割线------");
       
      //方法二:parseInt一步到位(常用)
      int num2 = Integer.parseInt(str);
      System.out.println(num2);
       
       
      //2.String → boolean
      String flag = "true";//注意,如果String的值不是boolean值(true/false),转换后的值永远为false
      boolean b1 = Boolean.parseBoolean(flag);
      System.out.println(b1);
      System.out.println("---分割---");
       
      //3.String → double
      String s = "6.66";
      double d = Double.parseDouble(s);
      System.out.println(d);
  }
}

 

20.5 基本数据类型与包装类型的区别

①以int与Integer为例,int属于基本数据类型,而Integer属于类,是一个对象。②基本数据类型存放在栈空间中,而包装类存放在堆空间中。(所有对象和数组存放在堆中)③基本数据类型的默认值为0/false,而包装类的默认值为null。④输出包装类时,底层会调用toString方法,实际输出基本数据类型的值。⑤基本数据类型为值传递,包装类为引用传递。

提示:实际开发中,包装类比基本类型更常用。

 

20.6 装箱和拆箱

装箱:自动将基本数据类型转换为包装类型。拆箱自动将包装类型转换为基本数据类型。

Integer i = 5;//装箱
int j = i;//拆箱

public class Test12 {
    public static void main(String[] args) {
        /**
         * 小案例:字符串中的数据排序
         * 对字符串"97,16,36,18,50"中的数字从小到大排序,再输出。
         */
        String str ="97,16,36,18,50";
        //1.分割字符串,转化为int类型数组
        String[] s1 = str.split(",");//用“,”分割字符串里的数字
        int[] s2 = new int[s1.length];
        for (int i = 0; i < s1.length; i++) {
            s2[i] = Integer.parseInt(s1[i]);
        }
        //2.对int数组排序,再输出
        Arrays.sort(s2);
        for (int i = 0; i < s2.length; i++) {
            if (i != s2.length - 1){
                System.out.print(s2[i]+",");
            }else {
                System.out.print(s2[i]);
            }
        }
    }
}

 

21.Date类

21.1 构造方法

//分配一个Date对象,初始化时间(当前时间),精确到毫秒。
public Date();
​
//分配一个Date对象,表示从标准时间起指定的毫秒数。
public Date(Long date);
​
//实例1
public class Test02 {
  public static void main(String[] args) {
      //注意:使用Date类时,要引入java.util.Date,不要错误地引入到java.sql.Date中
      Date date1 = new Date();
      System.out.println(date1);
      //结果:Wed Aug 07 09:08:12 CST 2024(CST表示“中国标准时间”)
​
      System.out.println("-----------");
      //GMT(格林威治时间)
      long time = 1000 * 60 * 60;//代表1小时
      Date date2 = new Date(time);
      System.out.println(date2);
      //结果:1970-1-1 0:00:00 + 8小时(中国是+8区) +1小时 = 1970-1-1 9:00:00
​
  }
}

 

21.2 常用方法

//获取日期对象,从1970年1月1日0:00:00到现在的毫秒数,也叫“时间戳”。
public long getTime();
​
//设定时间,毫秒数。
public void setTime(Long time)
​
//实例2
public class Test03 {
  public static void main(String[] args) {
      //getTime()
      Date date1 = new Date();
      long t1 = date1.getTime();//获取1970-1-1 0:00:00到现在的毫秒数。
      System.out.println(t1);
      System.out.println("-----------");
​
      //setTime()
      long t2 = 1000*60*60;//表示:一小时
      date1.setTime(t2);//在1970-1-1 0:00:00的基础上,增加“t2”个小时。
      System.out.println(date1);
      //结果:Thu Jan 01 09:00:00 CST 1970(即1970-1-1 9:00:00)
  }
}

 

21.3 格式化日期

SimpleDateFormat用于格式化和解析日期。作用有:①对时间日期格式化处理;②把Date对象转化为“年月日时分秒”格式字符串;③把字符串转化为Date对象。

字母 含义
y 年,如yyyy
M 月,如MM
d 日,如dd
h 时(12小时制)
H 时(24小时制)
m 分,如mm
s 秒,如ss
yyyy年M月dd日 2024年8月10日
//1.把Date对象转化为日期字符串:format()
public class Test04 {
  public static void main(String[] args) {
      //创建一个日期对象
      Date date = new Date();
      System.out.println(date);
      //结果:Sat Aug 10 08:54:12 CST 2024
​
      //对创建的日期格式化,使其更加美观
      //创建一个格式对象
      SimpleDateFormat date1 = new SimpleDateFormat("yyyy年MM月dd日 H:mm:ss");
      System.out.println(date1.format(date));
      //结果:2024年08月10日 8:54:12
  }
}
​
​
//2.把日期字符串转化为Date对象:parse()
public class Test05 {
  //日期字符串转为Date类型,需要抛出异常
  public static void main(String[] args) throws ParseException {
      //创建一个需要格式化的日期字符串
      String dt = "2024年08月10日 8:54:12";
      //创建SimpleDateFormat对象,对其格式化(注意格式要与日期字符串一致,否则无法转换)
      SimpleDateFormat dt1 = new SimpleDateFormat("yyyy年MM月dd日 H:mm:ss");
      System.out.println(dt1.parse(dt));
      //结果:Sat Aug 10 08:54:12 CST 2024
  }
}

 

21.4 日期工具类的设计

//1.先创建一个DateUtil工具类
public class DateUtil {
   private static final String FORMAT_1 = "yyyy-MM-dd HH:mm:ss";//常量变量名必须大写(这是规范)
   
   //先将构造方法私有化,这样就可以直接通过类名访问,不需要再创建对象(下面是一个无参构造方法)
   private DateUtil() {
​
  }
​
   //常用方法
   //Date转String方法
   public static String DateToString(Date date,String format) {
       SimpleDateFormat formatter = new SimpleDateFormat(format);
       return formatter.format(date);
  }
​
   //String转Date方法
   public static Date StringToDate(String date,String format) throws ParseException {
       SimpleDateFormat formatter = new SimpleDateFormat(format);
       return formatter.parse(date);
  }
​
   //获取当前系统时间,直接转化为String类型
   public static String getCuDateString() {
       return DateToString(new Date(),FORMAT_1);
  }
​
}
​
​
//2.在Test06类中调用
public class Test06 {
   public static void main(String[] args) throws ParseException {
       //1.调用DateUtil中的Date转String方法
       String d1 = DateUtil.DateToString(new Date(), "yyyy-MM-dd HH:mm:ss");
       System.out.println(d1);
       //结果:2024-08-10 09:42:57
​
       //2.调用DateUtil中的String转Date方法(要手动抛出一个字符串异常)
       Date d2 = DateUtil.StringToDate("2024-08-10 09:39:48","yyyy-MM-dd HH:mm:ss");
       System.out.println(d2);
       //结果:Sat Aug 10 09:39:48 CST 2024
​
       //3.调用DateUtil中的"获取当前系统时间,直接转化为String类型"方法
       String s3 = DateUtil.getCuDateString();
       System.out.println(s3);
       //结果:2024-08-10 10:01:14
  }
}

 

22.Calendar日历类

22.1 获取系统时间

public class Test07 {
  public static void main(String[] args) {
      //获取Calender对象,多态机制(因为抽象类不能创建对象)
      Calendar c = Calendar.getInstance();
      System.out.println(c);
      //结果:java.util.GregorianCalendar[time=1723258789560,areFieldsSet=true,areAllFieldsSet=true,lenient=true,
      // zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,
      // transitions=19,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2024,MONTH=7,
      // WEEK_OF_YEAR=32,WEEK_OF_MONTH=2,DAY_OF_MONTH=10,DAY_OF_YEAR=223,DAY_OF_WEEK=7,DAY_OF_WEEK_IN_MONTH=2,AM_PM=0,
      // HOUR=10,HOUR_OF_DAY=10,MINUTE=59,SECOND=49,MILLISECOND=560,ZONE_OFFSET=28800000,DST_OFFSET=0]
      System.out.println("------------");
​
      //获取年
      int year = c.get(Calendar.YEAR);
      //获取月,从0开始,因此实际要+1
      int month = c.get(Calendar.MONTH)+1;
      //获取日
      int day =c.get(Calendar.DAY_OF_MONTH);
      System.out.println("当前的日期为:"+year+"年"+month+"月"+day+"日");
      //结果:当前的日期为:2024年8月10日
  }
}

 

22.2 修改获取的系统时间

public class Test08 {
  public static void main(String[] args) {
      //Calendar常用方法
      Calendar c = Calendar.getInstance();
      //修改获取的系统日期,使用.add()方法,正数为增加,负数为减少
      c.add(Calendar.YEAR,1);//在当前年份的基础上,增加1年
      c.add(Calendar.MONTH,-1);//在当前月份的基础上,减1个月
      c.add(Calendar.DAY_OF_MONTH,5);//在当前日的基础上,加5天
​
      //直接修改成你想要的日期,使用.set()方法
      c.set(2060,8,8,12,30,00);//年月日时分秒,可以只设置一部分
​
      //获取年
      int year = c.get(Calendar.YEAR);
      //获取月,从0开始,因此实际要+1
      int month = c.get(Calendar.MONTH)+1;
      //获取日
      int day =c.get(Calendar.DAY_OF_MONTH);
      System.out.println("当前的日期为:"+year+"年"+month+"月"+day+"日");//这里最小只获取到日
​
  }
}

 

22.3 小案例:2月有多少天

public class Test09 {
  public static void main(String[] args) {
      //需求:键盘录入一个年份,可以显示其2月有多少天,并判断该年是闰年还是平年?
      //注意:平年的2月是28天,闰年的2月是29天
​
      System.out.println("请在下方输入一个年份:");
      Scanner sc = new Scanner(System.in);
      int sc1 = sc.nextInt();
​
      //创建日期对象,多态机制
      Calendar c = Calendar.getInstance();
      //修改年月日为:输入的年,3月,1日
      c.set(sc1,2,1);//因为月是从0开始算,所以2代表3月
      //在3月1日的基础上减去1天,就到了2月最后一天
      c.add(Calendar.DAY_OF_MONTH,-1);
      //获取日
      int day = c.get(Calendar.DAY_OF_MONTH);
      System.out.println(sc1+"年的2月有:"+day+"天");
      System.out.println(day==28?sc1+"年是平年":sc1+"年是闰年");
​
  }
}

 

23.异常

23.1 定义

程序执行报错或出现了不正常现象。JVM默认情况下,如果执行报错,会直接中断,后面的代码不会再执行。

public class Test01 {
  public static void main(String[] args) {
      int[] arr = {1,2,3};
      System.out.println(arr[4]);
      //ArrayIndexOutOfBoundsException: 越界异常
       
      User user = null;
      user.addUser();
      //NullPointerException:空指针异常(因为你没有new出来对象,没有调用方法)
​
  }
}

 

23.2 异常处理

//1.语句:try...catch...
​
//2.格式:
try{
可能出现异常的代码;
}catch(异常类名 变量名){
异常处理的代码;
}
​
//3.执行流程:
出现异常时,会生成一个异常类对象。Java运行并收到异常对象时,会到catch中找匹配的异常类,并做相应处理,程序还可继续往下执行,不会因为异常而中断。但如果没有在catch中找匹配的异常类依然会中断代码的执行哦。
​
//4.实例:
public class Test03 {
  public static void main(String[] args) {
      System.out.println("代码开始");
      try{
          //运行一段可能有问题的代码
          a1();
      }catch(Exception e){
          //捕获异常
          System.out.println("你访问的数组下标越界了!");
          e.printStackTrace();//在程序结尾显示异常的类型和位置(可省略)
      }
      System.out.println("代码结束");
  }
​
  public static void a1(){
      int[] arr = {8,9,10};
      System.out.println(arr[3]);
  }
}
​
​
//5.Throwable的成员方法
public String getMessage:返回此throwable详细消息字符串。
public String toString:返回此可抛出的简短描述。
public void printStrackTrace()将异常信息输出到控制台。
//java中的两类异常处理
public class Test06 {
  /**
    * java中 异常分为2类
    * 1.编译时异常,.java源代码 编译成.class文件 之间发生的异常,必须处理否则无法编译。
    * 2.运行时异常,编译成.class文件后,在运行时发生的异常,不一定要处理。
    */
  public static void main(String[] args) throws Exception{
      a1();
      a2();
      a3();
      a4();
  }
  //Exception包括了编译异常和运行时异常,前者必须throws或者try...catch处理。
  public static void a1() throws Exception{
      int[] arr = new int[3];
      System.out.println(arr[4]);//数组下标越界异常
  }
  public static void a2() throws Exception{
​
  }
  public static void a3() throws Exception{
​
  }
  //调用a4()方法时,不需要在main方法后throws Exception或在该调用时用try...catch捕获异常,因为ArrayIndexOutOfBoundsException属于运行时异常,可以不做处理。
  public static void a4() throws ArrayIndexOutOfBoundsException{
​
  }
}

 

23.3 自定义异常

//1.自定义一个login异常类(用于抛出编译时异常)
public class LoginException extends Exception {
//本类继承了Exception父类,因此可抛出编译时异常
  //创建一个登录异常的有参构造方法,将异常内容传到父类去
  public LoginException(String message) {
      super (message);
  }
}
​
//2.在Test08类中调用
public class Test08 {
  /**
    * 注意:用throws处理异常时,异常下面的代码将不会执行;而用try...catch捕获异常时,异常下面的代码还可执行。
    * @param args
    * @throws Exception
    */
  public static void main(String[] args) throws Exception{
      Scanner sc = new Scanner(System.in);
      System.out.println("请在下方输入用户名:");
      String userName = sc.nextLine();
      System.out.println("请在下方输入密码:");
      String pwd= sc.nextLine();
      login(userName,pwd);
  }
  public static void login(String userName, String pwd) throws Exception{
      if(!(userName.equals("admin") && pwd.equals("123456"))){
          //如果用户输入的名字和密码不正确就抛出异常,提示不正确
          throw new LoginException("你输入的用户名或密码不正确!");
      }
      System.out.println("用户名和密码正确,登录成功!");
  }
}
​
​
//3.如果想自定义一个login异常类用于抛出运行时异常,只需要改为继承RuntimeException父类即可。需要注意的是,该异常不强制要用try...catch来捕获,也可正常运行(这点与编译时异常不同)。

 

温馨提示
我也是有底线的~
点赞0
评论 抢沙发

请登录后发表评论

    暂无评论内容