08【Java核心API-02】

追求适度,才能走向成功;人在顶峰,迈步就是下坡;身在低谷,抬足既是登高;弦,绷得太紧会断;人,思虑过度会疯;水至清无鱼,人至真无友,山至高无树;适度,不是中庸,而是一种明智的生活态度。

导读:本篇文章讲解 08【Java核心API-02】,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文


上一篇07【Java核心API-01】

下一篇09【内部类、Lambda表达式、数据结构、集合概述】

目录【JavaSE零基础系列教程目录】



08【Java核心API-02】

一、Object类

1.1 Object概述

java.lang.Object类是Java语言中的根类,即所有类的父类。它中描述的所有方法子类都可以使用。在对象实例化的时候,最终找的父类就是Object。

如果一个类没有特别指定父类, 那么默认则继承自Object类。例如:

public class MyClass /*extends Object*/ {
  	// ...
}

根据JDK源代码及Object类的API文档,Object类当中包含的方法有11个。今天我们主要学习其中的2个:

方法名 介绍
String toString() 返回该对象的字符串表示。
boolean equals(Object obj) 指示其他某个对象是否与此对象“相等”。

1.2 toString方法

1.2.1 方法摘要

方法名 介绍
public String toString() 返回该对象的字符串表示。我们在输出对象时,默认会调用该对象的toString()方法;

toString方法返回该对象的字符串表示,其实该字符串内容就是对象的类型+@+内存地址值。由于toString方法返回的结果是内存地址,而在开发中,经常需要按照对象的属性得到相应的字符串表现形式,因此也需要重写它。

1.2.2 覆盖重写

如果不希望使用toString方法的默认行为,则可以对它进行覆盖重写。例如自定义的Person类:

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

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

    // 省略构造器与Getter Setter
}

在IntelliJ IDEA中,可以点击Code菜单中的Generate...,也可以使用快捷键alt+insert,点击toString()选项。选择需要包含的成员变量并确定。如下图所示:

在这里插入图片描述

1.3 equals方法

1.3.1 方法摘要

方法名 作用
public boolean equals(Object obj) 指示其他某个对象是否与此对象“相等”。

调用成员方法equals并指定参数为另一个对象,则可以判断这两个对象是否是相同的。这里的“相同”有默认和自定义两种方式。

1.3.2 默认地址比较

如果没有覆盖重写equals方法,那么Object类中默认进行==运算符的对象地址比较,只要不是同一个对象,结果必然为false。

1.3.3 对象内容比较

如果希望进行对象的内容比较,即所有或指定的部分成员变量相同就判定两个对象相同,则可以覆盖重写equals方法。例如:

import java.util.Objects;

public class Person {	
	private String name;
	private int age;
	
    @Override
    public boolean equals(Object o) {
        // 如果对象地址一样,则认为相同
        if (this == o)
            return true;
        // 如果参数为空,或者类型信息不一样,则认为不同
        if (o == null || getClass() != o.getClass())
            return false;
        // 转换为当前类型
        Person person = (Person) o;
        // 要求基本类型相等,并且将引用类型交给java.util.Objects类的equals静态方法取用结果
        return age == person.age && Objects.equals(name, person.name);
    }
}

这段代码充分考虑了对象为空、类型一致等问题,但方法内容并不唯一。大多数IDE都可以自动生成equals方法的代码内容。在IntelliJ IDEA中,可以使用Code菜单中的Generate…选项,也可以使用快捷键alt+insert,并选择equals() and hashCode()进行自动代码生成。如下图所示:

在这里插入图片描述

tips:Object类当中的hashCode等其他方法,今后学习。

1.4 Objects类

在刚才IDEA自动重写equals代码中,使用到了java.util.Objects类,那么这个类是什么呢?

JDK7添加了一个Objects工具类,它提供了一些方法来操作对象,它由一些静态的实用方法组成,用于计算对象的hashcode、返回对象的字符串表示形式、比较两个对象。

在比较两个对象的时候,Object的equals方法容易抛出空指针异常,而Objects类中的equals方法就优化了这个问题。方法如下:

  • public static boolean equals(Object a, Object b):判断两个对象是否相等。

我们可以查看一下源码,学习一下:

public static boolean equals(Object a, Object b) {  
    return (a == b) || (a != null && a.equals(b));  
}

二、Date类

2.1 Date类概述

java.util.Date类 表示特定的瞬间,精确到毫秒。

继续查阅Date类的描述,发现Date拥有多个构造函数,只是部分已经过时,但是其中有未过时的构造函数可以把毫秒值转成日期对象。

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

tips:由于我们处于东八区,所以我们的基准时间为1970年1月1日8时0分0秒。

