Javase复习-java常见API和异常

211 阅读13分钟

java之常见API和异常

API

1.API

Api即Application ProgrammingInterface(应用程序编程接口)。java中的API指的是JDK中提供的各种功能的java类,这些类把提层封装,我们不关系如何实现,只关心如何使用即可。

 // 例如 生成随机数、控制台输出、字符串等
 new Random().nextInt(); 
 System.out.println("");
 new Strng();

2.Object类

  • 问:Object中都有哪些方法呢?

    • 答:在Object中只有一个无参数的构造方法。我们子类会默认调用父类中的无参构造方法。
      1. clone() 克隆方法(复制对象)
      2. equals(Object obj) :比较两个对象是否相等
      3. finalize() -----jvm的gc机制(已经过时)
      4. getClass ---获取该对象的class 运行时类
      5. hashCode ---返回该对象的哈希码值 hashMap集合
      6. notify(), notifyAll(),wait(),wait(long timeoutMillis) --多线程之间的通讯会使用到
      7. toString() ---返回对象的字符串表示形式

3. Object类 toString()

对于System.out.println()

  • println方法调用了 String s = String.valueOf(obj类的对象);
  • valueOf: return (obj == null) ? "null" : obj.toString();
  • obj.toString : return getClass().getName() + "@" + Integer.toHexString(hashCode());
  • 即 toString 获得该类的路径 + @+ 对象的哈希值 转换为字符串输出回来

重写toString()方法

一般情况下 对象重写了toString 输出对象中成员属性值

  • Object中toString()的目的就是给我们对象重写的,输出对象中的成员属性值

4. String字符串

String的底层实现

         String str = "lanshuqian";
         System.out.println(str); //lanshuqian
         // 如果想使用char保存字符串的话  我们需要要创建一个char[] 数组
         char[] value  = {'l','a','n','s','h','u','q','i','a','n'};
         System.out.println(value);  //lanshuqian
  • jdk8中String底层就是基于 char[]实现的
  • jdk9中String底层是基于byte[]数组实现的

4.1 String中split()方法

split表达式 其实就是一个正则表达式 * ^ | 等符号必须加转义字符 \

  String str = "兴城市|北京市|上海市|孝感市";
         // 通过 |  来进行分割字符串 最终返回数组类型
         String[] split = str.split("\|");
         System.out.println(split[0]);
         System.out.println(split[1]);
         System.out.println(split[2]);
         System.out.println(split[3]);
 --------------------------
     console:
 兴城市
 北京市
 上海市
 孝感市

4.2 IndexOf()

         //查找字符 wjy
         String str = "lanshuqianwjy";
         // 1. 如果存在 wjy 就返回 开始时的下标位置 不存在返回-1
         int findWjy = str.indexOf("wjy");
         System.out.println(findWjy);  //10
 ​
         // 2. 我想知道 第二个wjy开始的下标 从13开始计数
         String str2 = "lanshuqianwjyAndwjy";
         int secondWjy = str2.indexOf("wjy", 12);
         System.out.println(secondWjy);  //16
  public static void main(String[] args) {
         String str = "MaA644";
         // 65 为 'A'
         int a = str.indexOf(65);
         int i = str.indexOf(97);
         System.out.println(a);  //2
         System.out.println(i);  //1
     }

4.3 StringApi帮助文档

  • toLowerCase()
  • toUpperCase()

5. String中的equals()方法

  String str1 ="lanshuqian1";
 String str2 = "lanshuqian2";
 //比较两个字符串的值是否相等  相等返回true
 System.out.println(str1.equals(str2));  //false

第一个对象最好确认是非空的,否则会出现NPE,所以编码习惯应该把可能为空的写在后面

  • 底层原理解析:

    • Object类中equals方法 默认比较两个对象的内存地址是否相同
    • 比较两个字符串 值(value) 对应的char[]数组 存放的元素值 是否都是相同的 相同true 不相同false
  public boolean equals(Object anObject) {
      // String.equals()先比较两个字符串的地址是否相同
         if (this == anObject) {
             return true;
         }
      // 判断比较的类型是否是String类型
         if (anObject instanceof String) {
             //强转 String 开始
             String anotherString = (String)anObject;
             int n = value.length;
             if (n == anotherString.value.length) {
                 char v1[] = value;
                 char v2[] = anotherString.value;
                 int i = 0;
                 while (n-- != 0) {
                     if (v1[i] != v2[i])
                         return false;
                     i++;
                 }
                 return true;
             }
         }
         return false;
     }

