泛型
参数化【类型】,让类型由原来的具体类型变成参数(变量)。称类型形参,然后在使用/调用的时候再传入具体的类型(类型实参)。
泛型类
public class ClassName<T>{
//类在使用时需要替换成具体类型
private T data;//T type
public T getData(){
return data;
}
}
泛型接口
跟泛型类也比较类似,实现接口时可以指定类型也可以不指定。
public class Interface1 implements InterfaceName<String>{
指定public class Interface1<T> implements InterfaceName<T>{
不指定,但前面要加上<T>
泛型方法
public static<A> void print(A a){
System.out.println(a);//a只在方法中可以泛型使用
}
//调用
print("abcde");
print(123123);//会自动装箱为integer
jdk1.7之后右边不需要写全<>内的内容了
JVM
- 泛型只在编译阶段有效,编译之后程序会采取去泛型化措施
- 泛型信息不会进入到运行时。正确检验泛型结果后,会将泛型相关信息摘出。对象进入和离开方法的边界处,添加一道关卡:类型检查和类型转换。
泛型的作用
- 提高代码复用率
- 类型在使用时指定,不需要强制类型转换
用泛型来限制类型
<T extends Fruit>
限定必须是Fruit的子类(或xx接口的实现类)
?
如果类型左边父右边子,是不可以的。
- 上界限定通配符
Plate<? extends Fruit> p = new Plate<Apple>();
必须是其子 - 下界限定
Plate<? super Apple> p = new Plate<Fruit>();
必须是其父 <?>
类似Object,指定了没有限制的泛型类型。可以传递东西替换这个?
Objects工具类
equals()
如果string1和string2是传参,在判断相等时如果有null,则会出现空指针异常。用空的东西去调方法是不行的。
可以在类里覆写equals,添加判空操作。
@Ovveride
public boolean equals(Object o){
if(this == o) return true;
//如果为空或者是获取类不一致(不一致就没法强制转换)
if(o == null || getClass()!=o.getClass()) return false;
//强制转换
Person p = (Person) o;
return Objects.equals(name,p.name)l//根据姓名来判断相等
}
Math工具类
Math.floor()
如果是负数的话,会往正的取整:-100.5->-100- 计算最接近(<=)当前数值的整数:
Math.floor(3.5)
=3.0 如果是负的就是-4.0 - 计算≥参数的最小整数:
Math.ceil(-3.5)
=-3.0如果是正的就是4.0
BigDecimal
如果计算0.1+0.2
是不精确的,会输出0.3000000000004(类似)。这是float 和 double的运算误差。
BigDecimal(val:15)
- substract 减法
- doubleValue获取double类型的结果
- multiply乘法
- divide除法
Arrays数组
asList()
返回列表toString()
返回[1,2,3]Arrays.copyOf(arr, newLength:15)
新长度,用于扩容
Date日期
精度为毫秒
getTime()
从1970/01/01 00:00:00GMT到现在的毫秒数- 创建当前时间的Date:
Date date = new Date();
- 打印方法
o.toString()
- 对日期+1-1的操作在日历类里
DateFormat格式化日期类
SimpleDateFormt format = new SimpleDateFormat(pattern:"yyyy-MM-dd HH:mm ss");
String text = format.format(new Date());//传入日期对象
format.parse("2021-12-12 12:12 12");//将字符串转换为date对象
//计算相差的天数
new Date().getTime()-date.getTime()/1000/60/60/24;
Calendar日历类
这是一个抽象类,无法直接创建。可以通过getInstance()
来创建对象。
public abstract Calendar getInstance(){
//返回已经创建好的子类对象
}
//内含时区,提供国际化
Calendar cl = Calendar.getInstance();
//获取年月日时分秒,存储在一个数组里面
protected int fields[];
//源码里其他的常量代表相对应的内容的下标
cl.get(Calendar.YEAR);//获取年的信息
cl.get(Calendar.DAY_OF_YEAR);//获取年月日
cl.set(Calendar.YEAR,2021);//设置
cl.add(Calendar.MONTH,0);//加
//获取字段最大值
cl.getActualMaximum(Calendar.DAY_OF_MONTH);
//注意0表示1月
在做打印日历练习的时候发现了两个坑:
- month接收输入后需要-1,因为是把0看作1月份
- DAY_OF_WEEK也需要-1,这样才能获得准确的星期几(每周从周一开始)
Date和Calendar的互转:getTime和setTime
System类
- gc()调用垃圾回收器
- exit(int status)终止
- currentTimeMills()毫秒为单位返回当前时间
- arraycopy(src,srcpos,dest,destpos,length)原数组,原数组开始位置,新数组,新数组开始位置,传多少个
String类 重点!!!
-
String类可以不用创建直接赋值,任何一个字符串都是String类的实例。
-
String是final的,不能被继承。
-
字符串的值在创建后无法更改,是通过字符数组存的。
char data[] = {a,b,c};
String str = new String(data);
- 两个字符串内容一样,永远相等,采用同一块内存地址。(==比较为true)
如何采用同一块内存地址?
字符串常量池。每个版本都不太一样,存在方法区(永久代),方法区是被所有线程共享的。存储的是:静态变量+常量+类信息(构造方法、接口定义)+运行时常量池
堆内存:新生代,老年代,永久代。一个JVM实例只存在一个堆内存,大小可调节,类加载器读取类文件之后,把类、方法、常变量放到堆内存,保存所有引用类型的真实信息,以便执行器执行。
- 如果new了,就是新的对象
- 传入字符数组和字符编码
String(byte[] bytes, Charset charsetName)
CharSequence
是string的父接口
StringBuffer StringBuilder可变字符序列
构造字符串缓冲区。Buffer线程安全。
-
构造方法里初始容量是16字符。存满动态扩容。
-
每次拼接产生的内存垃圾会立即被回收,string拼接出来的在字符串常量池,永久代里,不会被回收。
-
sb.append();
-
sb.toString();