简单来说:使用无参构造,可以自动设置当前系统时间的毫秒时刻;指定long类型的构造参数,可以自定义毫秒时刻。例如:

package com.dfbz.demo01;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */

import java.util.Date;

public class Demo01 {
    public static void main(String[] args) {
        // 创建日期对象,把当前的时间
        System.out.println(new Date()); // Tue Jan 16 14:37:35 CST 2018
        // 创建日期对象,把当前的毫秒值转成日期对象
        System.out.println(new Date(0L)); // Thu Jan 01 08:00:00 CST 1970
    }
}

2.2 Date常用方法

2.2.1 获取相关

  • int getDate():获取一个月中的日期;
  • int getDay():获取一个星期中的星期几,取值范围:0-6;0代表星期天、1代表星期1、2代表星期2;
  • int getHours():获取小时;
  • int getMinutes():获取分钟;
  • int getMonth():获取0-11的月份,0代表1月,1代表2月以此类推;因此我们获取月份一般使用:getMonth()+1
  • int getSeconds():获取秒;
  • long getTime():返回自1970年1月1日以来到当前日期的毫秒数;
  • int getYear():获取1900年到当前年的年份,如121代表2021年,120代表2020年以此类推…

使用示例:

package com.dfbz.demo01;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */

import java.util.Date;

public class Demo01 {
    public static void main(String[] args) {
        Date date = new Date();

        // 返回1900到现在的年份  如:2021 -> 121; 2020 -> 120
        System.out.println(date.getYear());

        // 返回月份  0-11  0代表1月,1代表2月...
        System.out.println(date.getMonth());

        // 返回当月的第几天
        System.out.println(date.getDate());

        // 小时
        System.out.println(date.getHours());

        // 分钟
        System.out.println(date.getMinutes());

        // 秒
        System.out.println(date.getSeconds());

        // 星期几
        System.out.println(date.getDay());
    }
}

2.2.2 设置相关

  • void setYear(int year) 设置年,从1900为0年,设置1为1901年,设置20为1920年,设置120为2020年…
  • void setMonth(int month):设置月,范围0-11,0为1月,1为2月,11为12月…
  • void setDate(int date):设置一个月的某天;
  • void setHours(int hours):设置小时
  • void setMinutes(int minutes):设置分钟;
  • void setSeconds(int seconds) :设置秒;
  • void setTime(long time):设置1970年1月1日到现在的毫秒值;

使用示例:

package com.dfbz.demo02;

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

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */

public class Demo01 {
    public static void main(String[] args) {

        Date date=new Date();
        date.setYear(120);          // 2020年
        date.setMonth(10);          // 11月
        date.setDate(8);           // 8号
        date.setHours(20);          // 20时
        date.setMinutes(50);        // 50分
        date.setSeconds(40);        // 40秒

        System.out.println(date);       // Sun Nov 08 20:50:40 CST 2020
    }
}

在这里插入图片描述

2.4 DateFormat类

java.text.DateFormat 是日期/时间格式化子类的抽象类,我们通过这个类可以帮我们完成日期和文本之间的转换,也就是可以在Date对象与String对象之间进行来回转换。

  • 格式化:按照指定的格式,从Date对象转换为String对象。
  • 解析:按照指定的格式,从String对象转换为Date对象。

2.4.1 构造方法

由于DateFormat为抽象类,不能直接使用,所以需要常用的子类java.text.SimpleDateFormat。这个类需要一个模式(格式)来指定格式化或解析的标准。构造方法为:

  • public SimpleDateFormat(String pattern):用给定的模式和默认语言环境的日期格式符号构造SimpleDateFormat。

参数pattern是一个字符串,代表日期时间的自定义格式。

2.4.2 格式规则

  • 常用的格式规则为:
标识字母(区分大小写) 含义
y
M
d
H
m
s

创建SimpleDateFormat对象的代码如:

package com.dfbz.demo01;

import java.text.DateFormat;
import java.text.SimpleDateFormat;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */

public class Demo01 {
    public static void main(String[] args) {
        // 对应的日期格式如:2021-06-02 20:04:25
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    }
}

2.4.3 常用方法

DateFormat类的常用方法有:

  • public String format(Date date):将Date对象格式化为字符串。
  • public Date parse(String source):将字符串解析为Date对象。

1)format方法

使用示例:

package com.dfbz.demo01;

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

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo02 {
    public static void main(String[] args) {
        Date date = new Date();
        // 创建日期格式化对象,在获取格式化对象时可以指定风格
        DateFormat df = new SimpleDateFormat("yyyy年MM月dd日");
        String str = df.format(date);
        System.out.println(str);            // 2021年06月02日
    }
}

2)parse方法

使用示例:

