1. 程式人生 > >System、Runtime、BigDecimal類

System、Runtime、BigDecimal類

System類代表當前Java程式的執行平臺,程式不能建立System類的物件,System類提供了一些類變數和類方法,允許直接通過System類來呼叫這些類變數和類方法。

System類提供了代表標準輸入、標準輸出和錯誤輸出的類變數,並提供了一些靜態方法用於訪問環境變數、系統屬性的方法,還提供了載入檔案和動態連結庫的方法;

public class TestSystem
{
	public static void main(String[] args) throws Exception
	{
		//獲取系統所有的環境變數
		Map<String,String>
env = System.getenv(); for (String name : env.keySet()) { System.out.println(name + " ------> " + env.get(name)); } //獲取指定環境變數的值 System.out.println(System.getenv("JAVA_HOME")); //獲取所有的系統屬性 Properties props = System.getProperties(); //將所有系統屬性儲存到props.txt檔案中 props.store(new FileOutputStream
("props.txt") , "System Properties"); //輸出特定的系統屬性 System.out.println(System.getProperty("os.name")); } }

程式執行後會在當前路徑下生成一個props.txt檔案,該檔案中記錄了當前平臺的所有系統屬性;

System類提供了通知系統進行垃圾回收的gc()方法,以及通知系統進行資源清理的runFinalization()方法;

除此之外,System類的in、out和err分別代表系統的標準輸入、標準輸出和錯誤輸出流,並提供了setIn()、setOut()和setErr()方法來改變系統的標準輸入、標準輸出和標準錯誤輸出流;

System類還提供了一個identityHashCode(Object x)方法,該方法返回指定物件的精確hashCode值,也就是根據該物件的地址計算得到的hashCode值。當某個類的hashCode()方法被重寫後,該類例項的hashCode()方法就不能唯一地標識該物件;但通過identityHashCode()方法返回的hashCode值,依然是根據該物件的地址計算得到的hashCode值。所以,如果兩個物件的identityHashCode值相同,則兩個物件絕對是同一個物件;

public class TestIdentityHashCode
{
	public static void main(String[] args) 
	{
		//下面程式中s1和s2是兩個不同物件
		String s1 = new String("Hello");
		String s2 = new String("Hello");
		//String重寫了hashCode方法——改為根據字元序列計算hashCode值,
		//因為s1和s2的字元序列相同,所以它們的hashCode方法返回值相同
		System.out.println(s1.hashCode() + "----" + s2.hashCode());
		//s1和s2是不同的字串物件,所以它們的identityHashCode值不同
		System.out.println(System.identityHashCode(s1) + "----" + 
			System.identityHashCode(s2));
		String s3 = "Java";
		String s4 = "Java";
		//s3和s4是相同的字串物件,所以它們的identityHashCode值相同
		System.out.println(System.identityHashCode(s3) + "----" + 
			System.identityHashCode(s4));
	}
}
//輸出
69609650----69609650
366712642----1829164700
2018699554----2018699554

identityHashCode值可以唯一標識該物件,因為identityHashCode值是根據物件的地址計算得到的;

Runtime類

Runtime類代表Java程式的執行時環境,每個Java程式都有一個與之對應的Runtime例項。應用程式不能建立自己的Runtime例項,但可以通過getRuntime()方法獲取與之關聯的Runtime物件;

Runtime類代表Java程式的執行時環境,可以訪問JVM的相關資訊,如處理器數量、記憶體資訊等;

public class TestRuntime
{
	public static void main(String[] args) 
	{
		Runtime rt = Runtime.getRuntime();
		System.out.println("處理器數量:" + rt.availableProcessors());
		System.out.println("空閒記憶體數:" + rt.freeMemory());
		System.out.println("總記憶體數:" + rt.totalMemory());
		System.out.println("可用最大記憶體數:" + rt.maxMemory());
	}
}
//輸出
處理器數量:4
空閒記憶體數:126248328
總記憶體數:128974848
可用最大記憶體數:1883242496

除此之外,Runtime類還有一個功能------它可以直接單獨啟動一個程序來執行作業系統的命令:

public class TestExec
{
	public static void main(String[] args)throws Exception
	{
		Runtime rt = Runtime.getRuntime();
		//執行記事本程式
		rt.exec("notepad.exe");
	}
}

Runtime類提供了一系列exec()方法來執行作業系統命令;

BigDecimal類

float、double兩種基本浮點型別容易引起精度丟失,例如:

public class TestDouble
{
    public static void main(String args[])
	{
        System.out.println("0.05 + 0.01 = " + (0.05 + 0.01));
        System.out.println("1.0 - 0.42 = " + (1.0 - 0.42));
        System.out.println("4.015 * 100 = " + (4.015 * 100));
        System.out.println("123.3 / 100 = " + (123.3 / 100));
    }
}
//輸出
0.05 + 0.01 = 0.060000000000000005
1.0 - 0.42 = 0.5800000000000001
4.015 * 100 = 401.49999999999994
123.3 / 100 = 1.2329999999999999

執行結果表明,Java的double型別會發生精度丟失,尤其在進行算術運算時更容易發生;

為了能精確表示、計算浮點數,Java提供了BigDecimal類。

檢視BigDecimal類的BigDecimal(double val)構造器的詳細說明時,可以看到不推薦使用該構造器的說明,主要是因為使用該構造器時有一定的不可預知性。當程式使用BigDecimal(0.1)來建立一個BigDecimal物件時,它的值並不是0.1,它實際上等於一個近似0.1的數。這是因為0.1無法準確地表示為double浮點數,所以傳入BigDecimal構造器的值不會正好等於0.1(雖然表面上等於該值)。

如果使用BigDecimal(String val)構造器的結果是可預知的----寫入new BigDecimal(“0.1”)將建立一個BigDecimal,它正好等於預期的0.1。因此建議優先使用基於String的構造器;

如果必須使用double浮點數作為BigDecimal構造器的引數時,不要直接將該double浮點數作為構造器引數建立BigDecimal物件,而是應該通過BigDecimal.valueOf(double value)靜態方法來建立BigDecimal物件;

BigDecimal類提供了add()、subtract()、multiply()、divide()、pow()等方法對精確浮點數程序常規算術運算:

public class TestBigDecimal
{
	public static void main(String[] args) 
	{
		BigDecimal f1 = new BigDecimal("0.05");
		BigDecimal f2 = BigDecimal.valueOf(0.01);
		BigDecimal f3 = new BigDecimal(0.05);
		System.out.println("下面使用String作為BigDecimal構造器引數的計算結果:");
		System.out.println("0.05 + 0.01 = " + f1.add(f2));
		System.out.println("0.05 - 0.01 = " + f1.subtract(f2));
		System.out.println("0.05 * 0.01 = " + f1.multiply(f2));
		System.out.println("0.05 / 0.01 = " + f1.divide(f2));
		System.out.println("下面使用double作為BigDecimal構造器引數的計算結果:");
		System.out.println("0.05 + 0.01 = " + f3.add(f2));
		System.out.println("0.05 - 0.01 = " + f3.subtract(f2));
		System.out.println("0.05 * 0.01 = " + f3.multiply(f2));
		System.out.println("0.05 / 0.01 = " + f3.divide(f2));
	}
}
//輸出
下面使用String作為BigDecimal構造器引數的計算結果:
0.05 + 0.01 = 0.06
0.05 - 0.01 = 0.04
0.05 * 0.01 = 0.0005
0.05 / 0.01 = 5
下面使用double作為BigDecimal構造器引數的計算結果:
0.05 + 0.01 = 0.06000000000000000277555756156289135105907917022705078125
0.05 - 0.01 = 0.04000000000000000277555756156289135105907917022705078125
0.05 * 0.01 = 0.0005000000000000000277555756156289135105907917022705078125
0.05 / 0.01 = 5.000000000000000277555756156289135105907917022705078125

書籍:瘋狂Java講義
學習所做的筆記,特此記錄下來