Java常用类库总结(持续更新)

Java常用类库总结(持续更新)

java.util.Objects类库

1.public boolean equals(Object obj)

前面学习过Object类,它是所有类的超类,它里面也有一个equals方法,不过该方法有一个局限性。

如:一个对象为空,空指针调用容易发生异常

public class Demo1 {
    public static void main(String[] args) {
        String s1 = null;
        String s2 = "456";
        //一个对象为空,空指针调用容易发生异常
        System.out.println(s1.equals(s2));
    }
}

​ 此时会抛出空指针异常
在这里插入图片描述

​ 再来看看Objects类库提供的equals方法

public class Demo2 {
    public static void main(String[] args) {
        //此时s1也为null
        String s1 = null;
        String s2 = "456";
        //调用Objects类库提供的equals方法
        System.out.println(Objects.equals(s1,s2));
    }
}

此时输出结果为false

对比一下两者源码

1.1 Object类源码
public boolean equals(Object obj) {
        return (this == obj);
    }
1.2 Objects类源码
public static boolean equals(Object a, Object b) {
        return (a == b) || (a != null && a.equals(b));
    }

从上面源码中我们发现总结出了一些点:

  1. Object类的equals只能处理引用数据类型变量(因为传入参数为Object类型)
  2. 查看Object类中源码,发现其equals方法也是 == 去比较首地址值。

咋们来看看用Object类的equals不会抛异常的情况

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

此时结果为true

插入一个知识点:
那好奇的小伙伴可能有疑问?为啥Object类的equals不是比较的是地址吗,咋们知道字符串也是一个String对象,既然是对象,那么两者的地址值肯定不一样,那为啥结果还是true呢?哈哈哈,其实不是的,他俩地址值其实也是一样的,在堆里面有一个字符串常量池,双引号定义的字符串都在这个常量池里,java定义了如果用双引号定义的字符串内容一样,则指向同一块内存地址。但如果是new的话就会不一样了,我们知道new是在堆中开辟了一块新的内存空间,所以此时便不再是同一块地址了。所以此时需要String重写object类equals来进行内容的比较了。

1.3 String类重写的Object类的equals方法的源码
public boolean equals(Object anObject) {
       if (this == anObject) {
           return true;
       }
       if (anObject instanceof String) {
           String anotherString = (String)anObject;
           int n = value.length;
           if (n == anotherString.value.length) {
               char v1[] = value;
               char v2[] = anotherString.value;
               int i = 0;
               while (n-- != 0) {
                   if (v1[i] != v2[i])
                       return false;
                   i++;
               }
               return true;
           }
       }
       return false;
}

从上面可以看出,重写的equals方法首先判断首地址是否相等,是,返回true,否,继续比较额每一个字符,直到全部相等才返回true ,否则,返回false。

1.4Objects.equals中的坑

从上面来看JDK1.7提供的Objects.equals方法,非常方便地实现了对象的比较,有效地避免了繁琐的空指针检查

但有时有个坑,如下:

Long a = 10L;
int b = 10;
System.out.println(Objects.equals(b,a));//false
System.out.println(Objects.equals(a,b));//false
System.out.println(a==b);//true

是不是意想不到!不是比较内容吗,明明同样内容是10,不应该是ture吗?

咋们再来看一遍Objects类源码:

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

可以发现Objects.equals在进行比较时会自动对基本类型做封装,也就是说它把int变成了Integer,使用了Long的equals方法进行了比较。而long源码如下:

  public boolean equals(Object obj) {
        if (obj instanceof Long) {
            return value == ((Long)obj).longValue();
        }
        return false;
    }

所以结果就是一个Integer一个是Long,类型不一样,直接返回false。各位在使用时应该避免这个坑。

2.public static T requireNonNull(T obj)

判断对象是否为空,若为空则抛出异常 。

源码:

public static <T> T requireNonNull(T obj) {
        if (obj == null)
            throw new NullPointerException();
        return obj;
    }

从这个方法的名称可以看出, 这个方法使用的场景是, 我们使用一个对象的方法时, 正常的运行状态应该能保证这个对象的引用非空, 如果这个对象为空了, 那一定是其他某个地方出错了, 所以我们应该抛出一个异常, 我们不应该在这里处理这个非空异常.

requireNonNull 方法还有一个重载方法, 可以提供一个报错信息, 以供我们 debug 的时候显示. 我们使用这个引用的时候, 应当保证非空, 如果不然, 会抛出异常告诉我们其他地方出错了, 这里出现了空指针异常. 这个方法重载的实现如下:

public static <T> T requireNonNull(T obj, String message) {
    if (obj == null)
        throw new NullPointerException(message);
    return obj;
}

java.lang.Math

Math:用于数学运算的类,一个工具类,里面的方法都是静态方法,使用时不需要创建实例对象。下面是它的一些使用