package com.dfbz.demo01;

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

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo03 {
    public static void main(String[] args) throws ParseException {          // 可能会出现ParseException异常

        // 创建日期格式化对象
        DateFormat df = new SimpleDateFormat("yyyy年MM月dd日");

        // 准备一个日期字符串
        String str = "2020年12月11日";

        // 使用格式化对象将字符串变为日期对象
        Date date = df.parse(str);

        System.out.println(date);           // Fri Dec 11 00:00:00 CST 2020
    }
}

2.4.4 练习

请使用日期时间相关的API,计算出一个人已经出生了多少天。

思路:

1.获取当前时间对应的毫秒值

2.获取自己出生日期对应的毫秒值

3.两个时间相减(当前时间– 出生日期)

  • 代码实现:
package com.dfbz.demo01;

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

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo04 {
    public static void main(String[] args) throws Exception {
        System.out.println("请输入出生日期 格式 YYYY-MM-dd");

        // 获取出生日期,键盘输入
        String birthdayString = new Scanner(System.in).next();

        // 将字符串日期,转成Date对象
        // 创建SimpleDateFormat对象,写日期模式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        // 调用方法parse,字符串转成日期对象
        Date birthdayDate = sdf.parse(birthdayString);

        // 获取今天的日期对象
        Date todayDate = new Date();

        // 将两个日期转成毫秒值,Date类的方法getTime
        long birthdaySecond = birthdayDate.getTime();
        long todaySecond = todayDate.getTime();
        long liveSecond = todaySecond - birthdaySecond;

        if (liveSecond < 0) {
            System.out.println("还没出生呢");
        } else {
            System.out.println("您活了: " + (liveSecond / 1000 / 60 / 60 / 24) + "天");
        }
    }
}

运行结果:

在这里插入图片描述

三、Calendar类

3.1 Calendar类概述

java.util.Calendar是日历类,在Date后出现,替换掉了许多Date的方法。该类将所有可能用到的时间信息封装为静态成员变量,方便获取。日历类就是方便获取各个时间属性的。

在这里插入图片描述

3.2 获取方式

Calendar为抽象类,Calendar类在创建对象时并非直接创建,而是通过静态方法创建,返回子类对象,如下:

  • public static Calendar getInstance():使用默认时区和语言环境获得一个日历
package com.dfbz.demo01;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */

import java.util.Calendar;

public class Demo01 {
    public static void main(String[] args) {

        // 获取日历对象
        Calendar cal = Calendar.getInstance();
    }
}

3.3 常用方法

根据Calendar类的API文档,常用方法有:

  • public int get(int field):返回给定日历字段的值。
  • public void set(int field, int value):将给定的日历字段设置为给定值。
  • public abstract void add(int field, int amount):根据日历的规则,为给定的日历字段添加或减去指定的时间量。
  • public Date getTime():返回一个表示此Calendar时间值(从历元到现在的毫秒偏移量)的Date对象。
  • public long getTimeInMillis():获取1970年到当前时间的毫秒值;

Calendar类中提供很多成员常量,代表给定的日历字段:

字段值 含义
YEAR
MONTH 月(从0开始,可以+1使用)
DATE、DAY_OF_MONTH 月中的天(几号)
HOUR 时(12小时制)
HOUR_OF_DAY 时(24小时制)
MINUTE
SECOND
DAY_OF_WEEK 周中的天(周几,0为星期6,1为星期天,2为星期1,3为星期2)
WEEK_OF_MONTH 一个月的第几周

1)get方法

get方法主要是获取日期的信息:

package com.dfbz.demo01;

import java.util.Calendar;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo02 {
    public static void main(String[] args) {
        Calendar calendar = Calendar.getInstance();

        System.out.println("年: " + calendar.get(Calendar.YEAR));
        System.out.println("月: " + calendar.get(Calendar.MONTH));       // 0-11,4代表5月,5代表6月
        System.out.println("日: " + calendar.get(Calendar.DAY_OF_MONTH));  // 0-6,0代表星期六,1代表星期天
        System.out.println("星期几: " + calendar.get(Calendar.DAY_OF_WEEK));
        System.out.println("一个月第几周: " + calendar.get(Calendar.WEEK_OF_MONTH));
        System.out.println("时: " + calendar.get(Calendar.HOUR));
        System.out.println("分: " + calendar.get(Calendar.MINUTE));
        System.out.println("秒: " + calendar.get(Calendar.SECOND));
    }
}

2)set方法

set方法主要是设置日期的值:

package com.dfbz.demo01;

