泛型,即“参数化类型”。就是将原来具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
作用:
public class ClassName<T> {
private T data;
public T getData() {
return data;
}
public void setData() {
this.data = data;
}
}
public interface InterfaceName<T> {
T getData();
}
// 实现接口时可以选择指定泛型类型,也可以不指定:
// 指定类型:
public class Interface1 implements InterfaceName<String> {
private string text;
@Override
public String getData() {
return text;
}
}
// 不指定类型:
public class Interface2<T> implements InterfaceName<T> {
private T data;
@Override
public T getData() {
return data;
}
}
private static <T> T methodName(T a, T b) {
}
// e.g.
public static <T> void print(T a) {
system.out.println(a);
}
指定泛型的限定区域,例如: 必须是某某类的子类或 某某接口的实现类:
// 格式:
// e.g.
public static void main(String[] args) {
Plate<Apple> p = new Plate<>();
}
interface Fruit{
}
class Apple implements Fruit{
}
class Plate<T extends Fruit> {
T data;
}
extends Parent>
指定了泛型类型的上界
super Child>
指定了泛型类型的下界
>
指定了没有限制的泛型类型
Plate<? extends Fruit> p = new Plate<Apple>(); // 上界
Plate<? super Apple> p = new Plate<Fruit>(); // 下界
注意:在编译之后程序会采取去泛型化的措施,也就是说Java中的泛型只在编译阶段有效,而不会进入到运行时阶段。在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦除,并在对象进入和离开方法的边界处添加类型检查和类型转换的方法。
// static boolean equals(Object a, Object b)
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
// static boolean isNull(Object obj)
public static boolean isNull(Object obj) {
return obj == null; }
// static boolean nonNull(Object obj)
public static boolean isNull(Object obj) {
return obj != null; }
// static boolean requireNonNull(T obj):检查对象引用是否不是null
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException(); //如果是空,直接抛出异常
return obj;
}
//四舍五入
Math.round(-100.5); // -100
binarySearch, compare, equals, sort, toString, copyOf
int[] arr = {2,3,4,5,1};
System.out.println(arr); //打印的是内存地址(哈希值)
System.out.println(Arrays.toString(arr)); //打印[2,3,4,5,1]
Arrays.sort(arr); //排序
Arrays.binarySearch(arr, 6); //二分查找
arr = Arrays.copyOf(arr, 15); //扩容至长度为15
实现小数的精准运算
// 构造方法
public BigDecimal(String val) {
}
// 常用方法
public BigDecimal add(BigDecimal augend);
public BigDecimal subtract(BigDecimal augend);
public BigDecimal multiply(BigDecimal augend);
public BigDecimal devide(BigDecimal augend);
// e.g.
BigDecimal b1 = new BigDecimal("0.1");
BigDecimal b2 = new BigDecimal("0.2");
BigDecimal b3 = b1.add(b2); // 0.3
double d = b3.doubleValue(); // 转换为double类型
表示特定的时刻,精度为毫秒
构造方法:
Date()
当前时间Date(long date)
方法:
long getTime()
返回自1970年1月1日00:00:00GMT以来的毫秒数void setTime(long time)
设置时间点SimpleDateFormat
String format(Date date)
格式化日期Date parse(String source)
解析日期字符串/**
* y: 年
* M: 月
* d: 日
* H: 时
* m: 分
* s: 秒
*/
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String text = format.format(new Date()); // 将date对象格式化为字符串
Date date = format.parse("2021-12-12 12:12:12"); // 将符合格式的字符串转化为date对象,可用于计算时间差
getInstance()
方法创建对象filed
数组里,通过传入下标(例如Calendar.YEAR
)用get()
方法获取set
get
add
getTime
获取日历时间表示的Date对象getActualMaximum
获取某字段的Calendar cl = Calendar.getInstance(); //创建对象
int year = cl.get(Calendar.YEAR); //2020
int year = cl.get(Calendar.MONTH); //0-11
int day = cl.get(Calendar.DAY_OF_YEAR); //一年的第几天,从0开始
cl.set(Calendar.YEAR, 2021); //设置年为2021
cl.add(Calendar.YEAR, 1); //设置年+1
Date d = cl.getTime(); //获取日历时间表示的Date对象
int m = cl.getActualMaximum(Calendar.DAY_OF_MONTH); //当前月份的最大值
常用方法:
gc()
运行垃圾回收器exit(int status)
终止当前运行的Java虚拟机static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
复制数组字符串是不变的,他们的值在创建后无法更改
String str = "abc";
// 相当于
char data[] = {
'a', 'b', 'c'};
string str = new String(data);
String
类 用final
修饰,不能被继承
两个字符串内容如果完全相同,则它们采用同一块内存地址(即可共享);但如果 是通过new
创建的对象,一定是新开辟的空间
字符串常量池(存在方法区中)
1. 方法区Method Area(加载代码的内存区),又称永久代Permanent Generation,被所有线程共享
2. 堆heap
1) 一个JVM实例只存在一个堆内存,大小是可以调节的;
2) 类加载器读取了类文件后,需要把类、方法、常变量放到堆内存中,保存所有引用类型的真实信息,以方便执行器执行;
3) 堆 在逻辑上分为三部分(Perm):
- 新生代 YoungGen:存刚创建的对象,gc回收很快
- 老年代 OldGen:存常用的对象(在新生代中连续15次没有被回收)
- 永久代 PermGen:类、方法、常量、static修饰的(不会被垃圾回收)
3. JDK1.8演变
字符串常量池还在堆,运行时常量池还在方法区,只不过方法区的实现从永久代变成了元空间Metaspace;
元空间与堆不相连,但与堆共享物理内存,逻辑上可认为在堆中
一种构造方法:
String(byte[] bytes, Charset charset)
使用charset字符集解码字节数组
方法:
int compareTo(String anotherString)
按字典顺序比较两个字符串boolean contains(CharSequence s)
是否包含指定的char值序列int indexOf(int ch)
指定字符第一次出现在字符串中的索引String trim()
删除首尾空格字符串拼接:
String
,应该使用StringBuffer / StringBuilder
String, StringBuilder, StringBuffer 的区别:
1. String 是字符串常量,不可变,修改时会创建了一个新的String对象,然后将指针指向它
2. StringBuffer 和 StringBuilder 是字符串变量,使用时会对对象本身进行操作(会动态扩容),而不是生成新的对象再改变对象引用,最后可以用 toString()方法转成 String
3. StringBuffer 是线程安全的;而 StringBuilder 不是(不能保证同步),速度更快,单线程时使用
4. 在某些特别情况下, String 对象的字符串拼接其实被 Java Compiler 编译成了 StringBuffer 对象的拼接,所以这时 String 对象的速度不比 StringBuffer 对象慢,例如:
String s1 = "This is only a" +