1.算术运算

  • Math.sqrt() : 计算平方根
  • Math.cbrt() : 计算立方根
  • Math.pow(a, b) : 计算a的b次方
  • Math.max( , ) : 计算最大值
  • Math.min( , ) : 计算最小值
  • Math.abs() : 取绝对值
public class Demo1 {
    public static void main(String[] args) {
        System.out.println(Math.sqrt(16));//4.0
        System.out.println(Math.cbrt(8));//2.0
        System.out.println(Math.pow(4,2));//16.0
        System.out.println(Math.max(32,45));//45
        System.out.println(Math.min(2.3,4.5));//2.3
        System.out.println(Math.abs(10.4));//10.4
        System.out.println(Math.abs(-10.4));//10.4
    }
}

2.进位计算

  • Math.ceil(): 逢余进一
  • Math.floor() :逢余舍一
  • Math.rint(): 四舍五入,返回double值。注意.5的时候会取偶数
  • Math.round(): 四舍五入,float时返回int值,double时返回long值

其他的都比较好理解,不过注意的是Math.rint()方法.5的时候会取偶数,例如:

public class Demo1 {
    public static void main(String[] args) {
        System.out.println(Math.rint(11.5)); // 12.0
        System.out.println(Math.rint(10.5)); //1.0  
    }
}

还有一点需要注意的是,这里所有的进位方法的入参都要保证是float或者是double 类型,不然进位毫无意义。

3.随机数

  • Math.random(): 取得一个[0, 1)范围内的随机数
 System.out.println(Math.random()); // [0, 1)的double类型的数             
 System.out.println(Math.random() * 100);//[0, 100)的double类型的数       
 System.out.println(Math.random() * 100+ 10);// [10, 110)的double类型的数 

java.math.BigDecimal

为什么有这个类库呢,是因为在一些特定场景中,如:在金额的计算中, 会出现精度丢失的情况。

数字计算时,计算机会将数字转换为最近似的二进制,在进行计算,这就会导致计算结果精度不正确。这个问题用java提供的BigDecimal可以很好的解决。

1.BigDecimal 常用方法 加减乘除运算

BigDecimal a = new BigDecimal(6);
BigDecimal b = new BigDecimal(5);
a.add(b);  //a+b  加
a.subtract(b); // a-b 减
a.multiply(b); // a*b 乘
a.divide(b);// a/b 除
a.doubleValue();//转换成双精度 double类型
a.floatValue(); //转换成单精度 float类型
a.longValue(); //转换成长整形 long 类型
a.intValue();  //转换成整形 int 类型
a.pow(3);//a的3次方
a.abs();//a的绝对值
a.negate();//a的负数

2.BigDecimal数值比较

BigDecimal a = new BigDecimal(6);
int i = a.compareTo(BigDecimal.ZERO); //和0做比较
i==-1;//表示a小于0
i==0;//表示a=0
i==1;//表示a大于0
boolean b1 = a.subtract(b).compareTo(BigDecimal.ZERO) > 0;//判断a-b是否大于0

java.util.Arrays

Arrays是针对数组的工具类,可以进行 排序,查找,复制填充等功能

关键字简介
copyOfRange/copyof数组复制
toString()转换为字符串
sort/parallelSort排序
binarySearch搜索
equals判断是否相同
fill填充

1.数组复制

array = new int[]{3, 10, 4, 0, 2};
int[] arrayCopy = Arrays.copyOf(array, 3);
out.println(Arrays.toString(arrayCopy)); //[3, 10, 4]

arrayCopy = Arrays.copyOf(array, 7);
out.println(Arrays.toString(arrayCopy)); //[3, 10, 4, 0, 2, 0, 0], 多出的长度补0

arrayCopy = Arrays.copyOfRange(array, 1, 4);
out.println(Arrays.toString(arrayCopy)); //[10, 4, 0]

需要注意的是 copyOfRange 的第3个参数,表示源数组的结束位置,是取不到的。

2.转换为字符串

int[] array = new int[]{9, 45, 3};
System.out.println(Arrays.toString(array)); //[9, 45, 3]

3.排序

array = new int[]{30, 10, 4, 20, 2};
Arrays.sort(array);
System.out.println(Arrays.toString(array)); //[2, 4, 10, 20, 30]

array = new int[]{3, 10, 4, 0, 2};
Arrays.parallelSort(array); //和sort相比是这个是并行的
System.out.println(Arrays.toString(array)); //[0, 2, 3, 4, 10]

array = new int[]{3, 10, 4, 0, 2};
Arrays.sort(array, 0, 4); //部分排序
System.out.println(Arrays.toString(array)); //[0, 3, 4, 10, 2]

4.搜索

array= new int[] { 18, 62, 68, 82, 65, 9 };
   Arrays.sort(array);
System.out.println(Arrays.toString(array));
//使用binarySearch之前,必须先使用sort进行排序
System.out.println("数字 62出现的位置:"+Arrays.binarySearch(array, 62));

5.比较

array = new int[]{1, 2, 3};
int[] array2 = new int[]{1, 2, 3};
out.println(Arrays.equals(array, array2)); //true