import java.util.Calendar;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo03 {
    public static void main(String[] args) {
        Calendar calendar = Calendar.getInstance();

        calendar.set(Calendar.YEAR, 2020);
        calendar.set(Calendar.MONTH, 10);            // 10代表11月
        calendar.set(Calendar.DAY_OF_MONTH, 8);        // 范围1-7,1代表星期天,2代表星期1,3代表星期2...
        calendar.set(Calendar.HOUR, 10);
        calendar.set(Calendar.MINUTE, 18);
        calendar.set(Calendar.SECOND, 50);

        System.out.println("年: " + calendar.get(Calendar.YEAR));
        System.out.println("月: " + calendar.get(Calendar.MONTH));       // 0-11,10代表11月,11代表12月
        System.out.println("日: " + calendar.get(Calendar.DAY_OF_MONTH));
        System.out.println("星期几: " + calendar.get(Calendar.DAY_OF_WEEK));       // 0-6,0代表星期天,1代表星期1,2代表星期2...
        System.out.println("时: " + calendar.get(Calendar.HOUR));
        System.out.println("分: " + calendar.get(Calendar.MINUTE));
        System.out.println("秒: " + calendar.get(Calendar.SECOND));

    }
}

3)add方法

add方法可以对指定日历字段的值进行加减操作,如果第二个参数为正数则加上偏移量,如果为负数则减去偏移量。代码如:

package com.dfbz.demo01;

import java.util.Calendar;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo04 {
    public static void main(String[] args) {
        Calendar cal = Calendar.getInstance();

        // 2021年6月2日
        System.out.println(cal.get(Calendar.YEAR) + "年" + (cal.get(Calendar.MONTH) + 1) + "月" + cal.get(Calendar.DAY_OF_MONTH) + "日");

        // 使用add方法
        cal.add(Calendar.DAY_OF_MONTH, 2); // 加2天

        cal.add(Calendar.YEAR, -3); // 减3年

        // 2018年6月4日
        System.out.println(cal.get(Calendar.YEAR) + "年" + (cal.get(Calendar.MONTH) + 1) + "月" + cal.get(Calendar.DAY_OF_MONTH) + "日");
    }
}

4)getTime方法

Calendar中的getTime方法并不是获取毫秒时刻,而是拿到对应的Date对象。

package com.dfbz.demo01;

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

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo05 {
    public static void main(String[] args) {
        Calendar cal = Calendar.getInstance();
        Date date = cal.getTime();
        System.out.println(date);           // Wed Jun 02 20:56:16 CST 2021
    }
}

tips:

  • 西方星期的开始为周日,中国为周一;
  • 在Calendar类中,月份的表示是以0-11代表1-12月;
  • 日期是有大小关系的,时间靠后,时间越大;

四、SpringBuilder类

4.1 StringBuilder简介

之前在学习String类的时候我们就说到过:String类是不可变类,即一个String对象被创建以后,包含在这个对象中的字符序列是不可改变的,直至这个对象被销毁。

回顾String类的字符串拼接:

String s1="1";
s1="2";

在这里插入图片描述

java.lang.StringBuilder又称为可变字符序列,是个字符串的缓冲区,即它是一个容器,容器中可以装很多字符串。并且能够对其中的字符串进行各种操作。它的内部拥有一个数组用来存放字符串内容,进行字符串拼接时,直接在数组中加入新内容。StringBuilder会自动维护数组的扩容。原理如下图所示:(默认16字符空间,超过自动扩充)

在这里插入图片描述

查看String拼接:

在这里插入图片描述

4.2 构造方法

根据StringBuilder的API文档,常用构造方法有2个:

  • public StringBuilder():构造一个空的StringBuilder容器。
  • public StringBuilder(String str):构造一个StringBuilder容器,并将字符串添加进去。

示例代码:

package com.dfbz.demo01;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo01 {
    public static void main(String[] args) {
        StringBuilder sb1 = new StringBuilder();
        System.out.println(sb1); // (空白)
        
        // 使用带参构造
        StringBuilder sb2 = new StringBuilder("abc");
        System.out.println(sb2); // abc
    }
}

4.3 常用方法

StringBuilder常用的方法有2个:

  • public StringBuilder append(...):添加任意类型数据的字符串形式,并返回当前对象自身。
  • public String reverse():将当前对象的字符串反转,并返回当前对象自身。
  • public String toString():将当前StringBuilder对象转换为String对象。

1)append方法:

package com.dfbz.demo01;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo03 {
    public static void main(String[] args) {
        //创建对象
        StringBuilder builder = new StringBuilder();

        //public StringBuilder append(任意类型)
        StringBuilder builder2 = builder.append("hello");

        //对比一下
        System.out.println("builder:" + builder);
        System.out.println("builder2:" + builder2);
        
        System.out.println(builder == builder2); //true
        
        // 可以添加 任何类型
        builder.append("hello");
        builder.append("world");
        builder.append(true);
        builder.append(100);
        
        // 在我们开发中,会遇到调用一个方法后,返回一个对象的情况。然后使用返回的对象继续调用方法。
        // 这种时候,我们就可以把代码现在一起,如append方法一样,代码如下
        // 链式编程
        builder.append("hello").append("world").append(true).append(100);
        System.out.println("builder:" + builder);
    }
}

