前言
本文开始介绍Java的核心类库,主要是常用类的概述和使用,主要包括API的使用和常用包的概述、Object类的概述、包装类和数学处理类。
1.API的使用和常用包的概述
核心类库即Java官方提供的类和接口。
要了解Java核心类库,则需要使用API,即应用程序接口。
有中文的API文档,但是由于翻译等原因,不一定完整准确,要想使用更完整的可以使用Java官方提供的英文版API。
API中首先分成模块,如下:
其中第一个模块是java.base
模块,定义Java SE平台的基础API。
点击进入该模块后,可以看到包含了很多包,如下:
然后可以选择需要查看的包并点击进入,会看到所包含的类、接口、异常、注解等。
以java.lang
包为例,如下:
可以看到,包含了该包所有的接口、类、枚举、异常、错误和注解类型。
还可以进一步点击查看,以System类为例如下:
包含了该类的字段和方法等信息。
如果不知道类等所在的模块和包,则可以进行检索和搜索,如下:
Java中常用的包及其功能如下:
- java.lang包
该包是Java语言的核心包,并且该包中的所有内容由Java虚拟机自动导入 ,提供了对Java编程语言设计至关重要的类,包括System类、String类等。
java.lang包中的类不需要我们手动导入。
- java.util包
该包是Java语言的工具包,里面提供了大量工具类以及集合类等,如Scanner类、Random类、List集合等。
- java.io包
该包是Java语言中的输入输出包,里面提供了大量读写文件相关的类等,如FileInputStream类、FileOutputStream类等。
- java.net包
该包是Java语言中的网络包,里面提供了大量网络编程相关的类等,如ServerSocket类、Socket类等。
- java.sql 包
该包是Java语言中的数据包,里面提供了大量操作数据库的类和接口等,如DriverManager类、Connection接口等。
- ……
在进行Java编程时可以使用大量类库,因此需要熟悉并记住。
2.Object类的概述
(1)Object类的概念和构造方法
Object类位于java.lang
包中。
java.lang.Object类的定义方式为public class Object
,是Java语言中类层次结构的根类 , 每个类都以Object作为超类,也就是说任何一个类都是该类的直接或者间接子类,所有对象(包括数组)都实现此类的方法。Object在英文中的含义是对象,也就印证了“万物皆对象 ”的说法。
如果定义一个Java类时没有使用extends关键字声明其父类,则其父类默认为Object 类。
例如之前定义Person类public class Person
相当于public class Person extends Object
。所以说Person类是Object类的直接子类,如果Student类继承自Person类,则Student类是Object类的间接子类。
Object类定义了对象的基本行为即方法,被子类默认继承。
Object类的常用方法包括:
- Object()
使用无参方式构造对象。
- boolean equals(Object obj)
用于判断调用对象是否与参数对象相等。
- int hashCode()
用于获取调用对象的哈希码值。
- String toString()
用于获取调用对象的字符串形式。
- Class<?> getClass()
用于返回调用对象执行时的Class实例,反射机制使用。
Object类中的无参构造方法是Object()
。
如下:
/**
* 实现无参构造方法
*/
public Person() {
super();
}
其中,super();
表示调用父类的构造方法,即Object类中的构造方法。
(2)equals方法默认功能的使用
boolean equals(Object obj)
方法用于判断调用对象是否与参数对象相等:
该方法默认比较两个对象的地址是否相等 ,与==
运算符的结果一致;
若希望比较两个对象的内容,则需要重写该方法;
若该方法被重写,则应该同时重写hashCode方法来保证结果的一致性。
因为未被static修饰,所以该方法需要通过对象来调用;
同时需要传入Object类型及其子类类型的对象,会形成多态。
现定义Student类如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/18 12:16
* @description javase-com.stage1.module3
*/
public class Student {
private int id; // 描述学号
private String name; // 描述姓名
public Student() {
}
public Student(int id, String name) {
setId(id);
setName(name);
}
public int getId() {
return id;
}
public void setId(int id) {
if (id > 0) {
this.id = id;
} else {
System.out.println("学号不合理");
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
测试类如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/18 12:40
* @description javase-com.stage1.module3
*/
public class StudentTest {
public static void main(String[] args) {
// 1.使用有参方式构造2个Student类型对象并判断是否相等
Student s1 = new Student(20210101, "Corley");
Student s2 = new Student(20210102, "Jack");
Student s3 = s1; // s3和s1指向了同一个对象,所以地址相同
// 2.调用继承自从Object类中继承的equals方法,比较两个对象的地址
boolean res1 = s1.equals(s2);
System.out.println("res = " + res1);
System.out.println(s1 == s2);
boolean res2 = s3.equals(s1);
System.out.println("res = " + res2);
}
}
输出:
res = false
false
res = true
因为s1和s2指向了不同的对象,其地址不同,所以s1.equals(s2)
的值为false;
同时s3和s1指向了同一个对象,地址相同,所以s3.equals(s1)
的结果为true。
(3)equals方法的重写
可以查看equals
方法的源代码如下:
public boolean equals(Object obj) {
return (this == obj);
}
显然,equals
方法默认是对地址进行比较;
如果不对对象的地址比较,而是比较其他特征,则需要重写该方法。
例如学生类Student可以比较学号也就是id属性。
Student类中重写equals方法如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/18 12:16
* @description javase-com.stage1.module3
*/
public class Student {
private int id; // 描述学号
private String name; // 描述姓名
public Student() {
}
public Student(int id, String name) {
setId(id);
setName(name);
}
public int getId() {
return id;
}
public void setId(int id) {
if (id > 0) {
this.id = id;
} else {
System.out.println("学号不合理");
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 为了比较两个对象的内容,这里是学号信息,需要重写equals方法
*/
@Override
public boolean equals(Object obj) {
// 判断obj指向的对象是否为Student类型的对象,若是则进行判断
if (obj instanceof Student) {
Student stu = (Student) obj;
return this.getId() == stu.getId();
}
// 若不是则说明类型不一致,因此没有可比性、内容一定不相同,直接返回false
return false;
}
}
测试类如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/18 12:40
* @description javase-com.stage1.module3
*/
public class StudentTest {
public static void main(String[] args) {
// 1.使用有参方式构造2个Student类型对象并判断是否相等
Student s1 = new Student(20210101, "Corley");
Student s2 = new Student(20210102, "Jack");
Student s3 = new Student(20210101, "Tony");
// 2.调用重写的equals方法,比较两个对象的内容
boolean res1 = s1.equals(s2);
System.out.println("res = " + res1);
System.out.println(s1 == s2);
boolean res2 = s1.equals(s3);
System.out.println("res = " + res2);
System.out.println(s1 == s3);
}
}
输出:
res = false
false
res = true
false
在重写的方法中进行了强制类型转换Student stu = (Student) obj;
,实现多态,使得可以调用子类中的get方法获取属性值;
当Student类中重写equals方法后,则调用重写后的方法,比较的是重写方法中指定的属性。
equals方法在非null对象引用上实现相等关系的比较,具有以下属性:
- 自反性
对于任何非空的引用x , x.equals(x)的值为true 。
- 对称性
对于任何非空引用值x和y , x.equals(y)的值为true当且仅当y.equals(x)的值为true 。
- 传递性
对于任何非空引用值 x、y 和 z,如果 x.equals(y) 的值为 true 并且 y.equals(z) 的值为 true,则 x.equals(z) 的值为 true。
- 一致性
对于任何非空引用值 x 和 y,x.equals(y) 的多次调用始终返回 true 或始终返回 false,前提是未修改对象的 equals 比较中使用的信息。
- 对于任何非空引用值 x,x.equals(null) 的值为 false。
为了处理最后一个特点中参数为空的情况与调用对象和参数对象指向同一个对象的特殊情况,可以进一步优化重写的equals方法,如下:
/**
* 为了比较两个对象的内容,这里是学号信息,需要重写equals方法
*/
@Override
public boolean equals(Object obj) {
// 特殊情况处理
// 当调用对象和参数对象指向同一个对象时,则内容一定相同,返回true
if (this == obj) return true;
// 当调用对象不为空而参数对象为空时,则内容一定不相同,返回false
if (null == obj) return false;
// 判断obj指向的对象是否为Student类型的对象,若是则进行判断
if (obj instanceof Student) {
Student stu = (Student) obj;
return this.getId() == stu.getId();
}
// 若不是则说明类型不一致,因此没有可比性、内容一定不相同,直接返回false
return false;
}
测试类如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/18 12:40
* @description javase-com.stage1.module3
*/
public class StudentTest {
public static void main(String[] args) {
// 1.使用有参方式构造2个Student类型对象并判断是否相等
Student s1 = new Student(20210101, "Corley");
Student s2 = new Student(20210102, "Jack");
Student s3 = new Student(20210101, "Tony");
Student s4 = null;
// 2.调用重写的equals方法,比较两个对象的内容
boolean res1 = s1.equals(s2);
System.out.println("res = " + res1);
System.out.println(s1 == s2);
boolean res2 = s1.equals(s3);
System.out.println("res = " + res2);
System.out.println(s1 == s3);
System.out.println(s1.equals(s4));
System.out.println(s1.equals(s1));
}
}
输出:
res = false
false
res = true
false
false
true
(4)hashCode方法的重写
int hashCode()
方法用于获取调用对象的哈希码值,即内存地址的编号:
若两个对象调用equals方法相等,则各自调用该方法的结果必须相同;
若两个调用对象equals方法不相等,则各自调用该方法的结果应该不相同;
为了使得该方法与equals方法保持一致,每当重写equals方法时,通常都需要重写 hashCode 方法,以维护 hashCode 方法的一般约定,即调用equals方法判断为相等的对象必须具有相等的哈希码值。
先调用hashCode()
方法获取哈希码值,如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/18 12:40
* @description javase-com.stage1.module3
*/
public class StudentTest {
public static void main(String[] args) {
// 1.使用有参方式构造2个Student类型对象并判断是否相等
Student s1 = new Student(20210101, "Corley");
Student s2 = new Student(20210102, "Jack");
Student s3 = new Student(20210101, "Tony");
Student s4 = null;
// 2.调用重写的equals方法,比较两个对象的内容
/*boolean res1 = s1.equals(s2);
System.out.println("res = " + res1);
System.out.println(s1 == s2);*/
boolean res2 = s1.equals(s3);
System.out.println("res = " + res2);
/*System.out.println(s1 == s3);
System.out.println(s1.equals(s4));
System.out.println(s1.equals(s1));*/
System.out.println("----------------------------------------");
// 调用从Object类中继承的hashCode方法,获取调用对象的hash码值
int h1 = s1.hashCode();
int h2 = s3.hashCode();
System.out.println("h1 = " + h1);
System.out.println("h2 = " + h2);
System.out.println(h1 == h2);
}
}
输出:
res = true
----------------------------------------
h1 = 440434003
h2 = 1032616650
false
可以看到,此时调用equals方法的结果是true,而调用hashCode()
方法得到的整数值不相同,违反了Java中的一般约定。
为了使得hashCode()
方法的结果与equals方法的结果保持一致,从而满足Java官方的一般约定,需要重写该方法:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/18 12:16
* @description javase-com.stage1.module3
*/
public class Student {
private int id; // 描述学号
private String name; // 描述姓名
public Student() {
}
public Student(int id, String name) {
setId(id);
setName(name);
}
public int getId() {
return id;
}
public void setId(int id) {
if (id > 0) {
this.id = id;
} else {
System.out.println("学号不合理");
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 为了比较两个对象的内容,这里是学号信息,需要重写equals方法
*/
@Override
public boolean equals(Object obj) {
// 特殊情况处理
// 当调用对象和参数对象指向同一个对象时,则内容一定相同,返回true
if (this == obj) return true;
// 当调用对象不为空而参数对象为空时,则内容一定不相同,返回false
if (null == obj) return false;
// 判断obj指向的对象是否为Student类型的对象,若是则进行判断
if (obj instanceof Student) {
Student stu = (Student) obj;
return this.getId() == stu.getId();
}
// 若不是则说明类型不一致,因此没有可比性、内容一定不相同,直接返回false
return false;
}
/**
* 为了使得hashCode()方法的结果与equals方法的结果保持一致,从而满足Java官方的一般约定,需要重写该方法
*/
@Override
public int hashCode() {
// return getId();
final int coefficient = 12;
final int constant = 31;
return getId() * coefficient + constant;
}
}
其中,return getId() * coefficient + constant;
是为了与getId()
方法进行区分。
测试类如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/18 12:40
* @description javase-com.stage1.module3
*/
public class StudentTest {
public static void main(String[] args) {
// 1.使用有参方式构造2个Student类型对象并判断是否相等
Student s1 = new Student(20210101, "Corley");
Student s2 = new Student(20210102, "Jack");
Student s3 = new Student(20210101, "Tony");
Student s4 = null;
// 2.调用重写的equals方法,比较两个对象的内容
boolean res1 = s1.equals(s2);
System.out.println("res = " + res1);
/*System.out.println(s1 == s2);*/
boolean res2 = s1.equals(s3);
System.out.println("res = " + res2);
/*System.out.println(s1 == s3);
System.out.println(s1.equals(s4));
System.out.println(s1.equals(s1));*/
System.out.println("----------------------------------------");
// 调用从Object类中继承的hashCode方法,获取调用对象的hash码值
int h1 = s1.hashCode();
int h2 = s2.hashCode();
int h3 = s3.hashCode();
System.out.println("h1 = " + h1);
System.out.println("h2 = " + h2);
System.out.println("h3 = " + h3);
}
}
输出:
res = false
res = true
----------------------------------------
h1 = 242521243
h2 = 242521255
h3 = 242521243
可以看到,此时两种方法保持了一致。
(5)toString方法的重写
String toString()
方法用于获取调用对象的字符串形式:
该方法默认返回的字符串为包名.类名@哈希码值的十六进制
;
为了返回更有意义的数据,需要重写该方法。
先直接调用继承自Object类的toString()
方法如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/18 12:40
* @description javase-com.stage1.module3
*/
public class StudentTest {
public static void main(String[] args) {
// 1.使用有参方式构造2个Student类型对象并判断是否相等
Student s1 = new Student(20210101, "Corley");
Student s2 = new Student(20210102, "Jack");
Student s3 = new Student(20210101, "Tony");
Student s4 = null;
// 2.调用重写的equals方法,比较两个对象的内容
boolean res1 = s1.equals(s2);
System.out.println("res = " + res1);
/*System.out.println(s1 == s2);*/
boolean res2 = s1.equals(s3);
System.out.println("res = " + res2);
/*System.out.println(s1 == s3);
System.out.println(s1.equals(s4));
System.out.println(s1.equals(s1));*/
System.out.println("----------------------------------------");
// 调用从Object类中继承的hashCode方法,获取调用对象的hash码值
int h1 = s1.hashCode();
int h2 = s2.hashCode();
int h3 = s3.hashCode();
System.out.println("h1 = " + h1);
System.out.println("h2 = " + h2);
System.out.println("h3 = " + h3);
System.out.println("----------------------------------------");
// 调用从Object类中继承下来的toSTring方法,获取调用对象的字符串形式:包名.类名@哈希码值的十六进制
String str1 = s1.toString();
System.out.println("str1 = " + str1);
}
}
输出:
res = false
res = true
----------------------------------------
h1 = 242521243
h2 = 242521255
h3 = 242521243
----------------------------------------
str1 = com.stage1.module3.Student@e74949b
可以看到,获取到了默认的字符串形式,但是字符串有意义的数据不多,此时可以对该方法进行改写。
Student类如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/18 12:16
* @description javase-com.stage1.module3
*/
public class Student {
private int id; // 描述学号
private String name; // 描述姓名
public Student() {
}
public Student(int id, String name) {
setId(id);
setName(name);
}
public int getId() {
return id;
}
public void setId(int id) {
if (id > 0) {
this.id = id;
} else {
System.out.println("学号不合理");
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 为了比较两个对象的内容,这里是学号信息,需要重写equals方法
*/
@Override
public boolean equals(Object obj) {
// 特殊情况处理
// 当调用对象和参数对象指向同一个对象时,则内容一定相同,返回true
if (this == obj) return true;
// 当调用对象不为空而参数对象为空时,则内容一定不相同,返回false
if (null == obj) return false;
// 判断obj指向的对象是否为Student类型的对象,若是则进行判断
if (obj instanceof Student) {
Student stu = (Student) obj;
return this.getId() == stu.getId();
}
// 若不是则说明类型不一致,因此没有可比性、内容一定不相同,直接返回false
return false;
}
/**
* 为了使得hashCode()方法的结果与equals方法的结果保持一致,从而满足Java官方的一般约定,需要重写该方法
*/
@Override
public int hashCode() {
// return getId();
final int coefficient = 12;
final int constant = 31;
return getId() * coefficient + constant;
}
/**
* 重写toString方法,获取更有意义的字符串数据
*/
@Override
public String toString() {
return "Student[id = " + getId() + ", name = " + getName() + "]";
}
}
测试类如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/18 12:40
* @description javase-com.stage1.module3
*/
public class StudentTest {
public static void main(String[] args) {
// 1.使用有参方式构造2个Student类型对象并判断是否相等
Student s1 = new Student(20210101, "Corley");
Student s2 = new Student(20210102, "Jack");
Student s3 = new Student(20210101, "Tony");
Student s4 = null;
// 2.调用重写的equals方法,比较两个对象的内容
boolean res1 = s1.equals(s2);
System.out.println("res = " + res1);
/*System.out.println(s1 == s2);*/
boolean res2 = s1.equals(s3);
System.out.println("res = " + res2);
/*System.out.println(s1 == s3);
System.out.println(s1.equals(s4));
System.out.println(s1.equals(s1));*/
System.out.println("----------------------------------------");
// 调用从Object类中继承的hashCode方法,获取调用对象的hash码值
int h1 = s1.hashCode();
int h2 = s2.hashCode();
int h3 = s3.hashCode();
System.out.println("h1 = " + h1);
System.out.println("h2 = " + h2);
System.out.println("h3 = " + h3);
System.out.println("----------------------------------------");
// 调用从Object类中继承下来的toSTring方法,获取调用对象的字符串形式:包名.类名@哈希码值的十六进制
String str1 = s1.toString();
System.out.println("str1 = " + str1);
System.out.println(s1);
System.out.println("hello, " + s2);
}
}
输出:
res = false
res = true
----------------------------------------
h1 = 242521243
h2 = 242521255
h3 = 242521243
----------------------------------------
str1 = Student[id = 20210101, name = Corley]
Student[id = 20210101, name = Corley]
hello, Student[id = 20210102, name = Jack]
可以看到,使用print或println打印引用或字符串拼接引用都会自动调用 toString()
方法。
(6)Student类以name属性为基准的改写
前面是以id为基准进行重写的,现在以name为基准重写方法。
Student类如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/18 12:16
* @description javase-com.stage1.module3
*/
public class Student {
private int id; // 描述学号
private String name; // 描述姓名
public Student() {
}
public Student(int id, String name) {
setId(id);
setName(name);
}
public int getId() {
return id;
}
public void setId(int id) {
if (id > 0) {
this.id = id;
} else {
System.out.println("学号不合理");
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 为了比较两个对象的内容,这里是学号信息,需要重写equals方法
*/
@Override
public boolean equals(Object obj) {
// 特殊情况处理
// 当调用对象和参数对象指向同一个对象时,则内容一定相同,返回true
if (this == obj) return true;
// 当调用对象不为空而参数对象为空时,则内容一定不相同,返回false
if (null == obj) return false;
// 判断obj指向的对象是否为Student类型的对象,若是则进行判断
if (obj instanceof Student) {
Student stu = (Student) obj;
// return this.getId() == stu.getId(); // 以学号为基准判断两个对象是否相等
// return this.getName() == stu.getName(); // 比较的是字符串对象的地址
return this.getName().equals(stu.getName()); // 比较姓名字符串的内容是否相同
}
// 若不是则说明类型不一致,因此没有可比性、内容一定不相同,直接返回false
return false;
}
/**
* 为了使得hashCode()方法的结果与equals方法的结果保持一致,从而满足Java官方的一般约定,需要重写该方法
*/
@Override
public int hashCode() {
// return getId();
final int coefficient = 12;
final int constant = 31;
return getName().hashCode() * coefficient + constant;
}
/**
* 重写toString方法,获取更有意义的字符串数据
*/
@Override
public String toString() {
return "Student[id = " + getId() + ", name = " + getName() + "]";
}
}
测试类如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/18 12:40
* @description javase-com.stage1.module3
*/
public class StudentTest {
public static void main(String[] args) {
// 1.使用有参方式构造2个Student类型对象并判断是否相等
Student s1 = new Student(20210101, "Corley");
Student s2 = new Student(20210102, "Jack");
Student s3 = new Student(20210101, "Corley");
Student s4 = null;
// 2.调用重写的equals方法,比较两个对象的内容
boolean res1 = s1.equals(s2);
System.out.println("res = " + res1);
/*System.out.println(s1 == s2);*/
boolean res2 = s1.equals(s3);
System.out.println("res = " + res2);
/*System.out.println(s1 == s3);
System.out.println(s1.equals(s4));
System.out.println(s1.equals(s1));*/
System.out.println("----------------------------------------");
// 调用从Object类中继承的hashCode方法,获取调用对象的hash码值
int h1 = s1.hashCode();
int h2 = s2.hashCode();
int h3 = s3.hashCode();
System.out.println("h1 = " + h1);
System.out.println("h2 = " + h2);
System.out.println("h3 = " + h3);
System.out.println("----------------------------------------");
// 调用从Object类中继承下来的toSTring方法,获取调用对象的字符串形式:包名.类名@哈希码值的十六进制
String str1 = s1.toString();
System.out.println("str1 = " + str1);
System.out.println(s1);
System.out.println("hello, " + s2);
}
}
输出:
res = false
res = true
----------------------------------------
h1 = -1479797801
h2 = 27611155
h3 = -1479797801
----------------------------------------
str1 = Student[id = 20210101, name = Corley]
Student[id = 20210101, name = Corley]
hello, Student[id = 20210102, name = Jack]
显然,此时比较的是name变量。
之前的id属于int类型,是基本数据类型,内存空间中存放的是数据本身,所以可以直接使用==
判断两个对象是否相同;
name属于String类型,是引用数据类型,内存中存放的是堆区中对应数据的地址,此时使用==
只能判断两个String对象的地址是否相同,也就是判断两个对象中姓名字符串的地址是否相同,显然不是我们所需要的;
此时我们需要调用字符串类的equals方法,也是对Object类equals方法的重写,用于比较两个字符串的内容是否相同;
此时对应也需要修改hashCode()
方法,也需要用到String类中重写的hashCode()
方法。
(7)equals方法和hashCode方法的生成
在实际开发中,可以自动生成equals方法和hashCode方法,直接使用IDEA自带的代码生成功能即可,有两种方式:
-
lntelliJ Default
-
java.util.Objects.equals and hashCode (java 7+)
演示如下:
其中,IDE生成的默认代码为:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (id != student.id) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
重写Objects类中的方式的代码如下:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return id == student.id && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
显然,后者更简洁。
toString()
方法也可以使用同样的方式生成。
3.包装类
(1)包装类的概念和分类
通常情况下认为基本数据类型的变量不是对象,为了满足万物皆对象 的理念就需要对基本数据类型的变量进行打包封装处理变成对象 ,而负责将这些变量声明为成员变量进行对象化处理的相关类,叫做包装类(Wrapper) 。
例如Student stu = new Student();
,显然此时stu是一个Student类型的对象,而在int num = 10;
中,从语法角度讲num是一个int类型的变量、而不是对象,而Java中有万物皆对象 的理念,此时应该将num进行处理、转变为一个对象才能符合这个理念。
Java官方提供了8种基本数据类型的包装类,如下:
包装类 | 对应基本类型 |
---|---|
java.lang.Byte | byte |
java.lang.Short | short |
java.lang.Integer | int |
java.lang.Long | long |
java.lang.Float | float |
java.lang.Double | double |
java.lang.Boolean | boolean |
java.lang.Character | char |
包装类的作用主要是为了将基本数据类型的变量打包成对象 ,从而满足万物皆对象 的理念。
(2)Integer类的概念和构造方式
java.lang.Integer
类内部包装了一个int类型的变量作为成员变量,同时声明为一个常量,主要用于实现对int类型的包装并提供int类型与String类之间的转换等方法。
Integer类中定义的常量包括:
常量类型和名称 | 功能介绍 |
---|---|
public static final int MAX_VALUE | 表示int类型可以描述的最大值,即 2 31 − 1 2^{31}-1 231−1 |
public static final int MIN_VALUE | 表示int类型可以描述的最小值,即 − 2 31 -2^{31} −231 |
public static final int SIZE | 表示int类型采用二进制补码形式的位数,即 4 ∗ 8 = 32 4*8=32 4∗8=32 |
public static final int BYTES | 表示int类型所占的字节个数,即4 |
public static final Class TYPE | 表示int类型的Class实例,即int |
现在对Integer类的常量进行测试,如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/19 9:46
* @description javase-com.stage1.module3
*/
public class IntegerTest {
public static void main(String[] args) {
// 1.打印Integer类中的常量数值
System.out.println("最大值:" + Integer.MAX_VALUE); // 2^31-1
System.out.println("最小值:" + Integer.MIN_VALUE); // -2^31
System.out.println("二进制位数:" + Integer.SIZE); // 32
System.out.println("字节数:" + Integer.BYTES); // 4
System.out.println("int类型对应的Class实例:" + Integer.TYPE); // int
}
}
输出:
最大值:2147483647
最小值:-2147483648
二进制位数:32
字节数:4
int类型对应的Class实例:int
Integer类中常用的方法如下:
方法声明 | 功能介绍 |
---|---|
Integer(int value) | 根据参数指定的整数来构造对象,已过时 |
Integer(String s) | 根据参数指定的字符串来构造对象,已过时 |
int intValue() | 获取调用对象中的整数值并返回 |
static Integer valueOf(int i) | 根据参数指定整数值得到Integer类型对象 |
boolean equals(Object obj) | 比较调用对象与参数指定的对象是否相等 |
String toString() | 返回描述调用对象数值的字符串形式 |
static int parseInt(String s) | 将字符串类型转换为int类型并返回 |
static String toString(int i) | 获取参数指定整数的十进制字符串形式 |
static String toBinaryString(int i) | 获取参数指定整数的二进制字符串形式 |
static String toHexString(int i) | 获取参数指定整数的十六进制字符串形式 |
static String toOctalString(int i) | 获取参数指定整数的八进制字符串形式 |
现在测试构造方法如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/19 9:46
* @description javase-com.stage1.module3
*/
public class IntegerTest {
public static void main(String[] args) {
// 1.打印Integer类中的常量数值
System.out.println("最大值:" + Integer.MAX_VALUE); // 2^31-1
System.out.println("最小值:" + Integer.MIN_VALUE); // -2^31
System.out.println("二进制位数:" + Integer.SIZE); // 32
System.out.println("字节数:" + Integer.BYTES); // 4
System.out.println("int类型对应的Class实例:" + Integer.TYPE); // int
System.out.println("------------------------------------");
// 2.使用构造方法构造Integer类型的对象
Integer it1 = new Integer(111);
System.out.println("it1 = " + it1); // 自动调用toString方法
Integer it2 = new Integer("222");
System.out.println("it2 = " + it2);
}
}
输出:
最大值:2147483647
最小值:-2147483648
二进制位数:32
字节数:4
int类型对应的Class实例:int
------------------------------------
it1 = 111
it2 = 222
可以看到,使用构造方法创建了Integer类型的对象,同时在打印时自动调用类中重写的toString()
方法来打印内容;
但是Integer(int value)
构造方法已弃用,改用静态工厂函数valueOf(int i)
,该方法有更好的空间和时间性能;Integer(String s)
也已弃用,使用 parseInt(String s)
将字符串转换为 int 类型,或使用 valueOf(String s)
将字符串转换为 Integer 对象。
使用如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/19 9:46
* @description javase-com.stage1.module3
*/
public class IntegerTest {
public static void main(String[] args) {
// 1.打印Integer类中的常量数值
System.out.println("最大值:" + Integer.MAX_VALUE); // 2^31-1
System.out.println("最小值:" + Integer.MIN_VALUE); // -2^31
System.out.println("二进制位数:" + Integer.SIZE); // 32
System.out.println("字节数:" + Integer.BYTES); // 4
System.out.println("int类型对应的Class实例:" + Integer.TYPE); // int
System.out.println("------------------------------------");
// 2.使用构造方法构造Integer类型的对象,构造方法已过时
Integer it1 = new Integer(111);
System.out.println("it1 = " + it1); // 自动调用toString方法
Integer it2 = new Integer("222");
System.out.println("it2 = " + it2);
// 使用valueOf方法创建对象
Integer it3 = Integer.valueOf(333); // 相当于从int类型到Integer类型的转换
System.out.println("it3 = " + it3); // 自动调用toString方法,得到的是String类型
Integer it4 = Integer.valueOf("444"); // 相当于从String类型到Integer类型的转换
System.out.println("it4 = " + it4); // 自动调用toString方法,得到的是String类型
// 获取调用对象的整数数值
int iv = it4.intValue(); // 相当于从Integer类型到int类型的转换
System.out.println("获取到的整数数值为" + iv); // 得到的是int类型
}
}
输出:
最大值:2147483647
最小值:-2147483648
二进制位数:32
字节数:4
int类型对应的Class实例:int
------------------------------------
it1 = 111
it2 = 222
it3 = 333
it4 = 444
获取到的整数数值为444
其中,static Integer valueOf()
方法中的参数为int类型时,相当于是从int类型到Integer类型的转换,参数是String类型时相当于是从String类型到Integer类型的转换,在打印时会自动调用toString()
方法,得到String类型;
int intValue()
方法相当于从Integer类型到int类型的转换,得到的就是int类型。
(3)Integer类的装箱和拆箱机制
Integer类是int类型的包装类,前面的例子中,Integer it3 = Integer.valueOf(333);
相当于从int类型到Integer类型的转换,这个过程称为装箱 ;
相反,int iv = it4.intValue();
相当于从Integer类型到int类型的转换,这个过程称为拆箱 。
在Java5之前,装箱和拆箱就是通过上面的方式实现的,即装箱需要将结果封装成包装类对象、拆箱需要将包装类对象拆分为基本类型数据,操作较为繁琐;
从Java5开始增加了自动装箱 和自动拆箱 的机制,直接通过赋值运算符即可实现自动装箱和自动拆箱。
同时,Integer类的内部提供了自动装箱池 技术,将-128到127之间的整数已经装箱完毕,当程序中使用该范围之间的整数时,无需装箱直接取用自动装箱池中的对象即可,从而提高效率。
如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/19 9:46
* @description javase-com.stage1.module3
*/
public class IntegerTest {
public static void main(String[] args) {
// 1.打印Integer类中的常量数值
System.out.println("最大值:" + Integer.MAX_VALUE); // 2^31-1
System.out.println("最小值:" + Integer.MIN_VALUE); // -2^31
System.out.println("二进制位数:" + Integer.SIZE); // 32
System.out.println("字节数:" + Integer.BYTES); // 4
System.out.println("int类型对应的Class实例:" + Integer.TYPE); // int
System.out.println("------------------------------------");
// 2.使用构造方法构造Integer类型的对象,构造方法已过时
Integer it1 = new Integer(111);
System.out.println("it1 = " + it1); // 自动调用toString方法
Integer it2 = new Integer("222");
System.out.println("it2 = " + it2);
// 使用valueOf方法创建对象
Integer it3 = Integer.valueOf(333); // 相当于从int类型到Integer类型的转换
System.out.println("it3 = " + it3); // 自动调用toString方法,得到的是String类型
Integer it4 = Integer.valueOf("444"); // 相当于从String类型到Integer类型的转换
System.out.println("it4 = " + it4); // 自动调用toString方法,得到的是String类型
// 获取调用对象的整数数值
int iv1 = it4.intValue(); // 相当于从Integer类型到int类型的转换
System.out.println("获取到的整数数值为" + iv1); // 得到的是int类型
System.out.println("------------------------------------");
// 3.Java5开始,自动装箱和拆箱
Integer it5 = 100; // 直接通过赋值运算符实现自动装箱
int iv2 = it5; // 直接通过赋值运算符实现自动拆箱
System.out.println("------------------------------------");
// 4.装箱和拆箱的笔试考点
Integer it6 = 128;
Integer it7 = 128;
Integer it8 = new Integer(128);
Integer it9 = new Integer(128);
System.out.println(it6 == it7); // false
System.out.println(it6.equals(it7)); // true
System.out.println(it8 == it9); // false
System.out.println(it8.equals(it9)); // true
// 自动装箱池
Integer it10 = 127;
Integer it11 = 127;
Integer it12 = new Integer(127);
Integer it13 = new Integer(127);
System.out.println(it10 == it11); // true
System.out.println(it10.equals(it11)); // true
System.out.println(it12 == it13); // false
System.out.println(it12.equals(it13)); // true
}
}
输出:
最大值:2147483647
最小值:-2147483648
二进制位数:32
字节数:4
int类型对应的Class实例:int
------------------------------------
it1 = 111
it2 = 222
it3 = 333
it4 = 444
获取到的整数数值为444
------------------------------------
------------------------------------
false
true
false
true
true
true
false
true
可以看到,127和128进行比较的结果是不同的,因为127位于自动装箱池中,进行装箱时可以直接使用,所以it10和it11使用(指向)的是同一个Integer类型的对象,因此地址相同,it10 == it11
的结果也为true,而128没有在自动装箱池中,每次装箱都会新建一个Integer对象,所以得到的it6和it7是两个不同的对象、地址不同,因此it6 == it7
的值为false;
也可以根据业务的需要调整自动装箱池的范围,此时需要用到JVM调优。
(4)Integer类的常用方法
现在对Integer类的其他常用方法进行使用,如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/19 9:46
* @description javase-com.stage1.module3
*/
public class IntegerTest {
public static void main(String[] args) {
// 1.打印Integer类中的常量数值
System.out.println("最大值:" + Integer.MAX_VALUE); // 2^31-1
System.out.println("最小值:" + Integer.MIN_VALUE); // -2^31
System.out.println("二进制位数:" + Integer.SIZE); // 32
System.out.println("字节数:" + Integer.BYTES); // 4
System.out.println("int类型对应的Class实例:" + Integer.TYPE); // int
System.out.println("------------------------------------");
// 2.使用构造方法构造Integer类型的对象,构造方法已过时
Integer it1 = new Integer(111);
System.out.println("it1 = " + it1); // 自动调用toString方法
Integer it2 = new Integer("222");
System.out.println("it2 = " + it2);
// 使用valueOf方法创建对象
Integer it3 = Integer.valueOf(333); // 相当于从int类型到Integer类型的转换
System.out.println("it3 = " + it3); // 自动调用toString方法,得到的是String类型
Integer it4 = Integer.valueOf("444"); // 相当于从String类型到Integer类型的转换
System.out.println("it4 = " + it4); // 自动调用toString方法,得到的是String类型
// 获取调用对象的整数数值
int iv1 = it4.intValue(); // 相当于从Integer类型到int类型的转换
System.out.println("获取到的整数数值为" + iv1); // 得到的是int类型
System.out.println("------------------------------------");
// 3.Java5开始,自动装箱和拆箱
Integer it5 = 100; // 直接通过赋值运算符实现自动装箱
int iv2 = it5; // 直接通过赋值运算符实现自动拆箱
System.out.println("------------------------------------");
// 4.装箱和拆箱的笔试考点
Integer it6 = 128;
Integer it7 = 128;
Integer it8 = new Integer(128);
Integer it9 = new Integer(128);
System.out.println(it6 == it7); // false
System.out.println(it6.equals(it7)); // true
System.out.println(it8 == it9); // false
System.out.println(it8.equals(it9)); // true
// 自动装箱池
Integer it10 = 127;
Integer it11 = 127;
Integer it12 = new Integer(127);
Integer it13 = new Integer(127);
System.out.println(it10 == it11); // true
System.out.println(it10.equals(it11)); // true
System.out.println(it12 == it13); // false
System.out.println(it12.equals(it13)); // true
System.out.println("------------------------------------");
// 5.实现静态方法的调用
// int iv3 = Integer.parseInt("555sss"); // 编译通过,运行时发生NumberFormatException异常,因为字符串中有非数字的字符
int iv3 = Integer.parseInt("555");
System.out.println("根据字符串转换得到的整数为:" + iv3);
System.out.println("根据参数指定的整数获取对应的十进制字符串:" + Integer.toString(666));
System.out.println("根据参数指定的整数获取对应的二进制字符串:" + Integer.toBinaryString(666));
System.out.println("根据参数指定的整数获取对应的八进制字符串:" + Integer.toOctalString(666));
System.out.println("根据参数指定的整数获取对应的十六进制字符串:" + Integer.toHexString(666));
}
}
输出:
最大值:2147483647
最小值:-2147483648
二进制位数:32
字节数:4
int类型对应的Class实例:int
------------------------------------
it1 = 111
it2 = 222
it3 = 333
it4 = 444
获取到的整数数值为444
------------------------------------
------------------------------------
false
true
false
true
true
true
false
true
------------------------------------
根据字符串转换得到的整数为:555
根据参数指定的整数获取对应的十进制字符串:666
根据参数指定的整数获取对应的二进制字符串:1010011010
根据参数指定的整数获取对应的八进制字符串:1232
根据参数指定的整数获取对应的十六进制字符串:29a
其中,int iv3 = Integer.parseInt("555sss");
编译通过,运行时发生NumberFormatException异常,因为字符串中有非数字的字符。
(5)Double类的概念和使用
java.lang.Double
类型内部包装了一个double类型的变量作为成员变量,主要用于实现对double类型的包装并提供double类型与String类之间的转换等方法。
Double类的常用常量如下:
常量类型和名称 | 含义 |
---|---|
public static final int SIZE | 表示double类型的二进制位数,值为64 |
public static final int BYTES | 表示double类型的字节个数,值为8 |
public static final Class TYPE | 表示double类型的Class实例,值为double |
常用的方法如下:
方法声明 | 功能介绍 |
---|---|
Double(double value) | 根据参数指定的浮点数据来构造对象(已过时) |
Double(String s) | 根据参数指定的字符串来构造对象 (已过时) |
double doubleValue() | 获取调用对象中的浮点数据并返回 |
static Double valueOf(double d) | 根据参数指定浮点数据得到Double类型对象 |
boolean equals(Object obj) | 比较调用对象与参数指定的对象是否相等 |
String toString() | 返回描述调用对象数值的字符串形式 |
static double parseDouble(String s) | 将字符串类型转换为double类型并返回 |
boolean isNaN() | 判断调用对象的数值是否为非数字 |
现在对Double类的方法进行测试,如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/19 17:50
* @description javase-com.stage1.module3
*/
public class DoubleTest {
public static void main(String[] args) {
// 1.在Java5之前装箱和拆箱的实现
// 实现从double类型到Double类型的转换,装箱
Double db1 = Double.valueOf(3.14159);
System.out.println("db1 = " + db1);
// 实现从Double类型到double类型的转换,拆箱
double d1 = db1.doubleValue();
System.out.println("d1 = " + d1);
System.out.println("-----------------------------------------------");
// 2.从Java5开始,实现了自动装箱和自动拆箱
Double db2 = 2.71828;
double d2 = db2;
System.out.println("-----------------------------------------------");
// 3.实现成员方法和静态方法的调用
double d3 = Double.parseDouble("3.14");
System.out.println("d3 = " + d3);
System.out.println("db2 is not a number: " + db2.isNaN());
Double db3 = Double.valueOf(0/0.0);
System.out.println("db3 is not a number: " + db3.isNaN());
}
}
输出:
db1 = 3.14159
d1 = 3.14159
-----------------------------------------------
-----------------------------------------------
d3 = 3.14
db2 is not a number: false
db3 is not a number: true
和Integer类类似,Double db1 = Double.valueOf(3.14159);
实现了从double类型到Double类型的转换,属于装箱,double d1 = db1.doubleValue();
实现了从Double类型到double类型的转换,属于拆箱;
因为0/0.0
的计算结果是NaN
,不是数字,所以db3.isNaN()
的结果为true;
Double类型没有自动装箱池。
java.lang.Number
类是一个抽象类,是上述6个数值类的父类,用来描述所有类共有的成员,定义了一些抽象方法,需要继承自它的子类进行重写。
(6)Boolean类的概念和使用
java.lang.Boolean
类型内部包装了一个boolean类型的变量作为成员变量,主要用于实现对boolean类型的包装并提供boolean类型与String类之间的转换等方法。
Boolean类中的常用常量如下:
常量类型和名称 | 功能介绍 |
---|---|
public static final Boolean FALSE | 对应基值为false的对象 |
public static final Boolean TRUE | 对应基值为true的对象 |
public static final Class TYPE | 表示boolean类型的Class实例,值为boolean |
常用方法如下:
方法声明 | 功能介绍 |
---|---|
Boolean(boolean value) | 根据参数指定的布尔数值来构造对象(已过时) |
Boolean(String s) | 根据参数指定的字符串来构造对象 (已过时) |
boolean booleanValue() | 获取调用对象中的布尔数值并返回 |
static Boolean valueOf(boolean b) | 根据参数指定布尔数值得到Boolean类型对象 |
boolean equals(Object obj) | 比较调用对象与参数指定的对象是否相等 |
String toString() | 返回描述调用对象数值的字符串形式 |
static boolean parseBoolean(String s) | 将字符串类型转换为boolean类型并返回 |
现在对常用的方法测试如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/19 18:23
* @description javase-com.stage1.module3
*/
public class BooleanTest {
public static void main(String[] args) {
// 1.Java5之前,使用方法进行装箱和拆箱
// 相当于从boolean类型到Boolean类型的转换,装箱
Boolean bo1 = Boolean.valueOf(true);
System.out.println("bo1 = " + bo1);
// 相当于从Boolean类型到boolean类型的转换,拆箱
boolean b1 = bo1.booleanValue();
System.out.println("b1 = "+ b1);
System.out.println("------------------------------------------");
// 2.Java5开始,支持自动装箱和自动拆箱
Boolean bo2 = false;
boolean b2 = bo2;
System.out.println("b2 = " + b2);
System.out.println("------------------------------------------");
// 3.实现String类型到Booelan类型的转换
// boolean b3 = Boolean.parseBoolean("tru"); // 只有传的字符串为true(不区分大小写)时,才会转化为true,否则都会转为false
boolean b3 = Boolean.parseBoolean("true");
boolean b4 = Boolean.parseBoolean("TrUE");
System.out.println("b3 = " + b3);
System.out.println("b4 = " + b4);
}
}
输出:
bo1 = true
b1 = true
------------------------------------------
b2 = false
------------------------------------------
b3 = true
b4 = true
其中,Boolean bo1 = Boolean.valueOf(true);
相当于从boolean类型到Boolean类型的转换,实现装箱,boolean b1 = bo1.booleanValue();
相当于从Boolean类型到boolean类型的转换,实现拆箱;
parseBoolean(String s)
方法将字符串转为boolean值时,只有传的字符串为true(不区分大小写)时,才会转化为true,否则都会转为false。
(7)Character类的概念和使用
java.lang.Character
类型内部包装了一个char类型的变量作为成员变量,主要用于实现对char类型的包装并提供字符类别的判断和转换等方法。
Character类中常用的常量包括:
常量类型和名称 | 功能介绍 |
---|---|
public static final int SIZE | 表示char类型的二进制位数,值为16 |
public static final int BYTES | 表示char类型的字节个数,值为2 |
public static final Class TYPE | 表示char类型的Class实例,值为char |
常用方法如下:
方法声明 | 功能介绍 |
---|---|
Character(char value) | 根据参数指定的字符数据来构造对象(已过时) |
char charValue() | 获取调用对象中的字符数据并返回 |
static Character valueOf(char c) | 根据参数指定字符数据得到Character类型对象 |
boolean equals(Object obj) | 比较调用对象与参数指定的对象是否相等 |
String toString() | 返回描述调用对象数值的字符串形式 |
static boolean isUpperCase(char ch) | 判断参数指定字符是否为大写字符 |
static boolean isLowerCase(char ch) | 判断参数指定字符是否为小写字符 |
static boolean isDigit(char ch) | 判断参数指定字符是否为数字字符 |
static char toUpperCase(char ch) | 将参数指定的字符转换为大写字符 |
static char toLowerCase(char ch) | 将参数指定的字符转换为小写字符 |
现在对常用的方法进行测试:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/19 18:37
* @description javase-com.stage1.module3
*/
public class CharacterTest {
public static void main(String[] args) {
// 1.Java5之前,调用方法实现装箱和拆箱
// 相当于从char类型到Character类型的转换,装箱
Character ca1 = Character.valueOf('a');
System.out.println("ca1 = " + ca1);
// 相当于从Character类型到char类型的转换,拆箱
char c1 = ca1.charValue();
System.out.println("c1 = " + c1);
System.out.println("---------------------------");
// 2.Java5以后,支持自动装箱和自动拆箱
Character ca2 = 'B';
char c2 = ca2;
System.out.println("c2 = " + c2);
System.out.println("---------------------------");
// 3.实现字符类型的判断和转换
System.out.println(Character.isUpperCase(c1)); // 判断是否是大写字母
System.out.println(Character.isLowerCase(c1)); // 判断是否是小写字母
System.out.println(Character.isDigit(c1)); // 判断是否是数字
System.out.println("转换为大写字母是:" + Character.toUpperCase(c1)); // 转换为大写字母
System.out.println("转换为小写字母是:" + Character.toLowerCase(c1)); // 转换为小写字母
}
}
输出:
ca1 = a
c1 = a
---------------------------
c2 = B
---------------------------
false
true
false
转换为大写字母是:A
转换为小写字母是:a
其中,Character ca1 = Character.valueOf('a');
相当于从char类型到Character类型的转换,实现装箱,char c1 = ca1.charValue();
相当于从Character类型到char类型的转换,实现拆箱。
(8)包装类的使用总结
-
本数据类型转换为对应包装类的方式
调用包装类的构造方法或静态方法valueOf,实现装箱 -
获取包装类对象中基本数据类型变量数值的方式
调用包装类中的xxxValue方法,实现拆箱 -
字符串转换为基本数据类型的方式
调用包装类中的parseXxx方法
4.数学处理类
(1)Math类的概念和使用
java.lang.Math
类主要用于提供执行数学运算的方法,如对数、平方根等。
Math类常用的方法如下:
方法声明 | 功能介绍 |
---|---|
static int max(int a, int b) | 返回两个参数中的最大值 |
static int min(int a, int b) | 返回两个参数中的最小值 |
static double pow(double a, double b) | 返回第一个参数的幂 |
static int abs(int a) | 返回参数指定数值的绝对值 |
static long round(double a) | 返回参数四舍五入的结果 |
static double sqrt(double a) | 返回参数的平方根 |
static double random() | 返回0.0到1.0的随机数 |
可以看到,这些方法都是静态方法。
现在对Math类中的方法进行测试,如下:
package com.stage1.module3;
/**
* @author Corley
* @date 2021/7/20 9:01
* @description javase-com.stage1.module3
* 编程使用Math类中的常用方法
*/
public class MathTest {
public static void main(String[] args) {
System.out.println("两个数中的最大值:" + Math.max(12, 20));
System.out.println("两个数中的最小值:" + Math.min(12, 20));
System.out.println("平方计算结果是:" + Math.pow(3, 4));
System.out.println("绝对值计算结果是:" + Math.abs(-2.5));
System.out.println("四舍五入结果是:" + Math.round(3.14159));
System.out.println("平方根结果是:" + Math.sqrt(16));
System.out.println("生成随机数是:" + Math.random());
}
}
输出:
两个数中的最大值:20
两个数中的最小值:12
平方计算结果是:81.0
绝对值计算结果是:2.5
四舍五入结果是:3
平方根结果是:4.0
生成随机数是:0.8086045361409571
(2)BigDecimal的概念和使用
由于float类型和double类型在运算时可能会有误差,若希望实现精确运算则需要借助java.math.BigDecimal
类。
BigDecimal类中的常用方法如下:
方法声明 | 功能介绍 |
---|---|
BigDecimal(String val) | 根据参数指定的字符串来构造对象 |
BigDecimal add(BigDecimal augend) | 用于实现加法运算 |
BigDecimal subtract(BigDecimal subtrahend) | 用于实现减法运算 |
BigDecimal multiply(BigDecimal multiplicand) | 用于实现乘法运算 |
BigDecimal divide(BigDecimal divisor) | 用于实现除法运算 |
使用BigDecimal类中的常用方法如下:
package com.stage1.module3;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* @author Corley
* @date 2021/7/20 9:11
* @description javase-com.stage1.module3
*/
public class BigDecimalTest {
public static void main(String[] args) {
// 1.构造2个BigDecimal对象
BigDecimal bd1 = new BigDecimal("3.14159");
BigDecimal bd2 = new BigDecimal("31.4159");
// 2.使用构造的对象实现加减乘除运算
System.out.println("加法运算:" + bd1.add(bd2));
System.out.println("减法运算:" + bd1.subtract(bd2));
System.out.println("乘法运算:" + bd1.multiply(bd2));
System.out.println("除法运算:" + bd1.divide(bd2));
System.out.println("------------------------------------");
// 3.使用BigDecimal实现精确计算
System.out.println(0.1 + 0.2);
BigDecimal bd3 = new BigDecimal("0.1");
BigDecimal bd4 = new BigDecimal("0.2");
System.out.println("精确计算:" + bd3.add(bd4));
System.out.println("------------------------------------");
// 4.注意事项
BigDecimal bd5 = new BigDecimal("0.314159");
BigDecimal bd6 = new BigDecimal("2.71828");
// System.out.println("除法运算:" + bd5.divide(bd6)); // java.lang.ArithmeticException
System.out.println("除法运算:" + bd5.divide(bd6, RoundingMode.UP));
}
}
输出:
加法运算:34.55749
减法运算:-28.27431
乘法运算:98.695877281
除法运算:0.1
------------------------------------
0.30000000000000004
精确计算:0.3
------------------------------------
除法运算:0.115573
可以看到,doube类型进行计算时存在误差,使用BigDecimal时计算不会存在误差;
在计算不能除尽时,会抛出异常java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
,此时需要给divide()
方法传入参数、指定舍入模式,这里可以使用RoundingMode.UP
,即最常用的四舍五入模式。
(3)BIgInteger类的概念和使用
若希望表示比long类型范围还大的整数数据,则需要借助java.math.BigInteger
类。
BigInteger类的常用方法如下:
方法声明 | 功能介绍 |
---|---|
BigInteger(String val) | 根据参数指定的字符串来构造对象 |
BigInteger add(BigInteger val) | 用于实现加法运算 |
BigInteger subtract(BigInteger val) | 用于实现减法运算 |
BigInteger multiply(BigInteger val) | 用于实现乘法运算 |
BigInteger divide(BigInteger val) | 用于实现除法运算 |
BigInteger remainder(BigInteger val) | 用于实现取余运算 |
BigInteger[] divideAndRemainder(BigInteger val) | 用于实现取商和余数的运算 |
BigInteger类中的常用方法使用如下:
package com.stage1.module3;
import java.math.BigInteger;
/**
* @author Corley
* @date 2021/7/20 9:45
* @description javase-com.stage1.module3
*/
public class BigIntegerTest {
public static void main(String[] args) {
// 1.构造2个BigInteger类型的对象
BigInteger bi1 = new BigInteger("123");
BigInteger bi2 = new BigInteger("321");
// 2.实现加减乘除求余运算
System.out.println("加法运算:" + bi1.add(bi2));
System.out.println("减法运算:" + bi1.subtract(bi2));
System.out.println("乘法运算:" + bi1.multiply(bi2));
System.out.println("除法运算:" + bi1.divide(bi2));
System.out.println("求余运算:" + bi1.remainder(bi2));
System.out.println("----------------------------------------");
// 3.同时得到商和余数
BigInteger[] bis = bi1.divideAndRemainder(bi2);
for (int i = 0; i < bis.length; i++) {
System.out.println("下标为" + i + "的元素的值为" + bis[i]);
}
}
}
输出:
加法运算:444
减法运算:-198
乘法运算:39483
除法运算:0
求余运算:123
----------------------------------------
下标为0的元素的值为0
下标为1的元素的值为123
总结
Java核心库是Java官方提供的,封装了常用的基础操作,我们不需要自己实现、直接调用即可,可以大大提高开发效率。