String中equals()方法原理

 package com.wang.day01;
 ​
 public class Test05 {
     public static void main(String[] args) {
         /**
          * 定义两个char类型数组
          */
         char[] str1 = {'m', 'a', 'y', 'i', 'k', 't'};
         char[] str2 = {'m', 'a', 'y', 'i', 'k', 't'};
         System.out.println(compare(str1, str2));
 ​
     }
 ​
     public static boolean compare(char[] str1, char[] str2) {
         //默认返回true;
         // 1.比较两个char类型的长度是否相同
         if(str1.length != str2.length){
             //两个char类型长度都不一致没必要比较char[]中的元素是否相同
             return false;
         }
         int n = str1.length; //获取str1的长度
          int i = 0;
         while (n-- != 0){
             // 通过循环的形式比较两个char类型数组 对应的 index 下标位置元素值 是否是相同的
             if(str1[i] != str2[i]){
                 // 直接退出while循环
                 return false;
             }
             i++;
         }
         // 如果两个char类型数组中的 元素值 相同  直接返回true
         return true;
     }
 }
 ​

6. Object中的equals()方法

  • equals 比较两个对象的值是否相同
  • == 比较两个对象的内存地址是否相同

但这么说不严谨,条件:==如果自定义的对象没有重写object父类的话,则是在比较两个对象的 内存地址是否相同 也就是说 和 ==一样

二者的联系和比较

 Objectequals()源码:
 ​
 public boolean equals(Object obj) {
         return (this == obj);
 }
 1.equals():如果对象不重写equals方法,他的作用和==是一样的,都是比较地址的值!但是大部分的类  都会重写父类的equals方法,来判断两个对象的内容是否相等。例如 String就重写了equals方法,用来比较字符串的内容是否相同。
 2.==:比较引用数据类型的时候,如果该对象没有重写equals方法,那么比较的是地址。如果重写了,就按照重写规则来比较对象。
 `基本数据类型 只能用==来判断两个值是否相同,因为基本数据类型不是类 不存在方法`
 ​

重写Object中的equals() 比较成员属性是否相同

 public boolean equals(Object obj){
     // this指的是s1对象 
     if(this==obj){  //两个对象的内存地址相同 直接返回true
         return true;
     }
     if(obj == null || obj.getClass() != this.getClass()){
         return false; // 类型不一样 没必要比较成员属性值
     }
     //开始比较属性值
     retutn this.age == obj.age && this.name.equals(obj.name);
 }

7. arrays中的常用方法

  • Arrays.toString() 将数组转成字符串
 int[] arrs = {99, 87, 22, 33, 7};
 String str = Arrays.toString(arrs);// 将数组转换成字符串
 System.out.println(str);  //[99, 87, 22, 33, 7]
  • Arrays.sort() 排序数组内的值
         // 定义一个数组
         int[] arrs = {99, 87, 22, 33, 7};
         //排序
         Arrays.sort(arrs); //底层封装了 冒泡排序!!
         System.out.println("排序后的结果" + Arrays.toString(arrs)); //[7, 22, 33, 87, 99]
 ​
 ​
          char[] ch = {'d','a','c','e'};
         //sort方法 如果int类型是从小到大牌 char类型是abcd
         Arrays.sort(ch);
         System.out.println(Arrays.toString(ch)); //[a, c, d, e]

8. jdk9为何把String底层改为byte[]

节省String占用jvm的内存空间

9. String遍历字符串

 public class Test06 {
     public static void main(String[] args) {
         /**
          * 实现遍历字符串
          */
         String str1 = "lanshuqian";
         // 因为string底层是用char[]封装的 我们遍历char[]数组即可
         // charAt():  根据 char value[index下标]获取对应的字符
         for(int i=0; i< str1.length();i++){
             System.out.println(str1.charAt(i));
         }
         // 底层源码实现:  return value[index]
     }
 }

10. System类

  • System类中常用方法
public static void exit(int status)终止当前运行的java虚拟机;0为正常退出,非0为异常退出
public static long currentTimeMills()返回系统当前时间,以毫秒为单位(监考点位1970年1月1日)
  • 计算代码运行时间 (毫秒为单位)
 long start = System.currentTimeMillis();//获取当前系统时间 1970/1/1---当前时间(for执行前)
 for (int i = 0; i < 10000; i++) {
      System.out.println("lanshuqian");  //36ms
 }
 long end = System.currentTimeMillis();//获取当前系统时间 1970/1/1---当前时间(for执行后)
 System.out.println("执行该for循环1w次花费的时间:"+(end-start)+"毫秒");

