JavaSE——常用类库(上)(泛型、Objects、Math、ArraysBigDecimal类)

第1节 常用类库(上)

面向对象更多是思想上的东西,常用类库更多是工具上的东西,熟能生巧,多整理笔记。

一、泛型

1.1 概述

泛型,即“参数化类型”。就是将类型由原来具体类型进行参数化 ,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参 ),然后在使用/调用时传入具体的类型(类型实参)

1.2 泛型的使用

   泛型一般在类、接口和方法中使用,其中主要是类中用的更多。
1.2.1 泛型在类中的使用
   先来看定义的时候的格式:
package com.kaikeba.coreclasslibrary;

public class Person<A> {
    private String name;
    private int age;
    //这里是形参,实际使用该类时需要给定实参,在该类中可以用A来代替一种不确定的类型
    private A data;

    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;
    }

    public A getData() {
        return data;
    }

    public void setData(A data) {
        this.data = data;
    }

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

   再看使用时的格式:
package com.kaikeba.coreclasslibrary;

public class genericParadigm {
    public static void main(String[] args) {
        //实际使用时指定具体的类型给泛型,那么该类中所有的A全部替换为Integer
        Person<Integer> p = new Person<>();
    }
}

看下面传入不同的类型,setData方法的参数列表中data的类型也随之变化:

在这里插入图片描述
在这里插入图片描述

1.2.2 泛型在接口中的使用
   定义时格式如下所示,和类中基本一致:
public interface 接口名<T> {
    T getData();
}

接口都是要被类实现才有意义,实现接口时,可以选择指定泛型类型,也可以选择不指定,如下所示:

1、指定类型

//指定类型:这样的类使用时无需再给泛型具体的类型,直接使用即可
public class 类名 implements 接口名<String> {
    private String text;
    @Override
    public String getData() {
        return text;
    }
}

具体的使用案例:

package com.kaikeba.coreclasslibrary;

public class genericParadigm2 {
    public static void main(String[] args) {
        Apple a = new Apple();
        a.text = "123";
        System.out.println(a.getData());
    }

}

interface Fruit<T>{
    T getData();
}

//实现接口时指定类型
class Apple implements Fruit<String>{
    String text;
    @Override
    public String getData() {
        return text;
    }
}

结果为:123

2、不指定类型:

//不指定类型:使用类时需要给定具体的类型
public class 类名<T> implements 接口名<T> {
    private T text;
    @Override
    public T getData() {
        return text;
    }
}

具体的使用案例:

package com.kaikeba.coreclasslibrary;

public class genericParadigm2 {
    public static void main(String[] args) {
        Apple<String> a = new Apple<>();
        a.text = "123";
        System.out.println(a.getData());
    }

}

interface Fruit<T>{
    T getData();
}

//实现接口时不指定类型
class Apple<T> implements Fruit<T>{
    T text;
    @Override
    public T getData() {
        return text;
    }
}

结果:123
1.2.3 泛型在方法中的使用
   泛型方法的格式如下,注意位置与类和接口不一样:
private static <T> T 方法名(T a, T b) {}

   想用T的地方可以用T,不想用的地方就用自己想用的类型即可,上述的格式案例中全用了T,下面看个例子:
package com.kaikeba.coreclasslibrary;

public class genericParadigm {
    public static void main(String[] args) {
        //根据传入的实际参数类型,自动获取泛型的类型
        print(123);
    }

    public static <A> void print(A a) {
        System.out.println(a);
    }
}

结果:123

1.3 泛型限制类型

在使用泛型的时候,可以指定泛型的限定区域,例如:必须是某某类的子类 或 某某接口的实现类,格式:

<T extends 类或接口1 & 接口2>

注意:这里不论是类还是接口,都是使用extends关键字。

package com.kaikeba.coreclasslibrary;

public class genericParadigm2 {
    public static void main(String[] args) {
        // 如果传入的不是水果的实现类,会报错
        // Plate<String> p = new Plate<>();
        // p.data = "String";
        
        // 如果传入的符合要求,则正确
        Plate<Apple> p = new Plate<>();
    }
}

//定义一个水果接口
interface Fruit<T>{
    T getData();
}

//实现水果接口的苹果类
class Apple<T> implements Fruit<T>{
    T text;
    @Override
    public T getData() {
        return text;
    }
}

//泛型限制只能传入水果接口的实现类
class Plate<T extends Fruit>{
    T data;
}

1.4 泛型中的通配符——?

