使用软件:eclipse 2019-2
jdk:11
首先,Objects类是属于Java的工具类,具体包的位置是java.Util.Objects。它是在jdk1.7版本中添加的一些用来检查的工具,其所有的方法都用了static修饰。
检查下标
一共有三个检查下标的方法,个人觉得都挺鸡肋的。自己写if判断都比这个要方便
checkIndex(int index,int length),判断传入的index是否在0到给定的数组长度的范围内(简单来说就是看给的数组下标越界了没有)如果没有超出范围则返回index的值,超出范围或给的index值小于0会显示下标越界异常
//首先定义了一个长度为10的数组
int[] a = new int[10];
for(int i=0;i<10;i++) {
a[i] = i+1;
}
//调用checkIndex方法,并把返回值赋值给x
int x = Objects.checkIndex(0, a.length);
System.out.println(x);
输出结果为:0
int x = Objects.checkIndex(6, a.length);
System.out.println(x);
输出结果为:6
当传入的index值大于等于给定的数组长度或是小于0时就会报错,错误类型为下标越界
//首先定义了一个长度为10的数组
int[] a = new int[10];
for(int i=0;i<10;i++) {
a[i] = i+1;
}
//调用checkIndex方法,并把返回值赋值给x
int x = Objects.checkIndex(-1, a.length);
System.out.println(x);
---------------------------------------------------
int x = Objects.checkIndex(10, a.length);
System.out.println(x);
---------------------------------------------------
int x = Objects.checkIndex(16, a.length);
System.out.println(x);
这三种的结果都为错误:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index -1 out of bounds for length 10
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:372)
at test.ObjectsTest.main(ObjectsTest.java:14)
checkFromIndexSize(int fromIndex,int size,int length),这个方法判断的时传入的fromIndex到fromIndex与size的范围(下面简称这个范围为fs,fromIndex简称为f),是否在0到给定数组长度的范围内。返回值为f,超出length的范围报错(下标越界)
可以简单把这个方法理解为判断从f开始往后数size个位置,看最后的这个位置是否在length的范围内
还是刚刚的数组
//调用checkFromIndexSize方法,并把返回值赋值给x
int x = Objects.checkFromIndexSize(7,3, a.length);
System.out.println(x);
这个就是从第7个位置开始往后数三个位置,就是7,8,9最后的位置在9,数组长度为10,所以没报错返回7
输出的结果为:7
int x = Objects.checkFromIndexSize(7,4, a.length);
System.out.println(x);
当把size的值改为4时,最后的位置下标就到了10,超出了数组长度,所以报错
Exception in thread "main" java.lang.IndexOutOfBoundsException: Range [7, 7 + 4) out of
bounds for length 10
checkFromToIndex(int fromIndex,int toIndex,int length),此方法是比较从fromIndex开始到toIndex(不包括)的范围,是否在给定数组范围内,返回值同样为fromIndex
还是一样的数组
int x = Objects.checkFromToIndex(7, 10, a.length);
System.out.println(x);
这个方法的意思就是从7开始,一直到10之前的范围是不是在数组a的范围内
从7开始7,8,9,数组a的范围为0,1,2...7,8,9,所以返回7,
输出结果就为7
有个特例:就是fromIndex的值可以与toIndex的值相等
int x = Objects.checkFromToIndex(10, 10, a.length);
System.out.println(x);
这个次调用的结果为10,虽然这里没有报错,但是我们在使用返回的这个下标作用到数组a时还是会报错。
需要注意
以上三个检查数组的方法参数都不能小于0,或是大于length。
equals
有两个equals方法,一个是equals,另一个是deepEquals,这两个都可以比较传入的任意类型的数据是否相等,返回值均为boolean类型
Objects中的两个equals方法有一个特别的地方,就是它可以比较值为null的两个对象其他的equals方法在调用者的值为null时就直接报错了
首先equals方法,
首先Objects中的equals源码为:
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
举例:
String s1 = null;
String s2 = null;
boolean result = Objects.equals(s1, s2);
System.out.println(result);
System.out.println(s1.equals(s2));
结果为:true
Exception in thread "main" java.lang.NullPointerException
at test.ObjectsTest.main(ObjectsTest.java:12)
Objects中的equals首先就判断传进来的参数是否相等,其次是判断第一个参数是否为null,
若不为空则调用该参数的equals方法去比较。
再看一个例子:
String[] s1 = {"q","w","e"};
String[] s2 = {"q","w","e"};
String[] s3 = {"a","s","d"};
boolean result = Objects.equals(s1, s2);
System.out.println(result);
result = Objects.equals(s1, s3);
System.out.println(result);
此例的输出为false,false;
因为数组是属于引用类型的变量,在进行比较时比较的是其内存地址,s1和s2虽然值一样,但是
内存地址不一样,所以为false
deepEquals
deepEquals字面意思就是比equlas进行更深度的比较
还是上面的例子,只是将equals换成了deepEquals
String[] s1 = {"q","w","e"};
String[] s2 = {"q","w","e"};
String[] s3 = {"a","s","d"};
boolean result = Objects.deepEquals(s1, s2);
System.out.println(result);
result = Objects.deepEquals(s1, s3);
System.out.println(result);
运行结果为ture,false;
这两种方法的区别就在于deepEquals是比较传入对象的值完全一致才会返回ture
所以在比较类类型,数组等引用类型时用deepEquals比较好,当然也可以选择
重写equalse方法来让比较更符合我们的要求
对null的判断
判断传入的对象是否为空,isNull(Object obj)和noNull(Object obj),字面意思isNull参数为null返回true反之false,noNull参数为null返回false反之true
源码也很简单
直接就是用==去和null比较
public static boolean isNull(Object obj) {
return obj == null;
}
public static boolean nonNull(Object obj) {
return obj != null;
}
有一点需要注意,在比较类类型对象时,只要创建了对象即使没有给该对象赋值,该对象也是不为空的
例: Person p1 = new Person("赤红",17);
Person p2 = new Person();
System.out.println(Objects.isNull(p1));
System.out.println(Objects.isNull(p2));
结果为两个false,因为只创建了对象并没有对对象的属性赋值,所以对象的属性为null
requireNonNull,判断传入的引用对象是否为空,这个方法有三种不同的形态
第一种,判断是否为空,空则报错,反之返回传入的参数
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
第二种,与第一种一样,区别是可以传入一个自定义的提示
public static <T> T requireNonNull(T obj, String message) {
if (obj == null)
throw new NullPointerException(message);
return obj;
}
传入的对象为空后,则把自定义的message跟在异常后面提示
例:String tips = "这是空的";
String s = null;
System.out.println(Objects.requireNonNull(s, tips));
结果为:Exception in thread "main" java.lang.NullPointerException: 这是空的
第三种,与第二种一样,区别是对自定义的提示做了一个判断,如果自定义的信息为null
则报错时就是默认的格式(感觉说了和没说一样)
public static <T> T requireNonNull(T obj, Supplier<String> messageSupplier) {
if (obj == null)
throw new NullPointerException(messageSupplier == null ?
null : messageSupplier.get());
return obj;
}
requireNonNullElse,用法与requireNonNull相似
对传进来的数据进行判断,返回第一个非空值(obj)否则返回第二个非空值(defaultObj)
可以看到里面调用了requireNoNull,若第二个也为空则报错,在错误后面提示defualtObj;
public static <T> T requireNonNullElse(T obj, T defaultObj) {
return (obj != null) ? obj : requireNonNull(defaultObj, "defaultObj");
}
requireNonNullElseGet
具体用法是这样,在调用时传入一个对象,和一个Supplier的实现类
如果传入的对象是null则调用Supplier的get方法,非空则调用其toString方法
尖括号里的类型要与传入对象一样
String s = null;
String tips = "这是空的";
System.out.println(Objects.requireNonNullElseGet(s, new Supplier<String>() {
@Override
public String get() {
// TODO Auto-generated method stub
return tips;
}
}));
toString
toString(Object o)
就是打印传入对象的toString方法,如果传入对象是空,就返回字符串"null"
toString(Object o, String nullDefault)
两个差不多,非空都是掉用o的toString方法,非空则输出nullDefault
还剩一个compare(T a, T b, Comparator<? super T> c),目前没接触到实际应用场景,待补充