1.泛型
泛型就是参数化类型,在定义时把像 Integer,String
这样的具体化类型参数化,只有在使用或者调用时才传入具体的类型。
1.1 在类中使用泛型
//类中使用泛型
class Test<T> {
T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
//使用举例
public class Generic {
public static void main(String[] args) {
Test<String> t = new Test<>();
t.data = "String";
System.out.println(t.data);
}
}
1.2 在接口中使用泛型
public interface TestInterface<T> {
T getData();
}
在实现接口时,可以选择指定泛型类型,也可以选择不指定。
//指定泛型类型
public class Demo3 implements TestInterface<String> {
@Override
public String getData() {
return "String";
}
}
//不指定泛型类型
public class Demo2<T> implements TestInterface<T> {
@Override
public T getData() {
return null;
}
}
1.3 在方法中使用泛型
public <T> T sum(T t1, T t2){
//业务代码
return null;
}
1.4 限制泛型的类型
在使用泛型时,可以对泛型类型进行限制。例如现在需要一个盘子类用来装水果,而不能用来装其他类型的东西,那么代码结构就可以像下面这样写。
public class Demo4 {
public static void main(String[] args) {
Plate<Apple> p1 = new Plate<>();
Plate<Grape> p2 = new Plate<>();
}
}
class Fruit{}
class Apple extends Fruit{}
class Grape extends Fruit{}
class Plate<T extends Fruit>{
T data;
}
不管是要继承类还是实现接口,限制泛型类型都是使用 extends
关键字,格式如下:
<T extends 类或者接口1 & 接口2 >
1.5 泛型通配符 ?
<? extends Parent>
指定了泛型类型的上界限<? super Child>
指定了泛型类型的下界限<?>
指定了没有限制的泛型类型
public class Demo4 {
public static void main(String[] args) {
//等号右边的泛型类型必须是继承或者实现了左边泛型类型
Plate<? extends Fruit> p1 = new Plate<Apple>();
Plate<? extends Fruit> p2 = new Plate<Grape>();
//等号左边的泛型类型必须是继承或者实现右边的泛型类型
Plate<? super Apple> p3 = new Plate<Fruit>();
Plate<? super Apple> p4 = new Plate<Fruit2>();
}
}
class Fruit{}
interface Fruit2{}
class Apple extends Fruit implements Fruit2{}
class Grape extends Fruit{}
class Plate<T>{
T data;
}
注意
泛型只在程序编译阶段有效,程序在经过编译之后会进行去泛型化操作,即泛型信息不会进入到运行时阶段,在经过编译之后就确定类型了。
2.java.util.Objects
该类是在 JDK7
版本之后添加的工具类,它包含了一些 static
的实用方法,用于操作对象在操作前检查某些条件,包括一些 null
值的检查,计算对象的哈希值,返回对象的字符串等等。
2.1 Objects.equals()
该方法用于比较两个参数是否相等,相等返回结果为 true
,否则 false
,在进行字符串比较时,与字符串本身的 equals()
方法不同的是在出现值为 null
的对象程序不会出错。
public static void testEquals() {
String str1 = null;
String str2 = "hahaha";
//使用Objects工具类进行比较
System.out.println(Objects.equals(str1, str2)); //false
//使用字符类本身的方法进行比较
System.out.println(str1.equals(str2)); //空指针异常
}
输出结果:
false
Exception in thread "main"
java.lang.NullPointerException
at day02.TestObjects.testEquals(TestObjects.java:26)
at day02.TestObjects.main(TestObjects.java:14)
Process finished with exit code 1
源码分析:其实就是多进行了一次非空判断,如果第一个参数为空,则直接返回false
/**
* Returns {@code true} if the arguments are equal to each other
* and {@code false} otherwise.
* Consequently, if both arguments are {@code null}, {@code true}
* is returned and if exactly one argument is {@code null}, {@code
* false} is returned. Otherwise, equality is determined by using
* the {@link Object#equals equals} method of the first
* argument.
*
* @param a an object
* @param b an object to be compared with {@code a} for equality
* @return {@code true} if the arguments are equal to each other
* and {@code false} otherwise
* @see Object#equals(Object)
*/
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
2.2 Objects.toString()
public static void testToString() {
int[] a = {1, 2, 3};
System.out.println(Objects.toString(a)); //输出对象的地址
String s1 = "123";
String s2 = null;
System.out.println(Objects.toString(s1, "对象为空")); //s1不为空,调用s1的toString()方法
System.out.println(Objects.toString(s2, "对象为空")); //s2为null,输出默认字符串
System.out.println(Objects.toString(s2)); //s2为空,输出null
}
输出结果:
[I@7c30a502
123
对象为空
null
2.3 其它方法
方法 | 作用 |
---|---|
checkIndex(int index, int length) (JDK9开始) | 检查是否 0<=index<length,如果在就返回index,否则抛出异常 |
checkFromIndexSize(int fromIndex, int size, int length) (JDK9开始) | 判断 fromIndex+size 是否在 0 ~ length范围,,如果在就返回fromIndex,否则抛出异常 |
requireNonNull(T o) | 要求对象不能为空,如果为空,则抛出异常 |
isNull(Object o) | 判断对象是否为空,返回布尔值 |
3. java.lang.Math
方法 | 作用 |
---|---|
abs(参数) | 返回参数的绝对值,支持int,float,long,double |
acos(double a) | 返回参数的反余弦值 |
ceil(double a) | 向上取整 |
floor(double a) | 向下取整 |
cos(double a) | 返回角度的余弦值(正弦正切也类似) |
log(double a) | 返回double值的自然对数(基数为e) |
max(参数1, 参数2) | 返回两个数中的较大的值 |
min(参数1,参数2) | 返回两个数中较小的值 |
pow(double a, double b) | 返回a的b次方 |
random() | 返回 [0, 1.0) 中的一个数 |
round(double a) | 对a的值进行四舍五入操作后返回 |
sqrt(double a) | 开算术平方根 |
4. java.math.BigDecimal
该类用于进行精确的算术运算,解决了浮点数计算的精度问题。
//常用构造方法:
BigDecimal b = new BigDecimal("0.1");
常用方法 | 作用 |
---|---|
add(BigDecimal b2) | 返回当前值与b2的算术和 |
subtract(BigDecimal b2) | 减法运算 |
multiply(BigDecimal b2) | 乘法运算 |
divide(BigDecimal b2) | 除法运算(如果结果为循环数,则会报错) |
abs() | 取绝对值 |
movePointRight(int n) | 小数点右移n位 |
movePointLeft(int n) | 小数点左移n位 |
max(BigDecimal b2) | 当前值与b2进行比较,返回较大值 |
doubleValue() | 获取当前值的double值(其他类型类似) |
precision() | 返回此BigDecimal的精度 |
pow(int n) | 返回该BigDecimal的n次方 |
remainder(BigDecimal b2) | 取余操作,相当于 this % b2 |
5.java.util.Date
Date
类表示特定的时刻,精度为毫秒,这是目前最主要的功能。
由于 该类不是很适合国际化操作,因此很多方法都已经过时了。
目前仍然使用的方法:getTime()
,返回此对象的表示的自1970年1月1日开始到目前的毫秒数。
6 java.text.DateFormat
主要作用就是格式化日期,表示成我们生活中常用的格式。在使用的时候,不能直接使用抽象类 DateFormat
,而需要通过他的子类 进行实例化。下面的例子演示了我们常用的两个方法:format()和parse()
public static void main(String[] args) throws ParseException {
/**
* Y : 表示年
* M : 表示月
* d : 表示日
* H : 表示时
* m : 表示分
* s : 表示秒
*/
SimpleDateFormat format = new SimpleDateFormat("YYYY-MM-dd HH:mm ss");
//把日期对象按照format模板格式化为字符串
String s = format.format(new Date());
System.out.println(s);
//把字符串描述的时间转换为一个Date对象
Date date = format.parse("2020-10-01 10:10 00");
System.out.println(date);
}
输出结果:
2020-10-13 21:50 33
Sun Dec 29 10:10:00 CST 2019