JavaSE-3异常&常用类

一、异常

1、异常体系

  • java.lang.Throwable类是 Java中所有错误或异常的超类
  • 常用方法
    • public void printStackTrace():打印异常信息是最全的,包括异常类型、信息、以及出现的行数等
    • public String toString() :输出异常类型和设置的异常信息
    • public String getMessage():输出设置的异常信息
  • 主要有两个子类

1)错误Error

  • 错误java.lang.Error: 无法处理的错误,只能事先避免。如java.lang.StackOverflowErrorjava.lang.OutOfMemoryError

2)异常Exception

  • 异常java.lang.Exception: 异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的。又分为两类
    • 编译时异常:java.lang.Exception包下除了RuntimeException之外的所有类
      • 没有任何的语法格式错误,但编译时JVM检查到存在安全隐患所报出的异常,如FileNotFoundExceptionSQLException
    • 运行时异常java.lang.RuntimeException:编译时没有发生任何语法格式错误,在运行时出现了的异常,如NullPointerExceptionClassCastException

2、异常处理

  • Java异常处理的5个关键字:try、catch、finally、throw、throws
  • 使用场景
    • 如果处理异常之后,还想让后续的代码正常执行,则使用try...catch
    • 如果方法之间是递进关系(调用),我们可以先throws,等到最后用try...catch做统一的异常处理

1)throws声明异常

  • 将异常抛给调用者进行解决
    • 在方法声明上使用throws关键字来声明异常,表示当前方法不处理异常,而是向上抛给调用者来处理
  • 格式修饰符 返回值类型 方法名 () throws 异常类名1,异常类名2,......,异常类名n {}
  • 注意
    • 如果throws后的多个异常之间有子父类继承关系,我们可以直接throws父类异常
    • 如果不知道多个异常之间是否有子父类继承关系,我们可以直接throws Exception
    • 子类重写方法声明的异常类型不能大于父类方法的异常类型,可以相同、或者是其子异常或子类方法不声明异常

2)try…catch捕获异常

  • 格式

    try {
        可能产生异常的代码
    } catch(异常类型形参) { //catch可以有多个,当多个异常类型之间构成继承关系时,子类型必须放在父类型之前,或者只处理父异常
        处理异常的代码 //如:记录日志/打印异常信息/继续抛出异常
    } catch(异常类型形参) {
        处理异常的代码 
    } finally {
        //finally中的代码总会执行,即使catch中也出现异常
        //一般将资源关闭的代码放到finally代码块,因为有一些对象GC回收不了,需要我们手动关闭。如:连接对象,IO流对象,Socket对象
    }
    
  • 在实际开发中,避免在catch里面出现return语句

    public static int method (int num) {
        try {
            throw new IOException("IO异常");
        } catch (IOException e) {
            e.printStackTrace();
            return 3;// JVM本来要执行,在执行之前发现了finally,return暂缓执行
        } finally {
            System.out.println("资源关闭");
            return 4;//最终返回4
        }
    }
    

3)手动抛出异常对象

  • throw new 异常类名()

  • throw用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行

    ServiceException tw = new ServiceException("abc");//创建异常对象不抛出不会报错
    throw tw;//1.throw语句后不能直接跟语句,永远无法执行到;  2.如果抛出的是编译时异常,则编译报错,必选进行处理
    System.out.println("这句永远执行不到,编译报错");
    

3、自定义异常类

  • 自定义编译异常:继承Exception
  • 自定义运行时异常:继承RuntimeException
  • 提供有参构造方法,便于设置异常信息

二、常用类

1、Object

  • java.lang.Object类是Java语言中的根类,即所有类的父类

  • 常用方法

    /*
    toString()返回的是“对象的运行时类型 @ 对象的hashCode值的十六进制形式"
    如果想输出对象的属性值,就重写Object中的toString方法
    */
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
    
    /*
    比较两个对象的地址值是否相等
        == 针对于基本数据类型来说,比较的是值 
        == 针对于引用数据类型来说,比较的是地址值
    如果想比较对象的属性值,就重写Object中的equals方法
    */
    public boolean equals(Object obj) {
        return (this == obj);
    }
    @IntrinsicCandidate
    public native int hashCode();
    
    /*
    复制一个属性值一样的新对象
      需要被克隆的对象实现Cloneable接口并重写clone方法
    */
    @IntrinsicCandidate
    protected native Object clone() throws CloneNotSupportedException;
    
    //获取对象的运行时类型-见反射章节
    @IntrinsicCandidate
    public final native Class<?> getClass();
    
    //见多线程章节
    @IntrinsicCandidate
    public final native void notify();
    @IntrinsicCandidate
    public final native void notifyAll();
    public final void wait() throws InterruptedException {
        wait(0L);
    }
    public final native void wait(long timeoutMillis) throws InterruptedException;
    public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
        //...
    }
    

