Java常用类入门
前言
Java常用类入门,有基本数据类型的包装类、字符串相关类、时间处理相关类、其它常用类。
一、基本数据类型的包装类
好处
1)Java作为一门面向对象语言,很多地方都涉及到对象操作,而8个基本数据类型却不是对象,将其转化为对象,便于使用Object[]、集合的操作。
2)封装起来,提供更加丰富的功能。
用法
1)基本数据类型转化为对象
//1.基本数据类型转化为对象
Integer i = new Integer(100);
i = Integer.valueOf(-1000);//新写法
2)对象转化为基本数据类型
Integer i = new Integer(100);
int val = i.intValue();
3)将字符串转化为integer对象
String str = "123";
val = Integer.parseInt(str);
4)Integer 转化为string对象
str = i.toString();
1、自动装箱、自动拆箱
//5.自动装箱和自动拆箱,JVM自动执行Integer.valueOf(5),this.intValue()
Integer n = 5;//编译器将其改为Integer.valueOf(5)
int a = n;//编译器将其改成n.intValue();若n没有初始化,是null,这里就会空指针异常。
2、包装类的缓存问题
先看源码
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
static final Integer cache[];
这个内部类中有一个缓存,从源码可以看成存的是【-128,127】的integer对象。我们称之为常量池,作为静态资源,放在方法区共享。
所以只要值在这个范围类,都是一个对象。JVM自动装箱时,调的是Integer.valueOf()
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
@HotSpotIntrinsicCandidate
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}`在这里插入代码片`
由源码可知,valueOf中使用了常量池。
二、String、StringBuilder、StringBuffer
1、String
不可变Unicode字符序列,每当字符增加删除时,都会产生新的对象。
@Stable
private final byte[] value;
private final byte coder;
public String() {
this.value = "".value;
this.coder = "".coder;
}
1)常量池+编译器优化
//右边是两常量相加,编译时就能识别常量,编译器就直接将两常量拼接了,所以这里只产生一个字符串对象s1
String s1 = "hello" + " java";
String s2 = "hello java";//这都属于字符串常量,s1 s2都引用常量池同一地址
System.out.println(s1 == s2);//true
2)非常量,产生新的对象。
String s3 = "hello";
String s4 = "java";
String s5 = s3 + s4;//编译时无法识别右边时常量(编译器无法优化),所以是两对象向拼接,然后生成新的对象。
System.out.println(s2 == s5);//false
2、StringBuilder
1)可变字符序列,不做线程同步检查,所以不安全效率高。
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, Comparable<StringBuilder>, CharSequence
abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
byte[] value;
/**
* The id of the encoding used to encode the bytes in {@code value}.
*/
byte coder;
注:value并没有被final修饰,所以可变。没有synchronized修饰方法,所以线程不安全效率高。
2)方法
append,delete,deleteChar,insert,reverse,tostring.
和string同:indexOf,substring,length,charAt.
主要了解append方法,添加字符在后面,并返回自身对象。
@Override
@HotSpotIntrinsicCandidate
public StringBuilder append(String str) {
super.append(str);
return this;
}
3、StringBuffer
1)可变字符序列,做线程同步检查,所以线程安全效率低。
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, Comparable<StringBuffer>, CharSequence
abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
byte[] value;
/**
* The id of the encoding used to encode the bytes in {@code value}.
*/
byte coder;
@Override
public synchronized int compareTo(StringBuffer another) {
return super.compareTo(another);
}
@Override
public synchronized int length() {
return count;
}
@Override
public synchronized int capacity() {
return super.capacity();
}
@Override
public synchronized void ensureCapacity(int minimumCapacity) {
super.ensureCapacity(minimumCapacity);
}
/**
* @since 1.5
*/
@Override
public synchronized void trimToSize() {
super.trimToSize();
}
注:value并没有被final修饰,所以可变。有synchronized修饰方法,所以线程安全效率低。
2)方法,同StringBuilder
4、操作陷阱
由于String是不可变字符序列,所以每次都要产生新的对象,导致在循环中产生大量垃圾,且耗时。
long pre_m = Runtime.getRuntime().freeMemory();//获取当前可用内存大小
long pre_t = System.currentTimeMillis();//获取系统当前时间
String data = "";
for (int i = 0; i < 5000; i++) {
data += i;//相当于产生了10000个对象,每次的data及每次的i
}
long cur_m = Runtime.getRuntime().freeMemory();
long cur_t = System.currentTimeMillis();
System.out.println("String对象占用内存大小:" + (pre_m - cur_m));
System.out.println("String对象用时:" + (cur_t - pre_t));
long pre_sbm = Runtime.getRuntime().freeMemory();//获取当前可用内存大小
long pre_sbt = System.currentTimeMillis();//获取系统当前时间
StringBuilder value = new StringBuilder();
for (int i = 0; i < 5000; i++) {
value.append(i);//只有一个对象
}
long cur_sbm = Runtime.getRuntime().freeMemory();
long cur_sbt = System.currentTimeMillis();
System.out.println("StringBuilder对象占用内存大小:" + (pre_sbm - cur_sbm));
System.out.println("StringBuilder对象用时:" + (cur_sbt - pre_sbt));
三、时间处理类
1、Date
时间核心类,以1970-1-1 00:00:00为起点,主要算时间毫秒数。
//1970.1.1 00:00:00作为0刻度
long time = Long.MAX_VALUE / (1000 * 3600 * 24 * 365);
System.out.println("一共前后可表示:" + time + "天");
//当前时间
long cur_time = System.currentTimeMillis();
long cur_time2 = new Date().getTime();
System.out.println(cur_time2);
2、DateFormat
Date分出来的类,专门管理字符串跟时间的关系,该类为抽象类,实现类为SimpleDateFormat.
//DateFormat 实现类SimpleDataFormat,将时间转化为字符串
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat sdf3 = new SimpleDateFormat("hh:mm:ss");
String cur_day = sdf1.format(new Date());
System.out.println(cur_day);
Date cur_date = sdf2.parse(cur_day);
DateFormat df1 = new SimpleDateFormat("今年第w周");
System.out.println(df1.format(new Date()));
DateFormat df2 = new SimpleDateFormat("这个月第W周");
System.out.println(df2.format(new Date()));
3、Calendar
Date分出来专门处理日期的类,该类为抽象类,实现类为GregorianCalendar。
//calendar类 实现类GregorianCalendar
Calendar cl = new GregorianCalendar(2021,11,10);
System.out.println(cl.get(Calendar.YEAR));
//可设置年份等
cl.set(Calendar.YEAR,2020);
//可先前后推移
cl.add(Calendar.YEAR,-1);
//跟时间关联
cl.setTime(new Date());
四、其它常用类
1)Math类,数学上面哪些知识,Math类提供静态方法和属性,可查API。
2)Random类
import java.util.Random;
public class TestOtherClass {
public static void main(String[] args) {
double p = Math.PI;
//Random
Random rand = new Random();
//生成【0,1)之间的数
rand.nextInt();
rand.nextDouble();
//生成【0,10)的随机数
rand.nextInt(10);
//[20,30)
System.out.println(20 + rand.nextInt());
System.out.println(20 + (int)rand.nextDouble() * 10);
}
}
3)File类,操作文件。
public class TestFile {
public static void main(String[] args) throws IOException {
File file = new File("d:\\study\\Java基础学习.mp4");
//获取项目路径
System.out.println(System.getProperty("user.dir"));
File cur_dir = new File(System.getProperty("user.dir"));
file.createNewFile();//throws IOException
System.out.println("文件是否存在:"+file.exists());
System.out.println("文件是否为目录:"+file.isDirectory());
System.out.println("文件是否文件:"+file.isFile());
System.out.println("文件最后修改时间:"+new Date(file.lastModified()));
System.out.println("文件的大小:"+file.length());
System.out.println("文件的目录路径:"+file.getPath());
}
}
五、打印目录树
public static void main(String[] args) {
File f = new File(System.getProperty("user.dir"));
printFile(f, 0);
}
private static void printFile(File f, int layer) {
for (int i = 0; i < layer; i++) {
System.out.print("-");
}
System.out.println(f.getName());
if (f.isDirectory()) {
File[] files = f.listFiles();
for (File file : files) {
printFile(file, layer + 1);
}
}
}
总结
1)包装类,为了便于操作
2)String、StringBuilder、String Buffer
3)Random、Date、Calendar、DateFormat
4)File、递归打印文件目录
参考文献
[1] Java SE 高淇.