6.填充

 array= new int[10];  
Arrays.fill(array, 5);
System.out.println(Arrays.toString(array));//[5,5,5,5,5,5,5,5,5,5]

日期类

1. Calendar类(日历)

Calendar:它为特定瞬间与一组如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。

通常获取当前时间的毫秒数, 都会使用new Date.getTime或者是System.currentTimeMillis(), 用日历类Calendar要怎么实现呢?

首先需要实例化对象, 通过JDK我们发现Calendar类的实例化方法是protected修饰的, 所以无法直接实例化, 我们需要调用下面方法获取Calendar对象。如:

Calendar calendar = Calendar.getInstance();
// 获取当前时间的毫秒数
long time = calendar.getTimeInMillis();
Calendar类的一些方法
/ 其日历字段已由当前日期和时间初始化:
Calendar rightNow = Calendar.getInstance(); // 子类对象
rightNow.getTimeInMillis()
// 获取年
int year = rightNow.get(Calendar.YEAR);
// 获取月
int month = rightNow.get(Calendar.MONTH);
// 获取日
int date = rightNow.get(Calendar.DATE);
//获取几点, 其中Calendar.HOUR代表12小时制, Calendar.HOUR_OF_DAY代表24小时制
int hour = rightNow.get(Calendar.HOUR);
//获取上午下午
int moa=rightNow.get(Calendar.AM_PM);
System.out.println(moa == 1 ? "下午" : "上午");

//月份是从0开始的,所以要+1
System.out.println(year + "年" + (month + 1) + "月" + date + "日"+hour+"时");
rightNow.add(Calendar.YEAR,5);
rightNow.add(Calendar.DATE, -10);
int year1 = rightNow.get(Calendar.YEAR);
int date1 = rightNow.get(Calendar.DATE);
System.out.println(year1 + "年" + (month + 1) + "月" + date1 + "日"+hour+"时");

2. Date,DateFomat

//Date 获得当前的系统时间
		Date now = new Date();
		System.out.println(now); //输出结果:Sat Jun 04 17:19:17 CST 2016
		
		//SimpleDateFormat 进行字符串和日期之间的转换
		// 1)将日期转换为字符串
		SimpleDateFormat date = new SimpleDateFormat();
		System.out.println(date.format(now));  //输出结果:16-6-4 下午5:25
		
		// 2) 用字符串模板将日期转换为字符串
		SimpleDateFormat dates = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
		System.out.println(dates.format(now)); //输出结果:2016年06月04日 17:29:22
		
		SimpleDateFormat dates2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println(dates2.format(now)); //输出结果:2016-06-04 17:31:03
		System.out.println(dates2.toPattern()); //输出结果:yyyy-MM-dd HH:mm:ss
		
		//将指定的字符串解析为时间
		String s = "2016-06-04 17:31:03";
		SimpleDateFormat time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			Date date2 = time.parse(s);
			System.out.println(date2);  //输出结果:Sat Jun 04 17:31:03 CST 2016
		} catch (ParseException e) {
			e.printStackTrace();
		}

java.lang.System

System类主要用于获取系统的属性数据,没有构造方法。

1.System类常用的方法:

(1) arraycopy(Object src, int srcPos, Object dest, int destPos, int length);

①参数详解:

src:原数组。

srcPos:原数组中的起始位置,也就是从原数组的哪一位开始拷贝。

dest:目标数组。

destPos:目标数据中的起始位置,也就是从目标数组的哪一个位置开始存储要拷贝的元素。

length:要复制的数组元素的数量。

如:

int[] srcArr = {10,12,14,16,19};
//把srcArr的数组元素拷贝 到destArr数组中。
int[] destArr = new int[4];
System.arraycopy(srcArr, 2, destArr, 1, 2);
System.out.println("目标数组的元素:"+Arrays.toString(destArr));//[0,14,16,0]

(2) currentTimeMillis();

该方法用于获取当前系统时间,返回的是毫秒值。返回当前时间与协调世界时 1970 年 1 月 1 日午夜之间的时间差(以毫秒为单位测量)。

(3) gc();

该方法用来建议jvm赶快启动垃圾回收器回收垃圾。只是建议启动,但是Jvm是否启动又是另外一回事。

(4) getenv(String name);

该方法用来根据环境变量的名字获取环境变量。

(5) getProperties();

该方法用于获取系统的所有属性。属性分为键和值两部分,它的返回值是Properties。

(6) getProperty(key);

该方法用于根据系统的属性名获取对应的属性值。

(7) exit(int status);

​ 该方法用于退出jvm,如果参数是0表示正常退出jvm,非0表示异常退出jvm。

​ 退出jvm后,后面的代码就不会执行。无论传0还是传1,Jvm都会退出。

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

​ 我们程序员的编程习惯是:如果在try块中退出Jvm,try块里面是没有异常的代码,所以try块中要传0,如果是在catch块里面退出Jvm,我们习惯于用非0退出。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值