2、比较大小接口

1)java.lang.Comparable

  • 基本类型数据需要比较大小,使用比较运算符即可

  • 引用数据类型比较大小,可以实现java.lang.Comparable接口,并重写compareTo方法

    public class Person implements Comparable<Person> {
        String name;
        int age;
    
        public Person() {
        }
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        @Override
        public int compareTo(Person person) {
            //大于0,则当前对象大
            //小于0,则当前对象小
            //等于0,则两个对象相等
            return this.age - person.age;
        }
    
        public static void main(String[] args) {
            Person p1 = new Person("张三", 18);
            Person p2 = new Person("王五", 20);
            System.out.println(p1.compareTo(p2)); // -2
        }
    }
    

3)java.util.Comparator

  • 使用场景:如果一个类没有实现Comparable接口,且又不方便修改源码;或者实现了Comparable接口,但不想按照它预定义的方法比较大小,又不能随意修改。可以使用java.util.Comparator接口

  • 创建比较器类:实现java.util.Comparator接口,并重写方法

    import java.util.Comparator;
    public class Test01 {
        public static void main(String[] args) {
            int compare = new Comparator<Person>() {
                @Override
                public int compare(Person o1, Person o2) {
                    return o1.getAge() - o2.getAge();
                }
            }.compare(new Person("zhang3", 18), new Person("li4", 20));
            System.out.println(compare); // -2
        }
    }
    

3、字符串相关

1)java.lang.String

  • Java中所有字符串字面值(如 “abc” )都是此类的实例

  • 字符串的对象是不可变对象,意味着一旦进行修改,就会产生新对象

  • jdk8中String底层是一个被final修饰的char数组private final char[] value,一个char类型占2个字节

  • jdk9后String底层是一个被final修饰的byte数组private final byte[] value,一个byte类型占1个字节

  • 常用构造方法

    String();
    String(String original);//根据字符串创建String对象
    String(char[] value);//根据char数组创建String对象
    String(byte[] bytes);//通过使用操作系统的默认字符集解码指定的 byte 数组,构造一个新的 String
    //操作系统默认字符集:GBK,一个中文占2个字节;UTF-8,一个中文占3个字节
    //Idea启动时可以指定默认字符集,如: -Dfile.encoding=UTF-8 
    
    //String 变量名 = ""//简化形式
    
  • 常用方法

    boolean equals(String s);
    boolean equalsIgnoreCase(String s);
    
    int length();
    String concat(String s);// 字符串拼接,返回新串儿
    char charAt(int index); // 根据索引获取对应的字符
    int indexOf(String s); // 获取指定字符串在大字符串中第一次出现的索引位置
    String subString(int beginIndex); // 截取字符串,从指定索引开始截取到最后,返回新串儿
    String subString(int beginIndex,int endIndex); // 截取字符串,含头不含尾,返回新串儿
    
    char[] toCharArray(); // 将字符串转成char数组
    byte[] getBytes(); // 将字符串转成byte数组
    byte[] getBytes(String charsetName); // 按照指定的编码   
    String replace(CharSequence c1,CharSequence c2); // 替换字符 String类实现了CharSequence接口
    
    String[] split(String regex); //按照指定的规则分割字符串 regex写的是正则表达式
    
    boolean contains(String s);
    boolean endsWith(String s);
    boolean startsWith(String s);
    String toLowerCase();
    String toUpperCase();
    String trim();
    
  • 面试题

    public static void main(String[] args) {
        String s1 = "HelloWorld";
        String s2 = "HelloWorld";
        String s3 = new String("HelloWorld"); 
        String s4 = new String("HelloWorld");
        String s5 = "Hello";
        String s6 = "World";
    
        System.out.println(s1==s2);//true 在常量池中创建,并指向同一地址
        System.out.println(s1==s3);//false
        System.out.println(s2==s3);//false
        System.out.println(s3 == s4); // false
        System.out.println("============================");
        /* 字符串拼接规则:
        1.如果等号右边是字符串字面值拼接,不会产生新对象
        2.如果等号右边有变量参数拼接,会产生新字符串对象
        */
        System.out.println(s1 == ("Hello" + "World")); //ture
        System.out.println(s1 == (s5 + "World")); // false
        System.out.println(s1 == (s5 + s6) ); //false
        System.out.println(s3 == (s5 + s6) ); //false
    }
    