11、工具类的设计思想

  • 构造方法使用private关键字修饰,禁止外部实例化
  • 成员方法public static关键字修饰 工具类中的方法 直接通过 类名.方法名()即可

12、包装类概念

  • 八种基本数据类型:byte,short,int,long,float,double,char,boolean
  • 八种基本数据类型都有对应的包装类
  • 包装类是对基本数据类型做的包装


  • 包装类目的在于基本数据类型和字符串之间做转化

13、 Integer包装类 (.valueOf)

方法名称说明
public Integer(int value)根据int值创建Integer对象(过时)
public Integer(String s)根据String值创建Integer对象(过时)
public static Integer valueOf(int i)返回表示指定int值的Integer实例
public static Integer valueOf(String s)返回一个保存指定值的Integer对象String
 public class util {
     public static void main(String[] args) {
         Integer integer = Integer.valueOf(100);
         System.out.println(integer);
         Integer testData = Integer.valueOf("30");    //把字符串转换成Integer 但!前提是字符串不能是非数字(比如"3tsd9")
         System.out.println(testData);
     }
 }

13.1 包装类的基本规则

   /**
      *  long类型 如何与String  相互的转换
      * @param args
      */
     public static void main(String[] args) {
         // str --->  long
         String str = "123456789";
         // 方法一
         Long aLong = Long.valueOf(str);
         long l1 = aLong.longValue();
         System.out.println(l1);
         //方法二
         long l2 = Long.parseLong(str);
         System.out.println(l2);
     }
 ​
 -------------------------------------------
     String falg = "sadsa";
     boolean b = Boolean.parseBoolean(flag); //false

13.2 Integer包装类底层设计原理

int与Integer的区别

  • int 是基本数据类型 Integer属于int的包装类对象 是一个类

  • 基本数据类型 存放在栈空间中的 局部变量表(方法) (了解)

  • 包装类属于对象 存在堆空间中

     Integer integerA = 60;
     ---------------------
     public static Integer valueOf(int i) {
         return new Integer(i);
     }
     ---------------------
     private final int value;
     public Integer(int value) {
        this.value = value;
     }
    
    • 为什么输入 对象名称 输出的不是内存地址 而是值呢

      • 包装类重写了toString()方法 输出对应的基本数据类型
  • Integer属于包装类 包装类默认值为 null int 基本数据类型 默认值为0
  • 包装类--->引用传递 基本数据类型---->值传递

int byte short long floag这些数字类型的默认值都是0

boolean的默认值是false

13.3 装箱和拆箱

  • 装箱: 就是自动将基本数据类型转换为包装器类型
  • 拆箱: 就是自动将包装类型转换为基本数据类型
  public static void main(String[] args) {
         /**
          * 装箱原理走的是:  Integer.valueOf(基本数据类型`60`)
          * 拆箱原理走的是:  public int intValue(){return value}  获取包装类中的基本数据类型
          */
         Integer a = 60;  // 60 是基本数据类型int  Integet a 是一个包装类 ,这里就是 `自动装箱`
         int z = a;  //包装类 赋值 给 int类型 拆箱   ,这里是 `自动拆箱`
 ​
         Integer j = 0;
         j += 1;
 ​
         // j += 1:  即 j = j + 1;  因为j 是包装类  j+1先 自动拆箱 
         // j+1的值 赋值给j  因为j是 包装类    包装类 = (0+1)  自动装箱
     }

14、String类中的valueOf()方法

  • 需求: 把int转换成字符串
  /**
   * 使用String.valueOf方法 将int long double char boolean都可以转成string
  */
         int a = 66;
         //方式一(空字符串+int)
         String a1 = a + "";
         //方式二(valueOf方法)
         String a2 = String.valueOf(a);

15、 String如何转换成int类型

字符串转int

   // String 转换成 int
         /**
          * String类型存放的字符串是 数字
          */
         String str = "123";
         Integer integer = Integer.valueOf(str); //Integer类型的123
                 //intValue 该方法不是静态方法 先new对象  对象实例.intValue方法
                 // 也就是调用intValue 方法 获取Integer 包装的 int基本数据类型 返回int类型
         int i = integer.intValue(); //int类型的123
 ​
 ​
         // 方法二  实际开发中使用以下这种方法
         int i1 = Integer.parseInt(str);
         System.out.println();