2)reverse方法:

package com.dfbz.demo01;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo04 {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("abc");

        StringBuilder sb2 = sb.reverse();

        System.out.println(sb);         // cba
        System.out.println(sb == sb2);  // true
    }
}

3)toString方法:

package com.dfbz.demo01;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo05 {
    public static void main(String[] args) {
        // 链式创建
        StringBuilder sb = new StringBuilder("Hello").append("World");
        // 调用方法
        String str = sb.toString();
        System.out.println(str); // HelloWorld
    }
}

五、System类

5.1 常用方法

java.lang.System是Java中的系统类,主要用于获取系统的属性数据,没有构造方法。类中提供了大量的静态方法,可以获取与系统相关的信息或系统级操作,在System类的API文档中,常用的方法有:

  • public static long currentTimeMillis():返回以毫秒为单位的当前时间。
  • public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length):将数组中指定的数据拷贝到另一个数组中。
  • public static exit(int status):该方法用于退出jvm,如果参数是0表示正常退出jvm,非0表示异常退出jvm。
  • public static getProperties():该方法用于获取系统的所有属性。属性分为键和值两部分,它的返回值是Properties。
  • public static gc():该方法用来建议jvm赶快启动垃圾回收器回收垃圾。只是建议启动,但是Jvm是否启动又是另外一回事。

5.2 System类的使用

5.2.1 currentTimeMillis

通过System的currentTimeMillis()方法我们可以获取当前时间的毫秒值,有了毫秒值我们可以将其转换为Date对象、Calendar对象等进行日期的运算;

package com.dfbz.demo01;

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

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo01 {
    public static void main(String[] args) {
        //  获取当前时间毫秒值
        long currTime = System.currentTimeMillis();

        // 有了毫秒值之后可以将其转换为Date
        Date date = new Date(currTime);

        // 获取日历类
        Calendar calendar = Calendar.getInstance();

        // 设置毫秒值
        calendar.setTimeInMillis(currTime);

        System.out.println(date);          
        System.out.println(calendar.get(Calendar.YEAR));
        System.out.println(calendar.get(Calendar.MONTH) + 1);
        System.out.println(calendar.get(Calendar.DAY_OF_MONTH));
    }
}

5.2.2 arraycopy

  • public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length):将数组中指定的数据拷贝到另一个数组中。

数组的拷贝动作是系统级的,性能很高。System.arraycopy方法具有5个参数,含义分别为:

参数序号 参数名称 参数类型 参数含义
1 src Object 源数组
2 srcPos int 源数组索引起始位置
3 dest Object 目标数组
4 destPos int 目标数组索引起始位置
5 length int 复制元素个数
  • 使用示例:

将src数组中前3个元素,复制到dest数组的前3个位置上复制元素前:src数组元素[1,2,3,4,5],dest数组元素[11,22,33,44,55]复制元素后:src数组元素[1,2,3,4,5],dest数组元素[1,2,3,44,55];

package com.dfbz.demo01;

import java.util.Arrays;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo02 {
    public static void main(String[] args) {
        int[] src = new int[]{1, 2, 3, 4, 5};
        int[] dest = new int[]{11, 22, 33, 44, 55};

        System.arraycopy(src, 0, dest, 0, 3);

        /*
            代码运行后:两个数组中的元素发生了变化
                src数组元素[1,2,3,4,5]
                dest数组元素[1,2,3,44,55]
        */

        // 使用字符串形式打印数组
        System.out.println(Arrays.toString(src));           // [1, 2, 3, 4, 5]
        System.out.println(Arrays.toString(dest));          // [1, 2, 3, 44, 55]
    }
}

图解:

在这里插入图片描述

5.2.3 exit

exit用于退出Jvm,需要注意的是:0或者非0的数据都可以退出Jvm,对于用户而言没有任何区别,对于windows是有作用的,因为如果传非0对于windows而言是异常终止的,如果是正版的操作系统,对于异常退出的软件,需要把这些异常退出的软件信息做成报告发送给微软,微软就可以针对这些问题对系统做出一些修改。

package com.dfbz.demo01;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo03 {
    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {
            System.out.println(i);
            if (i == 5) {
                System.exit(0);         // 程序退出
            }
        }
    }
}

5.2.4 gc