2)java.lang.StringBuilder

  • 一个可变的字符序列,不保证同步(线程不安全,但效率高)
  • 作用:拼接字符串
    • String每拼接一次,就会产生新的字符串对象,如果拼接次数多了,会占用内存,效率比较底
    • StringBuilder底层自带缓冲区,拼接字符串之后都会在此缓冲区中保存,在拼接的过程中,不会随意产生新对象,节省内存
  • 特点
    • 底层自带缓冲区,此缓冲区是没有被final修饰的byte数组,默认长度为16
    • 如果超出了数组长度,数组会自动扩容
    • 默认每次扩容老数组的2倍+2,如果一次性添加的数据超出了默认的扩容数组长度(2倍+2),则以该数据长度扩容
  • 常用方法
    • public StringBuilder append(任意类型数据)
    • public StringBuilder reverse()字符串翻转
    • public String toString() 转为String后,可以使用String中的方法进行处理。而用StringBuilder拼接字符串是为了效率

3)java.lang.StringBuffer

  • StringBuffer和StringBuilder的API基本一样(线程安全,效率低)

4、数字相关

1)java.lang.Math

  • final修饰的工具类,都是静态方法,私有构造方法,封装了基本的数学运算方法

  • 常用方法

    static int abs(xx a);
    static double ceil(xx a);// 向上取整
    static double floor(xx a);// 向下取整
    static long round(xx a);// 四舍五入
    static int max(xx a, xx b);
    static int min(xx a, xx b);
    static double random();// 返回[0,1)的随机值
    

2)java.math.BigInteger

  • BigInteger类:处理比long还要大的整数

    BigInteger(String val);// 参数的格式必须是数字形式
    
    BigInteger add(BigInteger val);
    BigInteger subtract(BigInteger val);
    BigInteger multiply(BigInteger val);
    BigInteger divide(BigInteger val);
    BigInteger remainder(BigInteger val);
    
    int intValue();// 将BigInteger转成int
    long longValue();// 将BigInteger 转成 long
    

3)java.math.BigDecimal

  • BigDecimal类:主要是解决float和double直接做运算出现的精度损失问题,前提是构造要使用new BigDecimal(String)

    BigDecimal(String val);// 参数的格式必须是数字形式
    
    BigDecimal add(BigDecimal val);
    BigDecimal subtract(BigDecimal val);
    BigDecimal multiply(BigDecimal val);
    BigDecimal divide(BigDecimal val);
    /*
    divisor:除号后面的那个数
    scale:指定保留几位小数
    roundingMode:取舍方式   ROUND_UP 向上加1;ROUND_DOWN 直接舍去; ROUND_HALF_UP 四舍五入
     */
    BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode); 
    BigDecimal remainder(BigDecimal val);
    

3)java.util.Random

  • public int nextInt(int n)在指定范围内随机生成一个整数,范围从[0,n)

    import java.util.Random;
    public class Test01 {
        public static void main(String[] args) {
            Random random = new Random();
            //public 
            System.out.println(random.nextInt(10));// 0-9
            System.out.println(random.nextInt(10) + 1);// (0-9)+1 -> 1-10
            System.out.println(random.nextInt(100) + 1);// (0-99)+1 -> 1-100
            System.out.println(random.nextInt(900) + 100);// (0-899)+100 -> 100-999
        }
    }
    

5、日期相关

1)java.util.Date

  • 表示特定的瞬间,精确到毫秒
import java.util.Date;
public class Test01 {
    public static void main(String[] args) {
        //1、Date() -> 获取当前系统时间
        Date date1 = new Date();
        System.out.println("date1 = " + date1); //Sun Oct 19 13:45:43 CST 2025
        //2、Date(long time) -> 根据毫秒值生成时间。毫秒值是从时间原点(1970年1月1日 0时0分0秒,UNIX系统起始时间)开始算,叫做格林威治时间,在0时区上
        Date date2 = new Date(1000L);
        System.out.println("date2 = " + date2);//Thu Jan 01 08:00:01 CST 1970

        //1.void setTime(long time)
        date1.setTime(3000L);
        System.out.println("date1 = " + date1); //Thu Jan 01 08:00:03 CST 1970
        //2.long getTime()
        System.out.println(date2.getTime()); //1000
    }
}

2)java.util.Calendar

  • 日历类,抽象类