16、String的替换方法

  public static void main(String[] args) {
         String str = "lanshuqian1111";  //define a string , we'll replace 1111 to 'wjy'
         /**
          * 参数1: 需要替换的字符串内容 (1111)
          * 参数2: 替换后的字符串内容(wjy)
          */
         System.out.println("替换前"+ str);
         String newStr = str.replace("1111", "wjy");
         System.out.println("替换后"+newStr);  //lanshuqianwjy
     }

replaceFirst: 替换第一次匹配到的字符 并且之更改这个

repalceAll: 替换所有

replaceAl()l和replace()都是替换所有的字符串 replace()是不支持正则,replaceAll()支持正则

17、Date类

  • Date代表了一个特定的时刻 ,精确到毫秒

构造方法

方法名说明
public Date()分配一个Date对象,并初始化,以便代表它所分配的时间,精确到毫秒
public Date(Long Date)分配一个Date对象,并初始化为从标准时间基准起指定的毫秒数
  public static void main(String[] args) {
         // 使用Date日期类 引入java.util.Date
         Date date1 = new Date();
         System.out.println(date1); // 输出当前系统时间
 ​
         //获取的时间从1970/1/1的 08:00:00  +  1 h   GMT(格林威治时间)
         long time = 1000 * 60 * 60 ;
         Date date2 = new Date(time);
         System.out.println(date2); // 1970/1/1的 09:00:00
     }

常用方法

方法名称说明
public long getTime()获取的日期对象从1970/1/1 00:00:00 到现在毫秒值(时间戳)
public void setTime(Long time)设置时间 给的是毫秒值 和构造器的 public Date(Long Date) 同样效果
  Date date = new Date();
         //   1970/1/1/  00:00:00  -------- 2022/9/25 系统毫秒数  时间戳
         System.out.println(date.getTime());
 ​
         // 1970/1/1/  00:00:00  时间差8h  + 1个小时   和构造器的public Date(Long date)相同
         long time = 1000 * 60 * 60;
         date.setTime(time);
         System.out.println(date);

SimpleDateFormat

构造方法

方法名说明
public new SDF()构造一个sdf,使用默认格式和日期
public new SDF(String pattern)构造一个sdf,使用给定的模式和默认样式
  • 格式化 解析日期 将Date对象转化为 年月日时分秒 格式字符串

  • 把字符串转化为Date对象Date parse(String source)

  • 常用的模式字母:

    • y 年
    • M 月
    • d 日
    • h 时 在上午或下午(1~12)
    • H 时 在一天中(0~23)
    • m 分
    • s 秒

    date转成str

  public static void main(String[] args) {
        Date date = new Date();
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
         String strDate = sdf.format(date);
         System.out.println("格式化后的日期" + strDate);
     }

字符串日期转为date

  // 日期字符串转换为date
         String strDate = "2021-10-22 04:45:30";
         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
         //将 string 字符串类型日期 转换成Date类型
         Date date = simpleDateFormat.parse(strDate);
         System.out.println(date);

日期工具类的设计

 /**
  * 日期工具类
  */
 public class DateUtils {
 ​
     private static final String FORMAT_1 = "yyyy-MM-dd HH:mm:ss";
 ​
     private DateUtils(){
 ​
     }
 ​
     //1. 将Date 转为 字符串
     public static String dateToString(Date date,String format){
         SimpleDateFormat sdf = new SimpleDateFormat(format);
         return sdf.format(date);
     }
 ​
     // 获取当前的系统时间转化为字符串
     public static String getCurrentDateString(){
        return dateToString(new Date(),FORMAT_1);
     }
 ​
     //2. 将字符串 转为 Date
     public static Date StringToDate(String date,String format){
         SimpleDateFormat sdf = new SimpleDateFormat(format);
         try {
             return sdf.parse(date);
         } catch (ParseException e) {
             throw new RuntimeException(e);
         }
     }
 }
 ​

18、 Calendar抽象类

  • 一个抽象类(当然 无法实例化)

    • 所以理所应当子类实现它
    • 它的子类有 1. BuddhistCalendar 2.GregorianCalendar 3.JapaneseImperialCalendar
     public static void main(String[] args) {
         // 获取Calendar 对象
         Calendar c = Calendar.getInstance();
         System.out.println(c);
         //获取年月日(注意  月分下标从0开始)
         int year = c.get(Calendar.YEAR); //获取年份
         int month = c.get(Calendar.MONTH);//获取月分
         int date = c.get(Calendar.DATE); // 获取日
         System.out.println(year+"年"+(month + 1)+"月"+date+"日");
     }