在Java程序运行时,如果一个对象没有再被引用,或者被指向为null,那么这个对象就应该被标记为”垃圾”,Jvm会根据某种算法来定时清除这些对象来释放内存;我们也可以通过System.gc()方法告诉Jvm垃圾回收器,叫他来清除一下垃圾;但gc方法只是建议Jvm赶快启动垃圾回收器回收垃圾。Jvm是否启动又是另外一回事。

package com.dfbz.demo01;

import java.util.Properties;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo04 {
    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {
            // 使用匿名对象(没有对象保存返回值)
            new Student();

            // 触发垃圾回收器
            System.gc();
        }
    }
}

class Student {
    @Override
    protected void finalize() throws Throwable {
        System.out.println("垃圾回收器执行了");
    }
}

finalize():是Object类的一个方法,如果一个对象被垃圾回收 器回收的时候,会先调用对象的finalize()方法。

运行效果:

在这里插入图片描述

六、包装类

6.1 包装类概述

Java提供了两个类型系统,基本类型与引用类型,使用基本类型在于效率,然而很多情况,会创建对象使用,因为对象可以做更多的功能,如果想要我们的基本类型像对象一样操作,就可以使用基本类型对应的包装类,如下:

基本类型 对应的包装类(位于java.lang包中)
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

6.2 装箱与拆箱

基本类型与对应的包装类对象之间,来回转换的过程称为”装箱“与”拆箱“:

  • 装箱:从基本类型转换为对应的包装类对象。

  • 拆箱:从包装类对象转换为对应的基本类型。

用Integer与 int为例:(看懂代码即可)

基本数值—->包装对象

Integer i = new Integer(4);//使用构造函数函数
Integer ii = Integer.valueOf(4);//使用包装类中的valueOf方法

包装对象—->基本数值

int num = i.intValue();

6.3 自动装箱与自动拆箱

由于我们经常要做基本类型与包装类之间的转换,从Java 5(JDK 1.5)开始,基本类型与包装类的装箱、拆箱动作可以自动完成。例如:

Integer i = 4;		// 自动装箱。相当于Integer i = Integer.valueOf(4);
i = i + 5;			// 等号右边:将i对象转成基本数值(自动拆箱) i.intValue() + 5;
					// 加法运算完成后,再次装箱,把基本数值转成对象。

6.4 基本类型与字符串之间的转换

6.4.1 基本类型转换为String

基本类型转换String总共有三种方式,查看课后资料可以得知,这里只讲最简单的一种方式:

基本类型直接与””相连接即可;如:10+""

6.4.2 String转换成对应的基本类型

除了Character类之外,其他所有包装类都具有parseXxx静态方法可以将字符串参数转换为对应的基本类型:

  • public static byte parseByte(String s):将字符串参数转换为对应的byte基本类型。
  • public static short parseShort(String s):将字符串参数转换为对应的short基本类型。
  • public static int parseInt(String s):将字符串参数转换为对应的int基本类型。
  • public static long parseLong(String s):将字符串参数转换为对应的long基本类型。
  • public static float parseFloat(String s):将字符串参数转换为对应的float基本类型。
  • public static double parseDouble(String s):将字符串参数转换为对应的double基本类型。
  • public static boolean parseBoolean(String s):将字符串参数转换为对应的boolean基本类型。

代码使用(仅以Integer类的静态方法parseXxx为例)如:

package com.dfbz.demo01;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo01 {
    public static void main(String[] args) {

        // 字符串转byte
        byte b = Byte.parseByte("100");

        // 字符串转short
        short s = Short.parseShort("100");

        // 字符串转num
        int num = Integer.parseInt("100");
        
        // 字符串转long
        long l = Long.parseLong("100");

        // 字符串转float
        float f = Float.parseFloat("100.0");
        
        // 字符串转double
        double d = Double.parseDouble("100.0");
        
        // 字符串转boolean
        boolean boo = Boolean.parseBoolean("true");

        // 字符串转char
        char c = "a".charAt(0);
    }
}

注意:如果字符串参数的内容无法正确转换为对应的基本类型,则会抛出java.lang.NumberFormatException异常。

七、数值类

Java中的八大基本数据类型如下:

数据类型 关键字 内存占用 取值范围
字节型 byte 1个字节 -128~127
短整型 short 2个字节 -32768~32767
整型 int(默认) 4个字节 -2147483648~2147483647
长整型 long 8个字节 -2的63次方~2的63次方-1
单精度浮点数 float 4个字节 1.4013E-45~3.4028E+38
双精度浮点数 double(默认) 8个字节 4.9E-324~1.7977E+308
字符型 char 2个字节 0-65535
布尔类型 boolean 1个字节 true,false

