Java中内置类及其方法的使用通常翻阅对应的API文档即可,但是对于常用的一些类和方法还是需要我们能够熟练的使用。
一、System
System.gc():手动启动垃圾回收器,垃圾回收器通常是自动启动的,某些时候Java可能觉得当下的情况并不需要启动gc,但是你又想启动的话,就可以调用这个方法手动启动gc。
System.exit(0):终止并退出JVM,exit方法可以传入一个程序结束的状态码,通常传入0就可以了。
System.currentTimeMillis():获取自1970年1月1日 00:00:00 000到当前时间的总毫秒数。
System.arraycopy?(Object src, int srcPos, Object dest, int destPos, int length):从源数组src中拷贝若干length连续的元素到目标数组dest当中,src为源数组,srcPos为源数组的起始下标,dest为目标数组,destPos为目标数组的起始下标,length为拷贝的元素个数或长度。
二、Object
protected Object clone():返回对象的克隆,注意这个方法的修饰符为protected,只有子类或同一个包下才能使用。
int hashCode():返回对象的哈希值。
boolean equals(Object obj):判断两个对象是否相等,默认使用“==”进行判断。注意,“==”的判断其实判断的是变量的值,对于引用类型就是比较的是内存地址,但这通常不是我们想要的结果,因为对于两个对象的比较,我们大多时候认为同一个类的对象,如果它们的属性等对象的内容是相同的话,那么这两个对象也可以认为它们是相同的,而不是去判断那它们的内存地址,所以这种时候就需要重写这个方法了。也由此可以看出,平时判断相等时,如果是基本数据类型则使用“==”进行判断,如果是引用数据类型,如String等,则需要使用它自带的equals方法。
String toString():将对象转换成字符串形式,默认为“类名@对象的内存地址”。在打印某个对象时,也会自动调用对象的这个方法。但是因为这个方法默认的返回值很多时候并不是我们想要的,所以通常都是在需要使用的时候重写它,而不是使用它的默认值。
三、String
方法区的字符串常量池:字符串虽然也是引用类型的实例对象,但是字符串字面值是存储在方法区中的字符串常量池当中,无论是使用双引号定义还是使用String定义,都会先在方法区内存中创建一个字符串对象,如果以后使用到了相同的字符串,则不会再创建一个字符串对象,而是会直接使用已经存在的字符串对象。
String类型引用:需要注意的是,直接使用双引号定义的字符串对象会直接在方法区中直接创建一个字符串对象,但是因为使用new关键字都是会先在堆中创建对应的对象,所以对于使用new关键字创建String对象,如“String s = new String("hello");”,虽然创建的对象在堆中,但s的值(内存地址)其实还是指向的是在方法区的字符串常量池中“"hello"”这个字符串对象。
字符串垃圾回收:另外一点,垃圾回收器不会回收字符串常量池中的字符串常量对象。
常用的构造方法:
// 最常用的方法 String s1 = "hello"; // 不常用 String s = new String("hello"); // 传入一个byte数组 byte[] bytes = {97, 98, 99}; // 97->a, 98->b, 99->c String s2 = new String(bytes); System.out.println(s2); // 输出:abc String s3 = new String(bytes, 1, 2); System.out.println(s3); // 输出:bc // 传入一个char数组 char[] chars = {‘h‘, ‘e‘, ‘l‘, ‘l‘, ‘o‘}; String s4 = new String(chars); System.out.println(s4); // 输出:hello String s5 = new String(chars, 2, 3); System.out.println(s5); // 输出:llo
常用方法:
四、StringBuffer/StringBuilder
如果需要进行大量的字符串拼接操作,建议使用Java自带的StringBuffer或StringBuilder,而不是使用加号+。
StringBuffer示例:
public class Test{ public static void main(String[] args){ // 默认会创建一个长度为16的byte[] // StringBuffer stringBuffer = new StringBuffer(); // 创建一个指定长度的StringBuffer StringBuffer stringBuffer = new StringBuffer(100); // 拼接字符串统一调append方法,当拼接的字符串长度超过了16或者指定的容量,这个byte[]数组会自动扩容 stringBuffer.append("abc"); stringBuffer.append(3.14); stringBuffer.append(true); } }
关于StringBuffer的优化:其中一个优化点是在初始化时预估一下需要的字符串长度,给一个大一点的长度(默认的数组只有16个byte),以减少后续数组扩容的次数,关键点在于这个长度不能太大也不能太小,太大也浪费空间,太小会增加扩容次数。
StringBuilder和StringBuffer的区别:两者在示例的使用上都一样的,都可以用于字符串的拼接,但区别在于StringBuffer是有synchronized关键字修饰的,表示在多线程的环境下是线程安全的,StringBuilder则没有synchronized关键字修饰,表示不是线程安全的。
对比String:String的底层其实是一个final类型的byte[], StringBuffer底层同样是一个byte[],但区别是没有final修饰符,因为数组的长度一旦确定了就不能改变,这表示final修饰的String类型的变量(引用)指向的内存地址是不能改变的,即该字符串是不能改变的,但是如果没有final修饰符,则这个数组满了之后可以扩容,StringBuffer的变量就可以指向扩容后新的数组的内存地址。说到String的这个final,特别需要注意的是,对于如“String s = "hello";”而言,final修饰的是“"hello"”这个字符串对象本身,而不是变量s(引用),s是可以重新给它赋值的。
五、8中基本数据类型的包装类
包装类之所以存在,就是为了应对一种情况,一些方法的参数需要是Object类型,但是又需要传入Java中的基本数据类型,基本数据类型因为类型不兼容所以肯定是不能传进去的,此时就需要使用基本数据类型经过包装过后的的包装类了,包装类型都属于引用数据类型,且它们的最终父类都是Object类,此时就可以传入这些方法中进行使用了。
基本数据类型对应的包装类:除了int和char类型对应的包装类略有不同外,其他类型的包装类都是其本身单词的首字母大写形式。
public class Test{ public static void main(String[] args){ // 装箱:将基本数据类型转换为引用数据类型 Integer i = new Integer(100); // 拆箱:将包装类对象转换为基本数据类型 float f = i.floatValue(); // 拆箱:将包装类对象转换为基本数据类型 int iv = i.intValue(); } }
自动装箱和自动拆箱:平时使用的时候都是使用的自动转换,上面示例的方式一般不常用了。
public class Test{ public static void main(String[] args){ // 自动装箱:自动将基本数据类型转换为引用数据类型 Integer i = 100; // 自动拆箱:自动将包装类对象转换为基本数据类型 int iv = i; // 对于算术运算,会进行自动拆箱操作 System.out.println(i + 1); } }
整数型常量池:Java中为了提高程序的执行效率,将[-128, 127]之间的所有包装对象提前创建好了,并放到了方法区中的整数型常量池中,以后只要用到这些对象就不会再去new对象了,就像字符串常量池一样。
Integer常用方法:因为包装类的用法大部分都相同,不同的部分也可以通过查阅帮助文档来了解使用,所以这里只展示Integer类的常用方法。
六、数组
// 静态初始化语法,即定义的时候就初始化好了所有的元素 int[] array1 = {100, 55, 30}; // 动态初始化语法,初始化时只定义好数组中元素的个数,new int[5]表示创建一个 // 有5个int类型元素的数组,但是并没有初始化数组中元素的值,只是赋予了默认值,即 // 基本数据类型的默认值和引用类型的默认值null。 int[] array2 = new int[5];
使用数组时,应注意以下几点:
数组的访问和赋值:直接通过下标进行访问和赋值即可,如“array1[0]=22;”。
数组的优点和缺点:
数组扩容:Java中数组扩容的原理或者说方法是将小容量的数组使用“System.arraycopy”方法拷贝到大容量的数组当中,然后删除小容量的数组,Java中数组的扩容效率是较低的,所以在数组的使用当中,应该尽量避免数组的拷贝和扩容。
二维数组:二维数组,包括三位数组等多位数组,其实就是数组中的元素又是一个数组,多少维其实由这个数组的元素“套了多少层”决定的,二维就是数组中的元素是一个一维数组,同理,三位数组中的元素是一个二维数组,然后以此类推即可。
// 静态初始化语法 int[][] a = { {1, 2, 3}, {4, 5, 6}, {9} }; // 动态初始化语法 int[][] array = new int[3][4];
Arrays工具类:这个工具类最常用的就是sort和binarySearch这两个方法,但是注意,二分查找方法的前提是数组已经排好序了。
import java.util.Arrays; public class ArrayToolsTest{ public static void main(String[] args){ int[] myArray = {3, 2, 6, 4}; // sort方法可以将一个数组排序,但是注意,sort方法并没有返回值, // 即不是返回排好序的数组,而是直接排序传入的数组 Arrays.sort(myArray); // 二分查找算法的前提是需要数组已经排好序了 // 返回值为元素在数组中的下标,元素在数组中不存在则返回-1 // 但是这个方法多用来判断数组中有没有这个元素,因为如果数组中该元素 // 不只一个的话,那么返回的下标不一定是第一个元素的下标 int indexd = Arrays.binarySearch(myArray, 6); } }
七、Date/SimpleDateFormat
对日期进行格式化则使用“java.text.SimpleDateFormat”类。
使用示例:
// 专门进行日期格式化的类 import java.text.SimpleDateFormat; // 日期操作的类 import java.util.Date; public class DateTest { public static void main(String[] args) throws Exception { // 直接调用无参构造方法,会默认使用当前系统日期时间来进行初始化,精确到毫秒 Date nowTime = new Date(); // 输出当前日期时间 System.out.println(nowTime); // 按照指定格式创建日期格式化对象 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); // 将日期对象格式化为指定格式的字符串 String nowTimeStr = sdf.format(nowTime); System.out.println(nowTimeStr); // 将时间字符串按格式转换为Date对象,需要注意,指定的格式需要和字符串中的格式相同 String t = "2020-06-01 21:18:22 333"; SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); Date dateTime = sdf2.parse(t); // 获取自1970年1月1日 00:00:00 000到当前日期的总毫秒数 long nowTimeMillis = System.currentTimeMillis(); System.out.println(nowTimeMillis); // 根据毫秒数创建一个Date对象 Date tt = new Date(nowTimeMillis); } }
日期时间格式化字符如下:
Letter | Date or Time Component | Presentation | Examples |
---|---|---|---|
G |
Era designator | Text | AD |
y |
Year | Year | 1996 ; 96 |
Y |
Week year | Year | 2009 ; 09 |
M |
Month in year (context sensitive) | Month | July ; Jul ; 07 |
L |
Month in year (standalone form) | Month | July ; Jul ; 07 |
w |
Week in year | Number | 27 |
W |
Week in month | Number | 2 |
D |
Day in year | Number | 189 |
d |
Day in month | Number | 10 |
F |
Day of week in month | Number | 2 |
E |
Day name in week | Text | Tuesday ; Tue |
u |
Day number of week (1 = Monday, ..., 7 = Sunday) | Number | 1 |
a |
Am/pm marker | Text | PM |
H |
Hour in day (0-23) | Number | 0 |
k |
Hour in day (1-24) | Number | 24 |
K |
Hour in am/pm (0-11) | Number | 0 |
h |
Hour in am/pm (1-12) | Number | 12 |
m |
Minute in hour | Number | 30 |
s |
Second in minute | Number | 55 |
S |
Millisecond | Number | 978 |
z |
Time zone | General time zone | Pacific Standard Time ; PST ; GMT-08:00 |
Z |
Time zone | RFC 822 time zone | -0800 |
X |
Time zone | ISO 8601 time zone | -08 ; -0800 ; -08:00 |
八、数字格式化
数字格式化应该使用“java.text.DecimalFormat”,如果处理大数据或者财务数据,应该使用“java.math.BigDecimal”,因为它的精度极高,具体使用可参阅API文档。
部分格式化字符:
import java.text.DecimalFormat; public class DecimalFormatTest{ public static void main(String[] args){ DecimalFormat df = new DecimalFormat("###,###.##"); String s = df.format(1234.561); System.out.println(s); // 输出:1,234.56 DecimalFormat df2 = new DecimalFormat("###,###.0000"); String s2 = df2.format(1234.56); System.out.println(s2); // 输出:1,234.5600 } }
九、随机数
想要生成一个随机数,应该使用“java.util.Random”,详细用法请参阅API文档。
import java.util.Random; public class RandomTest{ public static void main(String[] args){ Random random = new Random(); // 生成一个随机整数 int num1 = random.nextInt(); // 生成一个[0, 100]的随机整数,注意,这里不包括101 int num2 = random.nextInt(101); } }
十、枚举
枚举类型,关键字enum,也是一种引用数据类型,一个枚举编译后也会生成一个“.class”字节码文件。
枚举中的每一个值可以看做是常量,且每个枚举值只需要定义对应的名称即可,不需要给它赋值。
public enum Result{ // 只需要定义每个枚举项的名称即可,不需要给它赋值。 // 如果只有两个枚举项,建议使用boolean类型即可,多余两个时才建议使用枚举类型。 SUCCESS, FAIL }
public class Test{ public static void main(String[] args){ Result res = divide(3, 0); System.out.println(res); } public static Result divide(int a, int b){ try{ int c = a / b; return Result.SUCCESS; } catch (Exception e) { return Result.FAIL; } } }
原文:https://www.cnblogs.com/guyuyun/p/13028767.html