import java.util.Calendar;
import java.util.Date;
public class Test01 {
    public static void main(String[] args) {
        //1.Calendar getInstance() 通过Calendar的子类创建Calendar对象
        Calendar calendar = Calendar.getInstance();
        //2.int get(int field) ->返回给定日历字段的值
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        System.out.println("year = " + year); //year = 2025
        System.out.println("month = " + month); //month = 9  注意:实际月份=9+1
        //3.void set(int field, int value)  :将给定的日历字段设置为指定的值
        calendar.set(Calendar.YEAR,2018);
        System.out.println(calendar.get(Calendar.YEAR)); //2018
        //4.void add(int field, int amount) :根据日历的规则,为给定的日历字段添加或者减去指定的时间量
        calendar.add(Calendar.YEAR,-1);
        System.out.println(calendar.get(Calendar.YEAR)); //2017
        //5.void set(int year, int month, int date) -> 直接设置年月日
        calendar.set(2018,1,3);
        //6.Date getTime():将Calendar转成Date对象
        Date date = calendar.getTime();
        System.out.println("date = " + date); //date = Sat Feb 03 13:56:36 CST 2018
    }
}

3)java.text.SimpleDateFormat

  • 可以将日期时间和字符串做转换
public static void main(String[] args) throws ParseException {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    //1.String format(Date date) -> 将Date对象按照指定的格式转成String
    String time1 = sdf.format(new Date());
    System.out.println("time1 = " + time1);
    //2.Date parse(String source) throws ParseException-> 将符合日期格式的字符串转成Date对象
    String time2 = "2018-2-3 1:2:3";
    Date date = sdf.parse(time2);
    System.out.println("date = " + date); //date = Sat Feb 03 01:02:03 CST 2018
}

6、日期相关(JDK1.8)

1)java.time.LocalDate、LocalTime、LocalDateTime

public static void main(String[] args) throws ParseException {
    //1、创建LocalDate对象
    LocalDate localDate = LocalDate.now();
    System.out.println("localDate = " + localDate); //localDate = 2025-10-19
    LocalDate localDate1 = LocalDate.of(2018, 1, 2); //localDate1 = 2018-01-02
    System.out.println("localDate1 = " + localDate1);

    //2、创建LocalDateTime对象
    LocalDateTime localDateTime = LocalDateTime.now();
    System.out.println("localDateTime = " + localDateTime);//localDateTime = 2025-10-19T15:21:55.283423200
    LocalDateTime localDateTime1 = LocalDateTime.of(2018, 1, 2, 3, 4, 5);
    System.out.println("localDateTime1 = " + localDateTime1); //localDateTime1 = 2018-01-02T03:04:05

    // 3、获取年、月、日
    System.out.println(localDate.getYear());//2025
    System.out.println(localDate.getMonthValue());//10
    System.out.println(localDate.getDayOfMonth());//19

    // 4、修改年、月、日,支持链式调用
    LocalDate localDate2 = localDate.withYear(2017).withMonth(2).withDayOfMonth(3);
    System.out.println("localDate2 = " + localDate2); //localDate2 = 2017-02-03

    // 5、设置日期字段的偏移量,方法名plus开头,向后偏移;方法名minus开头,向前偏移
    LocalDate localDate3 = localDate.minusYears(3L).plusYears(1);;
    System.out.println("localDate3 = " + localDate3);//localDate3 = 2023-10-19
}

2)java.time.Period、Duration

//Period.between 计算两个日期之间的差值
LocalDate local1 = LocalDate.of(2018, 12, 11);
LocalDate local2 = LocalDate.of(2020, 11, 11);
Period period = Period.between(local1, local2); //period = P1Y11M
System.out.println("period = " + period);
System.out.println(period.getYears());//1年
System.out.println(period.getMonths());//又11个月
System.out.println(period.getDays());//零0天
System.out.println(period.toTotalMonths()); //共23个月

//Duration.between 计算两个时间之间的差值
LocalDateTime localDateTime1 = LocalDateTime.of(2018, 12, 11,1,2,3);
LocalDateTime localDateTime2 = LocalDateTime.of(2020, 11, 11,11,22,33);
Duration duration = Duration.between(localDateTime1, localDateTime2);
System.out.println("duration = " + duration);//duration = PT16834H20M30S
System.out.println(duration.toDays()); //共701天
System.out.println(duration.toHours()); //共16834小时
System.out.println(duration.toMinutes());//共1010060分
System.out.println(duration.toSeconds());//共60603630秒
System.out.println(duration.toMillis()); //共60603630000毫秒