8个基本数据类型都是有大小的,例如一个byte类型变量只能存储-128~127之间的数字,多了就存不下,这样在面对大数据量的计算时(如科学计算)基本数据类型会出现很大的问题(存不下);

如果基本的整数和浮点数精度不能够满足需求,那么可以使用java.math包中两个很有用的类:BigIntegerBigDecimal。这两个类可以处理包含任意长度数字序列的数值;BigInteger类实现任意精度的整数运算,BigDecimal实现任意精度的浮点数运算;

7.1 BigInteger

可以通过一个字符串来构建一个BigInteger类,BigInteger类封装了大量对数字的加减乘除等操作的方法,而字符串可以任意长度,也就是说BigInteger支持任意长度的数字进行加减乘除等运算;

7.1.1 获取BigInteger对象

  • 构造方法:
    • public BigInteger(String val):通过一个字符串来构建BigInteger对象;
  • 普通方法:
    • public static BigInteger valueOf(long val):通过一个Long数值来构建一个BigInteger对象,由于BigInteger对象都是针对于非常庞大的数据(远远超过了Long的取值范围)进行运算,因此很少使用这个方法来构建BigInteger对象;

示例代码:

package com.dfbz.biginteger;

import java.math.BigInteger;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo01_BigInteger的获取 {
    public static void main(String[] args) {
        // 基于一个Long数值来创建一个BigInteger对象
        BigInteger big1 = BigInteger.valueOf(1230020200L);

        // 基于一个字符串来创建一个BigInteger对象
        BigInteger big2 = new BigInteger("234234234231213123123123123213");
    }
}

7.1.2 BigInteger的常用方法

  • public BigInteger add(BigInteger val):返回值为 (this + val)
  • public BigInteger subtract(BigInteger val):返回值为 (this – val)
  • public BigInteger multiply(BigInteger val):返回值为 (this * val)
  • public BigInteger divide(BigInteger val):返回值为 (this / val)
  • public BigInteger mod(BigInteger m):返回值为(this % m)
  • public int compareTo(BigInteger val):如果this的数值比val的大,返回1,否则返回-1,如果相等则返回0

示例代码:

package com.dfbz.biginteger;

import java.math.BigInteger;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo02_BigInteger的常用方法 {
    public static void main(String[] args) {
        BigInteger num1 = new BigInteger("100");
        BigInteger num2 = new BigInteger("10");

        System.out.println(num1.add(num2));                 // 110
        System.out.println(num1.subtract(num2));            // 90
        System.out.println(num1.multiply(num2));            // 1000
        System.out.println(num1.divide(num2));              // 10
        System.out.println(num1.mod(num2));                 // 0
        System.out.println(num1.compareTo(num2));           // 1
    }
}

7.1.3 BigInteger转换为基本数据类型

  • 示例代码:
package com.dfbz.biginteger;

import java.math.BigInteger;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo03_转换为基本数据类型 {
    public static void main(String[] args) {
        BigInteger num = new BigInteger("10");

        // BigInteger转换为对应的基本数据类型
        byte b = num.byteValue();
        short s = num.shortValue();
        int i = num.intValue();
        long l = num.longValue();
        float f = num.floatValue();
        double d = num.doubleValue();

        // BigInteger转换为字符串
        String str = num.toString();
    }
}

7.1.4 BigInteger注意事项

BigInteger只能构建整数,不能构建小数,否则会出现程序异常现象;另外,如果两个BigInteger计算的值出现小数时则会出现丢失精度现象;

  • 示例代码:
package com.dfbz.biginteger;

import java.math.BigInteger;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo04_浮点数运算 {
    public static void main(String[] args) {
        BigInteger num1 = new BigInteger("10");
        BigInteger num2 = new BigInteger("3");

        System.out.println(num1.divide(num2));          // 结果为: 3; 出现丢失精度现象
    }
    
    public static void test(){
        
        // Exception in thread "main" java.lang.NumberFormatException: For input string: "9.3"
        BigInteger num1 = new BigInteger("9.3");
        BigInteger num2 = new BigInteger("2.5");

        // 程序异常: Exception in thread "main" java.lang.NumberFormatException: For input string: "9.3"
        System.out.println(num1.multiply(num2));
    }
}

7.2 BigDecimal

BigInteger是针对大整数的运算,BigDecimal则是针对大型浮点数的运算。值得注意的是,BigDecimal也可以针对大型整数进行运算,也就是包含了BigInteger的绝大部分功能,在大部分场景下我们使用BigDecimal会比较多,他与BigInteger其他特性几乎一样;

7.2.1 获取BigDecimal对象

  • 静态方法:
    • public static BigDecimal valueOf(long val):基于一个Long类型的数值来构建BigDecimal对象
    • public static BigDecimal valueOf(double val) :基于一个Double类型的数值来构建BigDecimal对象
  • 构造方法:
    • public BigDecimal(String val):基于一个字符串来构建BigDecimal对象