类型通配符是使用 ? 代替方法具体的类型实参。

  1. <? extends Parent>指定了泛型类型的上界,必须是Parent或其子类;

  2. <? super Child>指定了泛型类型的下界,必须是Child或其父类;

  3. <?>指定了没有限制的泛型类型。

package com.kaikeba.coreclasslibrary;

public class genericParadigm3 {
    public static void main(String[] args) {
        //不能将一个装着苹果的盘子看成一个装着水果的盘子
        //多态建立的基础:左右对象是父子关系,此时是同级别类,只是泛型是父子类关系而已
        //多态不能用在容器的内容上
        Plate3<? extends Fruit3> p1 = new Plate3<Apple3>();
        Plate3<? super Apple3> p2 = new Plate3<Fruit3>();
    }

}

interface Fruit3{}

class Apple3 implements Fruit3{}

class Plate3<T>{//也可以多个泛型
    T data;
}

1.5 泛型的作用以及注意事项

作用:

  1. 提高代码的复用率

  2. 泛型中的类型在使用时指定,不需要强制类型转换(类型安全,编译器会检查类型)

注意事项:

在编译之后程序会采取去泛型化的措施,也就是Java中的泛型,只在编译阶段有效。在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦除,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法,也就是说,泛型信息不会进入到运行时阶段。

二、java.util.Objects类

Objects类以及下面介绍的每一种类库,最好的学习方法就是看源码以及注释,其次可以配合中文手册,下面就是对其的整理。

简介: 此类由静态实用程序方法组成,用于对对象进行操作,或在操作前检查某些条件。这些实用程序包括空安全 (null-safe) 或空容忍 (null-tolerant) 方法,用于计算对象的哈希代码、返回对象的字符串、比较两个对象以及检查索引或子范围值是否超出范围等等。

2.1 checkFromIndexSize

在这里插入图片描述

2.2 checkFromToIndex

在这里插入图片描述

2.3 checkIndex

在这里插入图片描述

上面这三个判断索引范围,自己写也很简单。。。

2.4 compare

在这里插入图片描述

注意不是返回o,是返回0,还是看源码注释比较靠谱。。。

2.5 deepEquals

在这里插入图片描述

这个暂时用不到,用到了再来补充笔记。

2.6 euqals

在这里插入图片描述

这个目前比较重要,翻译的实在不太行,以后还是多看源码吧。

它的作用在于,如果一个对象为null,那么它调用默认Objectequals方法,会报空指针异常:

package com.kaikeba.coreclasslibrary.objects;

import java.util.Objects;

/**
 * Objects
 */
public class Demo {
    public static void main(String[] args) {
        String s1 = null;
        String s2 = "456";
        System.out.println(s1.equals(s2));
    }
}

结果为:
Exception in thread "main" java.lang.NullPointerException
  at com.kaikeba.coreclasslibrary.objects.Demo.main(Demo.java:12)

因为null对象没有equals方法。

但是如果使用Objects.equals则不会:

package com.kaikeba.coreclasslibrary.objects;

import java.util.Objects;

/**
 * Objects
 */
public class Demo {
    public static void main(String[] args) {
        Person p1 = null;
        Person p2 = new Person();
        System.out.println(Objects.equals(p1, p2));
    }
}

结果为:
false

看一下equals的源码就知道了:

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

首先判断a和b是否指向同一个对象,是则返回true,不是则看右边的括号,如果a为null,直接返回false,不空才调用Object.equals方法进行比较,这样可以避免因为空对象导致的异常抛出。

2.7 hash

在这里插入图片描述
哈希值目前还没介绍,后续补充。。。

2.8 hashCode

返回一个非空对象的哈希码,空对象返回0。

源码如下:

public static int hashCode(Object o) {
    return o != null ? o.hashCode() : 0;
}

2.9 isNull,nonNull

在这里插入图片描述

public static boolean isNull(Object obj) {
    return obj == null;
}

在这里插入图片描述

public static boolean nonNull(Object obj) {
    return obj != null;
}

2.10 requireNonNull、requireNonNullElse、requireNonNullElseGet

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.11 toString

在这里插入图片描述
在这里插入图片描述

三、java.lang.Math

Math类包含用于执行基本数值运算的方法,如初等指数、对数、平方根和三角函数。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

看几个较常用的:

package com.kaikeba.coreclasslibrary.math;

/**
 * Math
 */
public class Demo {
    public static void main(String[] args) {
        System.out.println(Math.abs(-100));
        System.out.println(Math.min(100, 200));

        //返回最接近的整数
        System.out.println(Math.round(100.55));
        System.out.println(Math.round(-100.55));
        //返回小于等于参数的最大整数
        System.out.println(Math.floor(3.5));
        System.out.println(Math.floor(-3.5));
        //返回大于等于参数的最大整数
        System.out.println(Math.ceil(3.5));
        System.out.println(Math.ceil(-3.5));
    }
}

