Arrays&Object&System&Math&Random&包装类
学习目标:
1. 熟练掌握Arrays工具类应用
2. 熟练掌握Object类应用
3. 熟练掌握System类应用
4. 熟练掌握Math工具类应用
5. 熟练掌握Random类应用
6. 熟练应用包装类
一、Arrays 数组工具类
1.1 Arrays 的基本应用
参照jdk8 api 文档 数组工具类Arrays 常用方法如下:
- asList : 返回由指定数组支持的一个固定大小的列表;
- binarySearch:使用二进制搜索算法搜索指定的值的字节数组;
- copyOf:复制指定的数组;
- copyOfRange:将指定的数组指定的范围复制到一个新的数组中;
- fill:将指定内容填充到数组中
- sort:为数组排序
- toString: 返回数组元素的字符串表示
示例1:Arrays常用方法演示
/**
* 数组的常用方法
*/
public class ArraysDemo1 {
/*程序入口*/
public static void main(String[] args) {
//1.将参数的数据放入集合中,集合是存放数据的容器,以后详细讲解,现在先理解数据工具类的方法
List<Integer> list = Arrays.asList(1, 2, 3);
System.out.println(list);
//2.二分查找,从数组中查找指定元素的下表;数组必须先排序
int[] arr = {1,2,3,9,10,11};
int index = Arrays.binarySearch(arr, 11);
System.out.println(index);
//3.数组复制,将指定数组复制到新数组中;第一个参数是要复制的数组,第二个参数是复制的长度
int[] arr2 = Arrays.copyOf(arr,arr.length-1);
System.out.println(Arrays.toString(arr2));
//4.数组复制,复制指定数组的子数组
int[] arr3 = Arrays.copyOfRange(arr, 0, 2);
System.out.println(Arrays.toString(arr3));
//5. 数组排序
int[] arr4 = {1,9,2,7,11};
Arrays.sort(arr4);
System.out.println(Arrays.toString(arr4));
//6.数组填充
Arrays.fill(arr4,1);
System.out.println(Arrays.toString(arr4));
}
}
1.2 自然排序
Arrays.sort默认只能对基本数据类型排序,无法对引用数据类型排序;引用数据类型要想完成排序需要实现Comparable接口,并重写compareTo方法。
Comparable接口使用api如下
引用数据类型总结如下:
- 被比较的对象实现Comparable接口
- 重写compareTo方法, 当前对象与当参数进行比较返回负数代表小于,0代表等于,1代表大于。
- 如果compareTo方法的参数是null时抛出空指针异常,如果参数和档期对象类型不一致抛出类型转换异常
示例2:根据用户的年龄为用户排序(自然排序)
/*
引用类型自然排序
*/
public class ArraysDemo2 {
/*程序入口*/
public static void main(String[] args) {
//定义user数组,并设置数组元素内容
User[] users = new User[4];
for (int i = 0; i <users.length; i++) {
User user = new User();
user.setId(i+1);
user.setName("张三"+(i+1));
user.setAge((int)(Math.random()*100));
users[i] = user;
}
//排序
Arrays.sort(users);
//查看
System.out.println(Arrays.toString(users));
}
}
class User implements Comparable{
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Object o) {
if(o==null){
throw new NullPointerException("null不能参与排序");
}
if(!(o instanceof User)){
throw new ClassCastException();
}
User user = (User)o;
return this.age-user.getAge();
}
}
注意:这用排序方式称为自然排序
1.3 定制排序
查看帮助文档我们发现排序方法还有如下重载方式
这种排序方式称为定制排序,参数二是Comparator接口实现类对象,该对象要重写compare方法,该方法的重写过程如下:
- 参数1与参数2比较返回负数代表小于,0代表等于,1代表大于。
- 如果方法的参数是null时抛出空指针异常,如果两个参数的类型和数组元素的类型不一致报类型转换异常。
示例3:数组的定制排序
public class ArraysDemo3 {
public static void main(String[] args) {
//定义user数组,并设置数组元素内容
Customer[] customers = new Customer[4];
for (int i = 0; i <customers.length; i++) {
Customer customer = new Customer();
customer.setId(i+1);
customer.setName("张三"+(i+1));
customer.setAge((int)(Math.random()*100));
customers[i] = customer;
}
//定制排序
Arrays.sort(customers, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if(o1==null || o2==null){
throw new NullPointerException();
}
if(!(o1 instanceof Customer) || !(o2 instanceof Customer)){
throw new ClassCastException();
}
Customer customer1 = (Customer)o1;
Customer customer2 = (Customer)o2;
return customer1.getAge()-customer2.getAge();
}
});
//查看
System.out.println(Arrays.toString(customers));
}
}
class Customer{
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Customer{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
练习题:定义User数组,User类属性如下:id,name,age;通过自然排序给User数组排序,优先按照年龄排序,如果年龄相同,按照姓名排序。
二、Object类进阶讲解
2.1 Object类已学方法复习
Object类api 如下:
其中equals方法、hashCode方法、toString方法我们已经讲完,这里简单复习下:
equals方法只能比较引用数据类型,默认比较的是内存地址是否相等,可以重写Object类的equals方法,重写为比较对象的内容是否相等。
hashCode方法显示的是对象的哈希值;支持此方法是为了方面使用HashMap所提供的散列表。
对象的哈希码值默认是根据对象的内存地址数值经过哈希算法得出的哈希值。所以哈希值不是内存地址,但和内存地址有关系。因此hashCode要满足如下约束:
- 如果两个对象的equals(obj)方法是相等的,那么对应的hashCode值也是一样的。
- 如果两个对象的equals(obj)方法是不相等的,那么对应的hashCode值尽量不一样,如果一样会影响HashMap容器的性能。
结论:**重写equals方法的同时要重写hashCode()方法;**因为equals方法默认比较的是内存地址,那么对应的hashCode也是默认设计为对象地址相同,hashCode一定相同;对象地址不同,hashCode值尽量不一样(一样也没事);
重写后的equals方法比较的是对象的内容是否相等,那么对应的hashCode也要重写为相同内容的对象hashCode值一定相等,对象内容不同的hashCode值尽量不等(不一样也没事)。
toStirng方法默认是对象内存地址的字符串表示,重写后可以表示对象的属性内容。
2.2 Object类克隆方法基本使用
Object类 提供 clone方法,方便对象的克隆操作。我们参照官方api发现java类要想实现克隆必须实现Cloneable接口
Cloneable 接口api 描述如下:
示例1:复制User对象
/**
* 完成User对象的克隆
*/
public class CloneDemo1 {
public static void main(String[] args) throws Exception {
//1.创建对象
User user = new User();
user.setId(1);
user.setName("张三");
user.setAge(18);
//2.克隆对象
User user2 = (User)user.clone();
//3.查看user2对象内容
System.out.println(user2);
//4.查看两个对象的地址是否相等,不等表示确实是内容克隆
System.out.println(user==user2);
}
}
class User extends Object implements Cloneable{
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
2.3 浅拷贝与深拷贝
浅拷贝与深拷贝的含义如下:
- 浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 。
- 深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象。
区别:被拷贝的对象的属性都是基本类型时,不存在浅拷贝;被拷贝的对象的属性存在引用类型时,浅拷贝后,这两个对象只要有一个改变引用类型属性的内容,就会影响另一个对象,因为二者的应用类型属性指向同一个内存地址;深拷贝改变新对象不会影响原对象,他们之间互不影响。
示例1:完成产品的浅拷贝
/**
* 产品的浅拷贝
*/
public class Product implements Cloneable{
//产品id
private int id;
//产品名字
private String name;
//产品分类信息
private Category category;
public Product(int id, String name, Category category) {
this.id = id;
this.name = name;
this.category = category;
}
public Product() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
@Override
public String toString() {
return "Product{" +
"id=" + id +
", name='" + name + '\'' +
", category=" + category +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
/*程序入口*/
public static void main(String[] args) throws Exception{
//创建产品分类对象,产品对象,并将产品分类对象注入产品对象中
Category category = new Category(1,"家电");
Product product1 = new Product(1,"联想笔记本",category);
//浅拷贝产品对象
Product product2 = (Product) product1.clone();
//改变拷贝后的对象的引用类型属性的内容
product2.getCategory().setName("笔记本");
//发现拷贝前后的两个对象的引用类型属性内容都变了
System.out.println(product2);
System.out.println(product1);
}
}
//产品分类
class Category{
//分类id
private int id;
//分类名字
private String name;
public Category(int id, String name) {
this.id = id;
this.name = name;
}
public Category() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Category{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
示例2:完成产品类的深拷贝
/**
* 产品的深拷贝
*/
public class Product implements Cloneable{
//产品id
private int id;
//产品名字
private String name;
//产品分类信息
private Category category;
public Product(int id, String name, Category category) {
this.id = id;
this.name = name;
this.category = category;
}
public Product() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
@Override
public String toString() {
return "Product{" +
"id=" + id +
", name='" + name + '\'' +
", category=" + category +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
//拷贝产品类
Product product = (Product) super.clone();
//将产品类的分类属性拷贝一份,赋值到拷贝后的产品类
product.category = (Category) category.clone();
return product;
}
/*程序入口*/
public static void main(String[] args) throws Exception{
//创建产品分类对象,产品对象,并将产品分类对象注入产品对象中
Category category = new Category(1,"家电");
Product product1 = new Product(1,"联想笔记本",category);
//浅拷贝产品对象
Product product2 = (Product) product1.clone();
//改变拷贝后的对象的引用类型属性的内容
product2.getCategory().setName("笔记本");
//拷贝前的对象的引用类型属性不受拷贝后对象的影响
System.out.println(product2);
System.out.println(product1);
}
}
//产品分类
class Category implements Cloneable{
//分类id
private int id;
//分类名字
private String name;
public Category(int id, String name) {
this.id = id;
this.name = name;
}
public Category() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Category{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
三、System工具类使用
System类的常用方法如下:
- arraycopy(Object src, int srcPos, Object dest, int destPos, int length) 从指定的源数组中复制一个数组,开始在指定的位置,到目标数组的指定位置。
- currentTimeMillis() 返回当前时间以毫秒为单位。
- getProperties() 确定当前系统属性。
- getProperty(String key) 获取指定的键指示的系统属性。
示例1:System类常用方法使用
/**
* 系统类常用方法
*/
public class SystemDemo {
public static void main(String[] args) {
int[] arr = {1,3,5,7,9};
//复制数组
// 第一个参数是源数组,第二个参数是从原数组的第几个下标开始赋值,第三个参数是被复制的目标数组,
// 第四个参数是被复制数组从第几个下标开始复制元素,第五个参数是复制的长度
System.arraycopy(arr,3,arr,2,2);
System.out.println(Arrays.toString(arr));
//获得系统的当前时间的毫秒值
System.out.println(System.currentTimeMillis());
//获得系统中的所有属性
Properties properties = System.getProperties();
System.out.println(properties);
//获得指定key的系统属性
String result = System.getProperty("sun.boot.library.path");
System.out.println(result);
}
}
四、Math工具类使用
数学工具类常用方法如下:
- abs返回一个数的绝对值
- ceil 向上取整
- floor向下取整
- round四舍五入
- max取最大值
- min取最小值
- random随机数
示例1:Math的常用方法演示
public class MathDemo {
public static void main(String[] args) {
//1. abs返回一个数的绝对值
System.out.println(Math.abs(-5));
//2. ceil 向上取整
System.out.println(Math.ceil(1.1));
//3. floor向下取整
System.out.println(Math.floor(1.9));
//4. round四舍五入
System.out.println(Math.round(4.5));
//5. max取最大值
System.out.println(Math.max(1,2));
//6. min取最小值
System.out.println(Math.min(1,2));
//7. random随机数(0-1之间随机包含0不包含1)
System.out.println(Math.random());
}
}
五、Random 类使用
Random是一个随机数类,能生成各种类型的随机数
示例1:Random类随即时演示
public class RandomDemo {
public static void main(String[] args) {
//创建随机数对象
Random random = new Random();
//随机0-10之间的随机数包含0不包含10
System.out.println(random.nextInt(10));
//随机boolean类型
System.out.println(random.nextBoolean());
//随机0-1之间的小数包含0不包含1
System.out.println(random.nextDouble());
}
}
六、包装类
6.1 包装类的概述
针对八种基本数据类型定义相应的引用类型—包装类(封装类) ,有了类的特点,就可以调用类中的方法,Java才是真正的面向对象
6.2 装箱操作
基本数据类型包装成包装类的过程叫装箱
-
通过包装类的构造器实现: int i = 1; Integer t = new Integer(i);
-
还可以通过字符串参数构造包装类对象: Float f = new Float(“4.56”); Long l = new Long(“asdf”); 如果格式错误报NumberFormatException
public static void main(String[] args) { //1.Byte类型 byte i = 1; Byte a = new Byte(i); //2.Short 类型 Short b = new Short(i); //3.Integer int j = 1; Integer jj = new Integer(j); //4.char类型 char c = '我'; Character cc = new Character(c); // 5.装箱的目的是调用方法 Integer k = new Integer(15); String result = Integer.toHexString(k); System.out.println(result); }
6.3 拆箱操作
获得包装类对象中包装的基本类型变量的过程叫拆箱
- 调用包装类的.xxxValue()方法:
Integer i = 1; i.intValue();
public static void main(String[] args) {
Integer i = new Integer(5);
int y = i.intValue();
Character cc = new Character('我');
char c = cc.charValue();
System.out.println(y);
System.out.println(c);
}
6.4 自动装箱拆箱操作
JDK5之后
,支持自动装箱,自动拆箱。但类型必须匹配。
public static void main(String[] args) {
//1.自动装箱
Integer i = 5;
//2.自动拆箱
int j = i;
}
6.5 基本数据类型转字符串
调用字符串重载的valueOf()
方法: String str = String.valueOf(true);
更直接的方式: String str = 5 + ""
;
public static void main(String[] args) {
int i = 1;
String str = String.valueOf(i);
System.out.println(str);
boolean tag = true;
String ss = String.valueOf(tag);
System.out.println(ss);
int k = 1;
String s = k+"";
System.out.println(s);
}
6.6 字符串转基本数据类型
通过包装类的构造器实现:int i = new Integer("12");
通过包装类的parseXxx(String s)静态方法: Float f = Float.parseFloat("12.1");
public static void main(String[] args) {
//包装类构造器转基本类型
String str = "1";
int i = new Integer(str);
String str2 = "true";
boolean tag = new Boolean(str2);
//包装类静态方法parse**转基本类型
String str3 = "12.2";
double a = Double.parseDouble(str3);
System.out.println(a);
String str4 = "12";
int b = Integer.parseInt(str4);
System.out.println(b);
String str5 = "true";
boolean c = Boolean.parseBoolean(str5);
System.out.println(c);
}
七、BigInteger与BigDecimal(了解)
当整数Long,浮点数double扔不能满足开发要求时,可使用巨大范围BigInteger类和BigDecimal类。
面试的时候知道这两个类的作用即可,开发时边看帮助文档边用。
7.1 BigInteger 使用
- Integer类作为int的包装类,能存储的最大整型值为2 31-1,Long类也是有限的, 最大为2 63-1。如果要表示再大的整数,不管是基本数据类型还是他们的包装类都无能为力,更不用说进行运算了。
- java.math包的BigInteger可以表示不可变的任意精度的整数。BigInteger 提供所有 Java 的基本整数操作符的对应物,并提供 java.lang.Math 的所有相关方法。另外,BigInteger 还提供以下运算:模算术、GCD 计算、质数测试、素数生成、位操作以及一些其他操作。
- 构造器
BigInteger(String val)
:根据字符串构建BigInteger对象
常用方法
public BigInteger abs()
:返回此BigInteger
的绝对值的BigInteger
。- BigInteger add(BigInteger val) :返回其值为 (this + val) 的 BigInteger
- BigInteger subtract(BigInteger val) :返回其值为 (this - val) 的 BigInteger
- BigInteger multiply(BigInteger val) :返回其值为 (this * val) 的 BigInteger
- BigInteger divide(BigInteger val) :返回其值为 (this / val) 的 BigInteger。整数相除只保留整数部分。
- BigInteger remainder(BigInteger val) :返回其值为 (this % val) 的 BigInteger。
BigInteger[] divideAndRemainder(BigInteger val)
:返回包含 (this / val) 后跟(this % val) 的两个 BigInteger 的数组。BigInteger pow(int exponent)
:返回其值为(thisexponent)
的 BigInteger。
7.2 BigDecimal 使用
一般的Float类和Double类可以用来做科学计算或工程计算,但在商业计算中,要求数字精度比较高,故用到java.math.BigDecimal
类。
BigDecimal
类支持不可变的、任意精度的有符号十进制定点数。- 构造器
- public BigDecimal(double val)
- public BigDecimal(String val)
- 常用方法
public BigDecimal add(BigDecimal augend)
public BigDecimal subtract(BigDecimal subtrahend)
public BigDecimal multiply(BigDecimal multiplicand)
public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
八、总结
-
Arrays常用方法
-
自然排序
-
定制排序
-
Object类常用方法
-
深拷贝与浅拷贝
-
系统工具类
-
数学工具类
-
Random随机数类
-
包装类