示例代码:

package com.dfbz.Bigdecimal;

import java.math.BigDecimal;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo01_BigDecimal的获取 {
    public static void main(String[] args) {

        // 基于一个Long类型的数值来构建BigDecimal对象
        BigDecimal big1 = BigDecimal.valueOf(1000);

        // 基于一个Double类型的数值来构建BigDecimal对象
        BigDecimal big2 = BigDecimal.valueOf(399.38);

        // 基于一个字符串来构建BigDecimal对象
        BigDecimal big3 = new BigDecimal("99999");

        // 基于一个字符串来构建BigDecimal对象
        BigDecimal big4 = new BigDecimal("99999.99");
    }
}

7.2.2 BigDecimal的常用方法

BigDecimal的常用方法和BigInteger基本一致;不过BigDecimal对除法(divide)进行了优化;

  • public BigDecimal divide(BigDecimal divisor, int roundingMode):除法运算,默认情况下不允许出现无限循环小数;

    • BigDecimal.ROUND_UP:最后一位如果大于0,则向前进一位,如果是正数则向上取整,如果是负数则向下取整。
      • 例如:3.3->4;-3.3->-4
    • BigDecimal.ROUND_DOWN:最后一位不管是什么都会被舍弃。
      • 例如:3.3->3;-3.3->-3
    • BigDecimal.ROUND_CEILING:向上取整。
      • 例如:3.3->4;-3.3->-3。
    • BigDecimal.ROUND_FLOOR:向下取整。
    • 例如:3.3->3;-3.3->-4。
  • 示例代码-1(整数运算):

package com.dfbz.Bigdecimal;

import java.math.BigDecimal;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo02_BigDecimal的常用方法 {
    public static void main(String[] args) {

        BigDecimal num1 = BigDecimal.valueOf(100);
        BigDecimal num2 = BigDecimal.valueOf(10);

        System.out.println(num1.add(num2));                 // 110
        System.out.println(num1.subtract(num2));            // 90
        System.out.println(num1.multiply(num2));            // 1000
        System.out.println(num1.divide(num2));              // 10
    }
}
  • 示例代码-2(结果为小数):
package com.dfbz.Bigdecimal;

import java.math.BigDecimal;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo03_BigDecimal的小数运算 {
    public static void main(String[] args) {
        BigDecimal num1 = BigDecimal.valueOf(10);
        BigDecimal num2 = BigDecimal.valueOf(3);

        // 结果有循环小数的,需要指定规则来调整
        System.out.println(num1.divide(num2, BigDecimal.ROUND_UP));                      // 4
        System.out.println(num1.divide(num2, BigDecimal.ROUND_DOWN));                    // 3
        System.out.println(num1.divide(num2, BigDecimal.ROUND_CEILING));                 // 4
        System.out.println(num1.divide(num2, BigDecimal.ROUND_FLOOR));                   // 3   
    }

    public static void test4() {
        BigDecimal num1 = BigDecimal.valueOf(10);
        BigDecimal num2 = BigDecimal.valueOf(3);

        /*
         出现异常: Exception in thread "main" java.lang.ArithmeticException:
         Non-terminating decimal expansion; no exact representable decimal result.
         结果不能出现无限循环小数
         */
        System.out.println(num1.divide(num2));
    }

    public static void test3() {

        // 小数参与运算也没有问题
        BigDecimal num1 = BigDecimal.valueOf(2.53);
        BigDecimal num2 = BigDecimal.valueOf(3.69);

        System.out.println(num1.add(num2));                 // 6.22
        System.out.println(num1.subtract(num2));            // -1.16
        System.out.println(num1.multiply(num2));            // 9.3357
    }

    public static void test2() {


        // 结果为小数,也没有什么问题
        BigDecimal num1 = BigDecimal.valueOf(5);
        BigDecimal num2 = BigDecimal.valueOf(2);

        System.out.println(num1.divide(num2));              // 4

    }

    public static void test() {

        // 普通运算和BigInteger基本类似
        BigDecimal num1 = BigDecimal.valueOf(100);
        BigDecimal num2 = BigDecimal.valueOf(10);

        System.out.println(num1.add(num2));                 // 110
        System.out.println(num1.subtract(num2));            // 90
        System.out.println(num1.multiply(num2));            // 1000
        System.out.println(num1.divide(num2));              // 10
    }
}

上一篇07【Java核心API-01】

下一篇09【内部类、Lambda表达式、数据结构、集合概述】

目录【JavaSE零基础系列教程目录】


记得点赞~!!!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/131777.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!