常用api方法

  • 修改年月日
 Calendar c = Calendar.getInstance();
 //修改获取的系统时间
 c.add(Calendar.YEAR,-20); //对年份修改
 c.add(Calendar.MONTH,-2); // 月分修改
 c.add(Calendar.DATE,13); // 对日修改
  • 直接设置时间
 Calendar c = Calendar.getInstance();
 c.set(2080,8,9);
 int year = c.get(Calendar.YEAR);
 int month = c.get(Calendar.MONTH);
 int date = c.get(Calendar.DATE);

19、 二月份有多少天

   public static void main(String[] args) {
         System.out.println("键入年份:");
         Scanner sc = new Scanner(System.in);
         int year = sc.nextInt();//get year
         Calendar c = Calendar.getInstance();
         //设置时间为3/1  前一天就是2月的最后一天 (month从0开始)
         c.set(year,2,1);
         //修改日
         c.add(Calendar.DATE,-1);
         System.out.println(c.get(Calendar.DATE));
     }

20、内存图解

  • 方法没有被调用的时候,在方法区中的字节码文件存档
  • 方法被调用的时候,需要进入到栈内存中运行

类似手枪的子弹 弹夹 就是方法区 放到枪的活塞里才能打出去(这个区域理解成栈内存)

main方法 从方法区 载入 到栈内存中 在栈内存中调用其他函数(其他函数入栈)

21、java元空间

  • JDK1.8之前称作为方法区、永久代 jdk1.8之后称为 元空间
 /**
 * 1. JDK1.8之前称为 方法区 永久代  存放静态变量 class信息
 * 2. 堆中 new出来的东西
 * 定义的字符串 存放在 字符串常量池中
 * jdk1.7之前 字符串常量池存放在方法区中
 * jdk1.7开始 字符串常量池存在堆里面
 */

异常

1. 什么是异常?

  • 异常:就是程序执行报错或者出现了不正常现象

2. 异常的处理

  • JVM默认的情况下 如果程序执行报错 则会中断JVM 报错之后的代码不会再执行了

  • 解决方法:

    • try...catch...
    • throws

3.catch顺序问题

  try {
             
 }catch (){
             
 }catch (){
             
 }........

4. Exception异常

Throwable是java语言中所有异常的超类

 try {
             
 }catch (Exception e){
     sout("捕获了所有异常")
 }
 ----------------
 try {
             
 }catch (Exception e){
     sout("捕获了所有异常")
 }catch(ArrayIndexOutOfIndex e){
     // 上面已经捕获了所有异常  下面这个catch不会执行 也不会通过编译
 }
 ​
 ---------------------
 try {
             
 }catch(ArrayIndexOutOfIndex e){
     // 顺序执行  先检测是不是数组访问下标越界异常 
 }catch (Exception e){
     sout("捕获了所有异常") //如果不是以上的任意一个exeption 捕获所有
 }

5. Throwable成员方法

方法名说明
public String getMessage返回此throwable的详细消息字符串(异常错误信息内容)
public String toString返回此可抛出的简短描述
public void printStackTrace()把异常的错误信息输出在控制台

6. 编译时异常和运行时异常

  • java中主要分成两大类

    • 编译时异常(受检异常) --------必须显示处理,否则程序会发生错误,不能编译
    • 运行时异常(非受检异常)-------无需显示处理,可以编译通过,但是程序运行时可能发生异常

区分异常: RunTimeException类以及子类 都是运行时异常 其余的异常都是编译时异常

7. throws

  • java允许在方法的后面使用throws关键字对声明该方法可能有异常,这样调用者在调用方法时,就明确地知道该方法有异常,并且必须在程序中对异常进行处理(try catch 或者 抛出去),否则编译无法通过。
  • 一个注意点:
 public void a1(){
     a2(); //此时的a2()爆红,我们需要处理异常(try catch或者给虚拟机)
 }
 ​
 public static void a2() throws Exception{
 }
 //但是还有一现象
 ------------------
 public void a1(){
     a2(); //a2()不爆红,因为a2()抛出的异常是运行时异常 不需要强制要求做捕获异常的
 }
 ​
 public static void a2() throws ArrayIndexOutOfBoundsException{
     
 }

8.自定义异常

  • 自定义异常类 继承异常类即可
 //运行时异常
 public class XXXException extends RuntimeException{
     
 }
 //编译时异常
 public class XXXException extends RunTimeException{
     
 }