结果如下:
100
100
101
-101
3.0
-4.0
4.0
-3.0

四、java.util.Arrays

该类包含用于操作数组的各种方法(例如排序和搜索)。 此类还包含一个静态工厂,允许将数组视为列表。
如果指定的数组引用为null,则此类中的方法都抛出NullPointerException ,除非另有说明。

4.1 binarySearch

在这里插入图片描述
除此之外,还有各种其他类型的二分查找,都是在一个数组中查找指定的值,返回找到的索引。

4.2 compare

在这里插入图片描述

比较两个数组

4.3 copyOf

在这里插入图片描述
将一个数组里的内容复制到一个新的长度的数组中。

4.4 copyOfRange

在这里插入图片描述

将指定数组的指定范围内容复制到新数组中。

4.5 equals

在这里插入图片描述

比较两个数组是否相同。

4.6 fill

在这里插入图片描述

将指定的元素分配给数组中每一个元素。

4.7 mismatch

在这里插入图片描述

查找并返回两个数组中第一个不匹配的索引。

4.8 sort

在这里插入图片描述

按升序对数组进行排序。

4.9 toString

在这里插入图片描述

返回数组内容的字符串表示形式。

上述的方法并没有全部总结,还有一些不常用的方法没有整理。

下面看一个例子:

package com.kaikeba.coreclasslibrary.arrays;

import java.util.Arrays;

public class Demo {
    public static void main(String[] args) {
        int[] arr = {8,1,2,3,4,5,6,7};
        //直接输出arr是地址信息
        System.out.println(arr);
        //下面可以输出数组的内容,但是很麻烦
        for(int i=0; i<arr.length; i++) {
            if(i == arr.length - 1) {
                System.out.print(arr[i]);
            }else {
                System.out.print(arr[i] + ", ");
            }
        }
        System.out.println();
        
        //Arrays中的方法都是静态的,直接用类名调用,无需新建对象
        //toString方法可以直接输出数组内每个元素
        System.out.println(Arrays.toString(arr));
        //sort方法可以升序排序
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
        
        //二分查找指定元素的索引,前提:数组必须有序
        System.out.println(Arrays.binarySearch(arr, 6));
        
        //动态扩容
        arr = Arrays.copyOf(arr, 15);
        System.out.println(Arrays.toString(arr));

    }
}

结果如下所示:
[I@7c30a502
8, 1, 2, 3, 4, 5, 6, 7
[8, 1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7, 8]
5
[1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0]

五、java.math.BigDecimal

5.1 概念

通过在控制台运行0.1+0.2,会发现float和double的运算误差:

package com.kaikeba.coreclasslibrary.bigdecimal;

import java.math.BigDecimal;

public class Demo {
    public static void main(String[] args) {
        System.out.println(0.1+0.2);
    }
}

结果:
0.30000000000000004

虽然误差很小,但是在类似于银行这种地方,这些小误差累计起来还是很严重的,所以需要一种严格准确的计算类。为了实现精确运算就需要借助java.math.BigDecimal类对要计算的对象加以描述。

5.2 常用构造方法

   有很多构造方法,最常用字符串来指定精确值:
public BigDecimal(String val) {
}

如:

BigDecimal b1 = new BigDecimal("0.1");
BigDecimal b2 = new BigDecimal("0.2");

5.3 常用方法

有很多关于数学运算的方法,最常用的还是加减乘除四个。下述所有的运算方法,不会影响参与运算的数据本身,运算的结果会被封装为一个新的BigDecimal对象,这个对象会通过return返回出去。

  1. public BigDecimal add(BigDecimal augend):加法运算

  2. public BigDecimal subtract(BigDecimal augend):减法运算

  3. public BigDecimal multiply(BigDecimal augend):乘法运算

  4. public BigDecimal divide(BigDecimal augend):除法运算

看一个例子:

package com.kaikeba.coreclasslibrary.bigdecimal;

import java.math.BigDecimal;

public class Demo {
    public static void main(String[] args) {
        BigDecimal b1 = new BigDecimal("0.1");
        BigDecimal b2 = new BigDecimal("0.2");
        BigDecimal b3 = b1.add(b2);
        System.out.println(b1);
        System.out.println(b2);
        System.out.println(b3);
    }
}

结果:
0.1
0.2
0.3

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值