(写在开篇:此篇Blog只代表个人笔记,如有错误或者不足之处尽情指正!)
一、泛型
概述:泛型即参数化类型。类似于方法中的变量参数,此时类型也定义成参数形式(类型形参),然后调用时传入具体的类型(类型实参)
使用:
1.泛型类(使用较多)
//定义
public class ClassName<T>{
private T date;
public T getData(){
......
}
}
//使用
Person<Integer> p = new Person <Integer(Integer可省略)> ();
2.泛型在接口中的使用
public interface InterfaceName<T>{
T getData();
}
在实现接口时,可以选择指定泛型类型,也可以选择不指定。
3.泛型方法
private static <T> T 方法名(T a,T b){
//方法体
}
4.泛型限定和通配符
1)限制:在使用时,可以指定泛型的限定区域
格式:
//必须是某类的子类,某类的实现类
<T extends 类或接口1 & 接口2>
2)通配符:?
注意多态不能运用在容器的内容上。
Plate<? extends Fruit> p = new Plate<Apple>();//上界限定
Plate<? super Apple> p = new Plate<Fruit>();//下界限定
<?> //指定了没有限制的泛型类型
5.作用
提高代码复用率,在使用时指定,不需要强转,安全。
6.注意
编译之后会执行去泛型化的措施。
二、java.util.Objects
static int checkFromIndexSize (int fromIndex, int size, int length);
//检查是否在子范围从 fromIndex (包括在内)到 fromIndex + size (不包括在内)是范围界限内 0 (包括)到 length (不包括)。
static <T> int compare (T a, T b, Comparator<? super T> c);
//如果参数相同则返回0,否则返回 c.compare(a, b) 。 如果其中一个参数为null , 会抛出NullPointerException。
static boolean equals (Object a, Object b);
//如果参数相等返回 true,其他返回false。 如果这两个参数是null , 返回true,如果只有一个参数为null , 返回false。
//如果不使用Objects的equals,如:String str1 = null;String str2 = "abc";str1.equals(str2);程序会中断,报错空指针异常。
static <T> T requireNonNull (T obj);
//检查指定的对象引用是不是 null 。 当一个方法需要外部传进来的对象,需要判断是不是空的时候可以用来判断。
三、java.lang.Math
类Math包含用于执行基本数字运算的方法。
public static 类型 abs (类型 a);
//返回“类型”值的绝对值。此处类型代指int、float、double等数值的类型。
min(类型 a,类型 b);//求较小值。
static long round (double a);
//返回与参数最接近的 long ,并将关系四舍五入。 100.5四舍五入是101,-100.5四舍五入是-100.
static double floor (double a);
//返回小于或等于参数的数。如floor(3.5)是3.0,floor(-3.5)是-4.0.
static double ceil (double a);
//返回大于或等于参数的数。 如ceil(3.5)是4.0,ceil(-3.5)是-3.0.
四、java.lang.Arrays
该类包含用于操作数组的各种方法(例如排序和搜索)。
binarySearch () //用于二分查找
toString (数组名) //用于输出数组
sort() //用于排序
copyOf() //动态扩容
static boolean[] copyOf(boolean[] original, int newLength)
static boolean[] copyOf(boolean[] original, int newLength)
static byte[] copyOf(byte[] original, int newLength)
static char[] copyOf(char[] original, int newLength)
static double[] copyOf(double[] original, int newLength)
static float[] copyOf(float[] original, int newLength)
static int[] copyOf(int[] original, int newLength)
static long[] copyOf(long[] original, int newLength)
static short[] copyOf(short[] original, int newLength)
static <T> T[] copyOf(T[] original, int newLength) //T是数组中对象的类
static <T,U> T[] copyOf(U[] original, int newLength, 类<? extends T[]> newType)
//U是原始数组中对象的类 T是返回数组中的对象类
五、 java.math.BigDecimal
主要用于解决运算中小数的精度问题。
构造方法:
public BigDecimal (String val) {
}
//将 BigDecimal的字符串转换为 BigDecimal。
加法:
public BigDecimal add (BigDecimal augend);
示例:
BigDecimal b1 = new BigDecimal ("0.1");
BigDecimal b2 = new BigDecimal ("0.2");
BigDecimal b3 = b1.add(b2);
然后输出b3,b3的值就是0.3;
或者用一个变量接着运算结果:double i = b3.doubleValue();
减法:
BigDecimal subtract (BigDecimal subtrahend);
乘法:
BigDecimal multiply (BigDecimal multiplicand);
除法:
BigDecimal divide (BigDecimal divisor);
六、java.util.Date
表示特定的时刻,精度毫秒。它允许将日期解释为年,月,日,小时,分钟和秒(Calendar类)。 它还允许格式化和解析日期字符串(DateFormat类)。
long getTime(); //返回Date对象从1970年1月1日东八区的早上八点整以来的毫秒数。1秒等于1000毫秒
构造方法:
Date();//表示当前时间。
Date (long date);//传入一个时间,返回从1970年1月1日东八区的早上八点整到date的毫秒数。
用Date date = new Date();
System.out.println(date); //以获取当前时间
System.out.println(date.getTime());//以获取当前时间的毫秒数
七、java.text.DateFormat
DateFormat是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化和分析日期或时间。
SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 HH:mm ss");
String str = format.format(new Date());//format方法将其转换成字符串(根据当前计算机的时间)
System.out.println(str);
Date date = format.parse("2021年01月01 12:12 12");//将日期字符串转化成Date对象
System.out.println(date.getTime());
y 表示年,几位写几个y
M 表示月
d 表示日
H 表示时
m 表示分
s 表示秒
八、java.util.Calendar
Calendar类是一个抽象类,Calendar提供了一个类方法getInstance ,用于获取此类型的通用对象。
Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);//取出日历的年
int day = c.get(Calendar.DAY_OF_YEAR);//按年的第几天取出day
c.set(Calendar.YEAR,2021);//设置当前生成对象的年
c.add(Calendar.YEAR,1);//对当前对象的年进行加1操作
//0-11表示1-12月,周是从周日开始算
System.out.println(c.get(Calendar.YEAR));//打印的是对象更改以后的值
//getTime:获取日历时间,表示的Date对象
Date d = new c.getTime();
//getActualMaximum获取某字段的最大值
int m = c.getActualMaximum(Calendar.MONTH);//获取当前年最大的月数
int d = c.getActualMaximum(Calendar.DAY_OF_MONTH);//获取当前月最大的天数
九、java.lang.System
System类提供的设施包括标准输入,标准输出和错误输出流; in “标准”输入流、out “标准”输出流、err “标准”错误输出流。
static void exit (int status); //终止当前运行的Java虚拟机,非0表示异常终止。
static long currentTimeMillis(); // 以毫秒为单位返回当前时间(1970年1月1日东八区早上8点)。
static void arraycopy (Object src, int srcPos, Object dest, int destPos, int length);
// 将指定源数组中的数组从指定位置开始复制到目标数组的指定位置。
//src - 源数组、srcPos - 源数组中的起始位置、dest - 目标数组、destPos - 目标数据中的起始位置、length - 要复制的数组元素的数量。
十、String(绝对重点)
String类表示字符串。 Java程序中的所有字符串文字都是此类的实例。 字符串是不变的; 它们的值在创建后无法更改。字符串缓冲区支持可变字符串。因为String对象是不可变的,所以可以共享它们(两个字符串如果完全相等,存储在同一块内存,缓存在字符串常量池)。
1.字符串常量池
字符串常量池存在于方法区。方法区被所有线程共享。
2.堆
一个JVM实例只存在一个堆内存,堆内存的大小是可以调节的。类加载器读取了文件后,需要把类、方法、常变量放到堆内存中,保存所有引用类型的真实信息,方便执行器执行。
堆在逻辑上分为三部分:
1)新生代:
刚创建的对象存储的位置,常称为YoungGen,位于堆空间。
新生代的GC频率很高,如果一个对象连续被GC问过15次,代表作用域比较广,那么就会被放进老年代。这么做能够节省GC的访问次数。
新生代又分为 Eden区:新创建的对象
Survior(幸存区):经过垃圾回收,但次数少于15次的对象
2)老年代:
回收次数超过15次,依然存活的对象
3)永久代:
永久储存的对象。
String str1 = "abc";
String str2 = "abc";
System.out.println(str1 == str2);//返回的是true
String str1 = "abc";
String str2 = new String("abc");//重新开辟了一块内存
System.out.println(str1 == str2);//返回的是false
JDK1.8后移除了永久代,用元空间(Metaspace)进行替代,字符缓冲区放入了元空间。
3.构造方法:
直接用String str1 = "abc";//这种方式比较常用
String (byte[] bytes, String charsetName); // 构造一个新的String由指定用指定的字节的数组解码charset 。
String (byte[] bytes); // 通过使用平台的默认字符集解码指定的字节数组构造新的 String 。
String (char[] value); // 分配新的 String ,使其表示当前包含在字符数组参数中的字符序列。
4.方法:
char charAt (int index); // 返回指定下标处的 char值。
int codePointAt (int index); // 返回指定下标处的字符(Unicode代码点)。
int compareTo (String anotherString); // 按顺序比较两个字符串。0相等,返回正数大于,负数代表小于。
String toString(); // 打印字符串
String toUpperCase(); // 转大写
static String valueOf (Object obj); // 返回 Object参数的字符串表示形式
5.字符串拼接
尽量避免字符串拼接如str1 = str1 + str2 + str3;浪费内存,拼接过程中被丢弃的字符串储存在永久代,所以不会被GC回收,会一直呆在字符串常量池中。
解决办法(减少内存浪费):
使用StringBuffer或者StringBuilder
StringBuffer(); //构造一个字符串缓冲区,其中没有字符,初始容量为16个字符,超过就会自动扩容。
先new一个StringBuffer(),然后调用append()方法进行拼接,然后转成字符串,再调用字符串的方法进行后续操作。
/**StringBuffer sb = new StringBuffer();
*sb.append("1");
*sb.append("2");
*sb.append("3");
*String str = sb.toString();
*System.out.println(str);
*/
StringBuffer是线程安全的实现,StringBuilder是线程不安全的实现,具体项目再决定用谁,在不考虑安全问题下,两者的使用完全一致。