Java基础类简介
一、系统相关
1、System
- 获取平台信息
System类提供获取当前Java程序的运行平台相关信息,在程序中不能创建System类的对象,可以通过调用此类的静态方法获取这些信息。
//系统环境变量
Map<String, String> env = System.getenv();
//系统属性
Properties props = System.getProperties();
//获取指定的环境变量或系统属性
System.getenv("JAVA_HOME");//C:\Program Files\Java\jdk1.8.0_45
System.getenv("OS");//Windows_NT
System.getProperty("os.name");//Windows 8.1
- 输入&输出
可以使用System.in
(InputStream)、System.out
(PrintStream)、System.err
(PrintStream)获取标准输入、标准输出和错误输出流,而且可以使用System.setIn()
、System.setOut()
、System.setErr()
方法来改变系统的标准输入、输出和错误输出流。
static PrintStream | err |
static InputStream | in |
static PrintStream | out |
static void | setErr(PrintStream err) |
static void | setIn(InputStream in) |
static void | setOut(PrintStream out) |
- 获取时间
调用System.currentTimeMillis()
(以毫秒为单位)与System.nanoTime()
(以微秒为单位)方法的返回值是当前时间与UTC 1970年1月1日午夜的时间差。
//Date:20180902
System.out.println(System.currentTimeMillis());//1535859644472
System.out.println(System.nanoTime());//98770354993078
- 获取对象的
hashCode
可以使用System.identityHashCode(Object x)
方法获取指定对象的hashCode
值(根据此对象的地址计算),如果某个类的hashCode()
方法被重写,仍然可以使用此方法获取唯一标识该对象的hashCode
值。
class User{
@Override
public int hashCode() {
return 666;
}
}
User user = new User();
System.out.println(user.hashCode());
System.out.println(System.identityHashCode(user));
程序输出:
666
1704856573
- 垃圾回收
可以调用System.gc()
通知系统进行垃圾回收,调用System.runFinalization()
通知系统进行资源清理。
2、Runtime
Runtime
类代表Java程序的运行时环境,每个Java程序都有一个对应的Runtime对象,可通过此对象来获得运行时的环境信息(处理器、内存等):
Runtime runtime = Runtime.getRuntime();
//处理器
System.out.println(runtime.availableProcessors());//4
//JVM可使用的总内存,以字节为单位
System.out.println(runtime.totalMemory());//128974848
//JVM空闲内存
System.out.println(runtime.freeMemory());//126929904
Runtime对象也无法直接创建,可以通过Runtime.getRuntime()
来获取。与System
类类似,Runtime
类也提供了gc()
和runFinalization()
方法;除此之外,Runtime类还提供了load(filename)
和loadLibrary(libname)
方法来加载文件和动态链接库。
Runtime runtime = Runtime.getRuntime();
runtime.gc();
runtime.runFinalization();
runtime.load(filename);
runtime.loadLibrary(libname);
Runtime还可以单独启动一条进程来运行操作系统的命令:
Runtime runtime = Runtime.getRuntime();
try {
//运行计算器
runtime.exec("calc");
} catch (IOException e) {
e.printStackTrace();
}
二、获取用户输入
1、Scanner
使用Scanner
类可以很方便地获取用户的键盘输入,Scanner是一个基于正则表达式的文本扫描器,可以从文件、输入流、字符串中解析出基本类型值和字符串。
Scanner类主要使用以下方法判断或获取输入:
-
hasNext()
或hasNextXxx()
是否有下一个输入项,例如:
hasNextInt()
、hasNextBoolean()
等,hasNext()
方法判断是否包含下一个字符串。 -
next()
或nextXxx()
获取下一个输入项,例如:
next()
、nextFloat()
、nextBigDecimal
等。 -
hasNextLine()
是否还有下一行输入。
-
nextLine()
获取下一行输入。
Scanner默认使用空白作为多个输入项之间的分隔符,可以使用useDelimiter(pattern)
方法设置分隔符,参数是正则表达式。
-
样例:获取控制台输入并打印
Scanner scanner = new Scanner(System.in); scanner.useDelimiter("\n"); while(scanner.hasNext()){ System.out.println(scanner.next()); }
输入:
how are you
输出:how are you
如果不设置分隔符,即去掉:
scanner.useDelimiter("\n");
:输入:
how are you
输出:how are you
-
样例:读取文件内容并输出
Scanner scanner = new Scanner(new File("G://abc.html"));
//按行读取文件内容
while(scanner.hasNextLine()){
System.out.println(scanner.nextLine());
}
2、BufferedReader
可以用BufferedReader
来包装System.in
,然后使用它的readLine()
方法来逐行读取键盘输入。BufferedReader
是Java IO
中的一个字符包装流,它必须建立在一个字符流的基础上,但System.in
是字节流,因此需要使用转换流InputStreamReader
将System.in
转换为字符流。
与Scanner
类不同的是,BufferedReader
不能读取基本类型输入项(Long、Boolean等),它只能读取字符串:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = null;
while((str = br.readLine()) != null){
System.out.println(str);
}
三、字符串与数值
1、Object类
Object
类是所有类的父类,所有Java对象都可以调用Object类的方法,常用方法:
equals()
public boolean equals(Object obj) {
return (this == obj);
}
hashCode()
public native int hashCode();
返回对象的hashCode值,通常与System.identityHashCode(Object x)
方法返回值相同。
getClass()
public final native Class<?> getClass();
返回对象运行时的类。
toString()
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
返回对象的字符串表示:运行时类名@hashCode的十六进制值。
finalize()
protected void finalize() throws Throwable { }
当程序中该对象不再被引用时,垃圾回收器调用此方法清理该对象的资源。
2、字符串
- String
String
类是不可变的,当一个String对象被创建后,包含在这个字符串中的字符序列是不可改变的,直到此对象销毁。
例如:
String str = "hello" + "-" + "world";
上面的例子中,除了使用了3个字符串直接量之外,还会额外生成2个字符串常量:"hello-"
和"hello-world"
;因为String是不可变的,所以会导致生成很多临时变量,而使用StringBuffer
或StringBuilder
就可以避免这个问题。
- StringBuffer
StringBuffer
代表可变的字符序列,当一个StringBuffer对象被创建后,可以使用append()
、reverse()
等方法来改变字符序列。可以通过调用toString()
方法转换为String对象。
- StringBuilder
StringBuilder
与StringBuffer
类似,只不过StringBuffer是线程安全的,而StringBuilder不是线程安全的,因此性能略高。
String
、StringBuilder
与StringBuffer
它们都有length属性,但String类的length属性是不可变的,而后两者的length属性是可变的。
3、数值
- Math
Java提供了Math
工具类来实现一些复杂的数学运算,该类中提供了大量静态方法和两个静态属性:Math.PI
(π)和Math.E
(e)。
System.out.println(Math.PI);//3.141592653589793
System.out.println(Math.E);//2.718281828459045
//乘方
System.out.println(Math.pow(2, 3));//8.0
//绝对值
System.out.println(Math.abs(-0.65));//0.65
//平方根
System.out.println(Math.hypot(3, 4));//5.0
//角度、弧度转化
System.out.println(Math.toDegrees(Math.toRadians(90)));//90.0
//三角函数
System.out.println(Math.sin(Math.toRadians(30)));//0.49999999999999994
//向下取整
System.out.println(Math.floor(1.2));//1.0
//向上取整
System.out.println(Math.ceil(1.2));//2.0
//四舍五入
System.out.println(Math.round(1.56));//2
//伪随机数(0≤x<1)
System.out.println(Math.random());
-
Random
Random
类专门用于生成一个伪随机数,它的构造器如下:-
public Random()
使用默认的种子
-
public Random(long seed)
使用指定的种子
它可以生成各种类型伪随机数:整数、浮点数或者指定随机数的范围,例如:
-
nextInt()
生成一个int范围内的整数
-
nextInt(bound)
生成一个
0 ~ bound
范围内的整数 -
nextBoolean()
随机生成一个布尔类型值
-
nextFloat()
随机生成一个
0.0 ~ 1.0
之间的浮点数
……
如果使用相同的种子创建
Random
对象,再以相同的方法产生随机数,那么结果是一样的:Random random = new Random(555); System.out.println(random.nextInt(100)); System.out.println(random.nextLong()); System.out.println(random.nextBoolean()); Random another = new Random(555); System.out.println(another.nextInt(100)); System.out.println(another.nextLong()); System.out.println(another.nextBoolean());
程序输出:
38 1257936417059039565 false 38 1257936417059039565 false
为了避免两个Random对象生成相的伪随机数,可以使用当前时间作为Random的种子:
Random random = new Random(System.currentTimeMillis());
-
-
BigDecimal
float
、double
两种浮点类型在计算时很容易引起精度丢失,例如:
System.out.println("0.1 + 0.2 = " + (0.1 + 0.2));
System.out.println("1.0 - 0.55 = " + (1.0 - 0.55));
程序输出:
0.1 + 0.2 = 0.30000000000000004
1.0 - 0.55 = 0.44999999999999996
Java提供了BigDecimal
类来精确表示、计算浮点数,该类提供了很多构造器来创建BigDecimal对象。
使用BigDecimal(double val)
构造器时仍有一定的不可预知性:
BigDecimal decimal = new BigDecimal(0.1);
System.out.println(decimal);
输出:
0.1000000000000000055511151231257827021181583404541015625
因此建议优先使用基于String
的构造器:
BigDecimal decimal = new BigDecimal("0.1");
System.out.println(decimal);//0.1
如果必须使用double
类型数构造BigDecimal对象时,应该通过BigDecimal.valueOf(double val)
方法创建。
BigDecimal
类提供了add
、multiply
、pow
等方法进行算术运算:
BigDecimal num = new BigDecimal("0.1");
System.out.println("0.1 + 0.2 = " + num.add(new BigDecimal("0.2")));
System.out.println("0.1 - 0.055 = " + num.subtract(new BigDecimal("0.055")));
num = new BigDecimal("1.0");
System.out.println("1.0 / 2.0 = " + num.divide(new BigDecimal("2.0")));
System.out.println("1.0 * 6.0 = " + num.multiply(new BigDecimal("6.0")));
输出:
0.1 + 0.2 = 0.3
0.1 - 0.055 = 0.045
1.0 / 2.0 = 0.5
1.0 * 6.0 = 6.00
四、日期与时区
1、日期
-
Date
Java提供了
java.util.Date
类来处理日期和时间,常用构造器和方法如下:-
Date()
生成一个代表当前日期时间的
Date
对象,此方法调用Date(long date)
构造器,所传参数为System.currentTimeMillis()
。 -
Date(long date)
使用指定的
long
型整数生成Date
对象。 -
getTime()
返回
Date
对象对应的long型整数,即与GMT 1970-01-01 00:00:00
的时间差。 -
after(Date when)、before(Date when)
测试该日期是否在指定日期之后或之前。
Date date = new Date(); System.out.println(date.getTime());//1535881629374 Date ago = new Date(1535881515741L); System.out.println(date.after(ago));//true System.out.println(date.before(ago));//false
-
-
Calendar
Calendar
是一个抽象类,用于表示日历。该类提了getInstance()
方法来创建Calendar
对象,在创建时也可以指定TimeZone
和Locale
。Calendar
与Date
之前可以互相转换://从Calendar对象获得Date对象 Calendar calendar = Calendar.getInstance(); Date date = calendar.getTime(); //根据Date对象创建对应的Calendar对象 Date date = new Date(); Calendar calendar = Calendar.getInstance(); calendar.setTime(date);
Calendar
类提供了很多获取、修改日期、时间的方法:-
int get(int field)
获取日历指定字段的值
-
void set(int field, int value)
设置日历指定字段的值
-
void set(int year, int month, int date, int hourOfDay, int minute, int second);
设置日历的年、月、日、时、分、秒
-
void add(int field, int amount)
根据日历的规则,增加或减少指定字段的值。
-
void roll(int field, int amount)
与
add()
方法类似,此方法中如果日历字段添加amount
后超过了该字段表示的最大范围后,不会向上一个字段进位。
上面参数中的
field
为Calendar
类中的静态属性,例如:Calendar.MONTH
。Calendar calendar = Calendar.getInstance(); //int get(int field) System.out.println("年份: " + calendar.get(Calendar.YEAR)); //void set(year, month, date, hourOfDay, minute, second); calendar.set(2016, 5, 5, 15, 30, 45); //2016-6-5 15:30:45 System.out.println(calendar.getTime()); //年份减2 calendar.add(Calendar.YEAR, -2); //2014-6-5 15:30:45 System.out.println(calendar.getTime()); //月份加8 calendar.roll(Calendar.MONTH, 8); //2014-2-5 15:30:45 System.out.println(calendar.getTime());
-
容错性设置
还可以通过setLenient(lenient)
方法来设置Calendar的容错性,Calendar
默认是支持容错性的,例如:设置某一字段的值使其超过该字段上限时会自动向上一字段进位;如果关闭容错性,则不允许设置某字段的值超过其上限。
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, 15);
System.out.println(calendar.get(Calendar.MONTH));
calendar.setLenient(false);
calendar.set(Calendar.MONTH, 15);
//下面获取Month值时报错
System.out.println(calendar.get(Calendar.MONTH));
程序输出:
3
Exception in thread "main" java.lang.IllegalArgumentException: MONTH
at java.util.GregorianCalendar.computeTime(Unknown Source)
at java.util.Calendar.updateTime(Unknown Source)
at java.util.Calendar.complete(Unknown Source)
at java.util.Calendar.get(Unknown Source)
at com.strikeback.base.CalendarTest.main(CalendarTest.java:42)
set()
方法的延迟修改
如上面的程序所示,在调用set(field, value)
方法修改日历字段时,Calendar
所代表的时间并不会立即修改,直到下次调用get()
、getTime()
、add()
、roll()
等方法时才会重新计算日历的时间,这就是set
方法的延迟修改,优势是多次调用set()
方法并不会触发多次不必要的计算。
Calendar calendar = Calendar.getInstance();
calendar.set(2018, 7, 31);//2018-08-31
calendar.set(Calendar.MONTH, 8);
//set方法延迟修改,上一步并不会立即计算时间 [2018-10-01(9月没有31号)]
calendar.set(Calendar.DAY_OF_MONTH, 7);
System.out.println(calendar.getTime());//2018-09-07
2、时区
Java中使用TimeZone
表示时区,TimeZone
是一个抽象类,可以通过调用它的静态方法:getDefault()
或getTimeZone(id)
来创建实例。
常用方法:
-
getDefault()
获取机器默认的时区对象
-
getTimeZone(ID)
获取指定的时区对象
-
getID()
返回该时区的ID
-
getDisplayName()
返回时区名称
-
getAvailableIDs()
获取Java支持的所有时区ID
TimeZone timeZone = TimeZone.getDefault();
System.out.println(timeZone.getID());//Asia/Shanghai
System.out.println(timeZone.getDisplayName());//中国标准时间
String[] ids = TimeZone.getAvailableIDs();
System.out.println(Arrays.toString(ids));
timeZone = TimeZone.getTimeZone("America/Chicago");
System.out.println(timeZone.getDisplayName());//中央标准时间
参考资料:
- 《疯狂Java》