3)java.time.format.DateTimeFormatter

public static void main(String[] args) throws ParseException {
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    /*
        String format(TemporalAccessor temporal)-> 将日期对象按照指定的规则转成String
         */
    System.out.println(dtf.format(LocalDateTime.now()));

    /*
        TemporalAccessor parse(CharSequence text)-> 将符合规则的字符串转成日期对象
         */
    TemporalAccessor temporalAccessor = dtf.parse("2018-01-02 03:04:05");
     /* 将TemporalAccessor转成我们常见的LocalDateTime日期对象
     注意:
       TemporalAccessor接口,子接口有Temporal
       Temporal接口的实现类:LocalDate LocalDateTime
        */
    LocalDateTime localDateTime = LocalDateTime.from(temporalAccessor);
    System.out.println("localDateTime = " + localDateTime);
}

7、系统相关

1)java.lang.System

  • final修饰的工具类,private构造器,静态方法
  • 常用方法
    • public static native long currentTimeMillis():返回以毫秒为单位的当前时间
    • public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) :复制数组,从源数组的指定索引开始,到目标数组的指定索引开始,复制length个元素
    • public static void exit(int status): 终止当前正在运行的 Java 虚拟机
    • static String getProperty(String key):获取某个系统属性

2)java.lang.Runtime

  • 每个Java程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接
  • 常用方法
    • public static Runtime getRuntime(): 返回与当前 Java程序相关的运行时对象
    • public long totalMemory():返回 Java 虚拟机中的内存总量。此方法返回的值可能随时间的推移而变化,这取决于主机环境
    • public long freeMemory():返回 Java 虚拟机中的空闲内存量

8、其他

1)java.lang.Arrays

  • 工具类,私有构造方法,封装了对数组的各种操作
  • 常用方法
    • static int binarySearch(int[] a, int key) :要求数组有序,在数组中查找key是否存在,如果存在返回第一次找到的下标,不存在返回负数

    • static int[] copyOf(int[] original, int newLength) :根据original原数组复制一个长度为newLength的新数组,并返回新数组

    • static int[] copyOfRange(int[] original, int from, int to) :复制original原数组的[from,to)构成新数组,并返回新数组

    • static void sort(int[] a) :将数组元素按照从小到大进行排序

    • static void sort(int[] a, int fromIndex, int toIndex) :将数组的[fromIndex, toIndex)部分按照升序排列

    • static String toString(int[] a) :把数组的元素拼接为一个字符串,形式为:[元素1,元素2,元素3。。。]

2)java.util.Scanner

  • 读取键盘录入的基本数据类型和String类型的数据
/*
nextInt() 输入整数int型的
next():录入字符串 -> 遇到空格或回车就结束录入了,如果录入的数据是"a b",回车后只接收到a
nextLine():录入字符串 -> 遇到回车就结束录入了
避免nextLine()和其他next方法混用
*/

三、包装类

  • 包装类就是基本类型对应的类

    • byte->Byte;short->Short;long->Long;float->Float;double->Double;boolean->Boolean
    • int->Integer;char->Character
  • 基本数据类型和包装类之间的转换

    • 装箱:将基本数据类型转为对应的包装类后,就可以使用包装类中的方法操作数据

      • 通过包装类的静态方法Integer.valueOf(123)
    • 拆箱:将包装类转为基本数据类型后,就可以做算数运算

      • 通过包装类的实例方法 Integer对象.intValue()
    • JDK5增加了自动装箱拆箱

      Double d1 = 1.0;
      double d2 = 1.0;
      System.out.println(d1==d2);//true 和基本数据类型比较会自动拆箱,比较数据值
      Integer i = 1000;
      double j = 1000;
      System.out.println(i==j);//true  会先将i自动拆箱为int,然后根据基本数据类型“自动类型转换”规则,转为double比较
      
  • 基本数据类型和字符串之间的转换

    • 基本数据类型-》字符串
      • (常用)通过 + 拼接,如 String str = 123 +"";
      • 通过String类的静态方法 String.valueOf(123)
      • 通过包装类的静态方法 Integer.toString(123)
    • 字符串-》基本数据类型
      • (常用) 通过包装类(除了Character)的静态方法,如Integer.parseInt("123")
      • 先把字符串转为包装类,然后可以自动拆箱为基本数据类型,如Integer.valueOf("123")
      • 注意:如果字符串参数的内容无法正确转换为对应的基本类型,则会抛出java.lang.NumberFormatException 异常
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值