我的全棧之路-Java基礎之數據存儲

我的全棧之路-Java基礎之數據存儲

2.1 標識符

標識符是在程序開發時給包,類、接口、註解,變量,方法命名的字符序列。
標識符在命名時需要遵守相關的規則和規範:

標識符的命名規則:

  1. 標識符不能是Java的關鍵字和保留字,關鍵字是Java中被賦予賦予特殊含義的單詞,例如public static void等等。保留字是現有Java版本尚未使用,但是未來的Java版本可能會做關鍵字使用的單詞,例如goto,const。但是可以包含關鍵字,保留字。
  2. 標識符可以由字母、數字、下劃線組成,但是不能以數字開頭

日常開發中應該嚴格遵守標識符的命名規則,否則程序會出現編譯錯誤。

標識符的命名規範:

  1. 包名統一使用小寫,點分隔符之間有且僅有一個自然語義的英語單詞。包名統一使 用單數形式,但是類名如果有複數含義,類名可以使用複數形式。,例如com.taobao
  2. 類名單詞首字母大寫,多個單詞首字母也要大寫,例如HelloWorld
  3. 變量名、方法名首字母小寫,後面單詞首字母大寫,例如myName,testVarriable()
  4. 常量名單詞字母全部大寫,多個單詞使用下劃線隔開,例如ORDER_TYPE
  5. 雖然Java支持Unicode字符集,但是標識符不能是中文,同時禁止使用中英文混合命名,更不允許直接使用中文的命名方式,建議命名時見名知意。

由於軟件開發是團隊協作,標識符的命名規範不遵守不會出現錯誤,但是遵守標識符的命名規範可以提高程序的可讀性,便於後期維護,因此日常開發中也應該嚴格遵守。

package net.ittimeline.java.core.foundational.syntax; //包的命名

/**
 * Java標識符
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-22 16:21
 * @website www.ittimeline.net
 * @since JDK11
 */
public class IdentifierTest {


    public static void main(String[] args) {

        CustomerInfo customerInfo = new CustomerInfo();
        customerInfo.setCustomerName("tony");

        System.out.println("customerInfo name is " + customerInfo.getCustomerName());

        System.out.println("customerInfo id card id " + CustomerInfo.CUSTOMER_ID_CARD);


    }
}

/**
 * 類的命名
 */
class CustomerInfo {
    /**
     * 成員變量的命名
     */
    private String customerName;

    /**
     * 常量的命名
     */
    public static final String CUSTOMER_ID_CARD = "430904458902219877";


    /**
     * 方法的命名
     *
     * @return
     */
    public String getCustomerName() {
        return this.customerName;
    }

    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }


}

2.2 變量

2.2.1 變量的概述

變量代表內存的某個存儲區域,該區域的數據可以在同一類型之內隨着業務邏輯不斷髮生變化,例如銀行的利率,遊戲中人物的位置等等。
變量作爲最基本的存儲數據的單元,由變量名、變量類型和變量值組成。通過操作變量,就可以方便的操作內存中的數據。

2.2.2 變量的定義和使用

Java是強類型的語言,變量在定義時必須要明確變量的數據類型。變量定義的語法格式爲 數據類型 變量名=變量值;,數據類型可以是Java的基本數據類型和引用數據類型兩種。 變量名必須遵守標識符的命名規則和規範,=表示賦值,即將"="右邊的值賦值給左邊的變量,Java中的相等性使用"=="表示,變量的值可以是對應變量數據類型取值範圍內的值。例如 int age=28;

變量的定義也可以是先聲明,再進行賦值

//先聲明一個整數變量
int number; 
//將整數變量number賦值爲10
number=10;

變量定義後,Java會根據變量的數據類型在內存中開闢對應的空間存儲數據。

變量在使用前必須聲明並賦初始值,如果使用了未聲明的變量,程序會發生編譯錯誤,如果使用了未賦值的變量,程序會發生運行時錯誤。

package net.ittimeline.java.core.foundational.syntax;

/**
 * Java變量的使用
 * <p>
 * 變量的聲明格式
 * <p>
 * 變量類型 變量名=變量值;
 * 變量必須初始化賦值後才能使用
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-22 16:55
 * @website www.ittimeline.net
 * @since JDK11
 */
public class VarriableTest {


    public static void main(String[] args) {

        //變量的聲明賦值
        int age = 28;
        System.out.println("current age = " + age);

        //修改變量的值
        //同一時刻,變量只有一個值,新值會覆蓋舊值
        age = 29;
        System.out.println("next year age = " + age);

        //如果使用了未聲明的變量,會發生編譯錯誤
        //編譯時找不到變量name的聲明
        // System.out.println("my name is "+name);

        String name;

        //局部變量聲明之後還要初始化賦值才能使用
        //System.out.println("my name is "+name);
    }

}

在使用變量時,只能在定義時的作用域內使用。在同一個作用域下不能定義重複的變量名。

package net.ittimeline.java.core.foundational.syntax;

/**
 * 變量作用域測試
 *
 * @author liuguanglei [email protected]
 * @version 2019/9/2 16:38
 * @website ittimeline.net
 * @since JDK11
 */
public class VarriableScopeTest {

    public static void main(String[] args) {

        //這裏會發生編譯錯誤,因爲整數變量age在test方法中定義,只能在test方法中使用
        //  System.out.println(" my age is "+age);

    }

    public static void test() {
        int age = 28;
        //這裏會發生編譯錯誤,在同一個作用域下,不能定義重複的變量
     //   int age = 29;

    }
}

2.2.4 變量的分類

變量按照其作用域可以分爲局部變量、成員變量以及類變量。
在方法中聲明的變量叫做局部變量,作用域和生命週期從屬於方法

package net.ittimeline.java.core.foundational.syntax.variable;

/**
 * 局部變量的使用
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-26 10:39
 * @website www.ittimeline.net
 * @since JDK11
 */
public class LocalVariableTest {

    public static void main(String[] args) {

        {
            int age = 29;


        }

        //這裏無法使用代碼塊中的aqe變量,因爲age只能在{}作用域內訪問
        //System.out.println("age = "+age);

        int score = 100;

        System.out.println("score = " + score);
    }
}

成員變量是在方法外部、類中定義,並未使用static修飾的變量,成員變量的作用域和生命週期從屬於對象,
訪問成員變量時需要實例化對象,然後通過對象.成員變量名訪問。

package net.ittimeline.java.core.foundational.syntax.variable;

/**
 * 成員變量的使用
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-26 10:40
 * @website www.ittimeline.net
 * @since JDK11
 */
public class MemberVariableTest {

    /**
     * 方法外部,類中聲明兩個成員變量
     */
    String name;
    int age;

    public static void main(String[] args) {
        //實例化MemberVariableTest對象
        MemberVariableTest memberVariableTest = new MemberVariableTest();
        //通過對象的引用memberVariableTest.name訪問成員變量
        memberVariableTest.name = "tony";
        memberVariableTest.age = 29;

        System.out.println("name is " + memberVariableTest.name + " age is " + memberVariableTest.age);
    }
}

類變量是在方法外部、類中定義,使用static修飾的變量,作用域和生命週期從屬於類。訪問類變量通過類名.成員變量名。

package net.ittimeline.java.core.foundational.syntax.variable;

/**
 * 靜態變量的使用
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-26 10:40
 * @website www.ittimeline.net
 * @since JDK11
 */
public class StaticVarriableTest {


    public static void main(String[] args) {


        System.out.println(User.ID_CARD);

        //靜態變量可以直接由類名.變量名訪問
        System.out.println(User.remark);
    }
}


class User {

    static final String ID_CARD = "421023199302888588";

    /**
     * 靜態變量由Java負責初始化
     */
    static String remark;

}

成員變量和類變量由Java根據變量的負責初始化,局部變量由程序員手動初始化。

package net.ittimeline.java.core.foundational.object;

/**
 * Java成員變量的初始化機制
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-22 10:15
 * @website www.ittimeline.net
 * @since JDK11
 */
public class DefaultInitialization {

    char c;
    int i;

    DefaultInitialization() {

        System.out.println(" i = " + i);
        System.out.println(" c = [" + c + ']');
    }


    public static void main(String[] args) {

        DefaultInitialization defaultInitialization = new DefaultInitialization();

    }
}

2.2.5 變量的交換

在Java中,變量的交換有三種方式實現,分別是使用中間變量、算術運算以及異或運算三種方式實現。

package net.ittimeline.java.core.foundational.syntax.variable;

/**
 * 變量交換
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-26 10:17
 * @website www.ittimeline.net
 * @since JDK11
 */
public class VariableSwapTest {


    public static void main(String[] args) {

        int left = 5;
        int right = 10;


        //通過引入中間變量tmp實現變量的交換
        System.out.println("通過引入中間變量tmp實現變量的交換");
        System.out.println("交換變量之前");
        println(left, right);
        // tmp=5 left=5
        int tmp = left;
        //left=10,right=10
        left = right;
        right = tmp;

        System.out.println("交換變量之後");
        println(left, right);


        //通過算術運算+ -實現交換
        System.out.println("通過算術運算實現交換");
        left = 5;
        right = 10;
        System.out.println("交換變量之前");
        println(left, right);
        //left=15 right=10
        left = left + right;
        //right=5 left=15
        right = left - right;
        //left=10 right=5
        left = left - right;
        System.out.println("交換變量之後");
        println(left, right);


        //通過異或運算實現變量交換
        System.out.println("通過異或運算實現變量交換");
        left = 5;
        right = 10;
        System.out.println("交換之前");
        println(left, right);

        left = left ^ right;
        right = left ^ right;
        left = left ^ right;
        System.out.println("交換之後");
        println(left, right);


    }

    /**
     * 輸出left和變量的值
     *
     * @param left
     * @param right
     */
    public static void println(int left, int right) {
        System.out.println("left = " + left + " right = " + right);
    }


}



2.3 數據類型

在計算機底層數據都是使用二進制表示的,使用起來不太方便,因此引入數據類型的概念,數據類型用於對不同的數據進行分類,其原因在於

  • 不同的類型所能存儲的數據類型不同,
  • 不同表示的數據範圍(極限)也不同
  • 不同的數據類型 在內存中佔據的空間(字節數量)也不同
  • 不同的數據類型參與不同的運算。

Java的數據類型分爲基本數據類型(Primitive Type)和引用數據類型(Reference Type)兩大類,如下列表所示,目前只討論基本數據類型
Java數據類型

其中基本數據類型都有數組類型,數組就是一片連續的存儲空間。
而基本數據類型不具有面向對象的編程機制,也沒有對象的特性:沒有成員變量、方法可以被調用,因此Java八種基本數據類型對應的引用類型,也被稱爲包裝類,如下表格所示。

基本數據類型 byte short int float double boolean char
包裝類 Byte Short Integer Float Double Boolean Character

在日常開發中常用的基本類型有byte,int,long和boolean。

2.4 JDK1.5新特性 自動拆箱和裝箱

JDK1.5以後提供了自動拆箱和自動裝箱的特性實現了基本數據類型和包裝類的轉換。

自動拆箱:將引用數據類型(例如Long)轉換爲基本數據類型(例如long)
自動裝箱:將基本數據類型(例如byte)轉換爲引用數據類型(例如Byte)

package net.ittimeline.java.core.foundational.object;

/**
 * JDK5新特性:自動拆箱和自動裝箱
 * 自動拆箱:引用數據類型轉換爲基本數據類型
 * 自動裝箱:基本數據類型轉換爲引用數據類型

 * Java八種基本數據類型以及包裝類想換轉換

 * @author liuguanglei [email protected]
 * @create 2019-07-22 10:40
 * @website www.ittimeline.net
 * @since JDK11
 */
public class AutoboxingTest {


    public static void main(String[] args) {

        //自動裝箱
        Byte by = 1;
        //自動拆箱
        byte bt = by;
        System.out.println("byte = " + bt);

        Short sh = 1;
        short s = sh;
        System.out.println("short = " + s);

        Integer in = 1;
        int i = in;
        System.out.println("int = " + i);

        Long lo = 1L;
        long l = lo;
        System.out.println("long = " + l);

        Boolean bo = true;
        boolean b = bo;
        System.out.println("boolean = " + b);

        Character ch = 'x';
        char c = ch;
        System.out.println("char = " + c);

        Float fl = 1.0f;
        float f = fl;
        System.out.println("float = " + f);

        Double db = 1.0d;
        double d = db;
        System.out.println("double = " + d);
    }
}

2.5 整型

2.5.1 Java整型的極限

整型是日常生活中常用的類型,例如人的年齡,大樓的層數等等。
Java中的整型按照佔據不同內存大小,可以分爲byte,short,int,long四種類型。
其中整數默認是int類型,long類型的變量值需要加L後綴。
可以通過查看其包裝類Byte的源碼獲取其表示數據的範圍
Byte的表示範圍
以及Byte佔據的位數和字節數
Byte佔據的位數和字節數

其他類型可以使用同樣的方式通過查看包裝類的源碼獲取存儲數據的表示範圍以及佔據的字節帶小。

使用四種整數類型的包裝類獲取其對應的數據存儲範圍以及佔據的字節數量。

package net.ittimeline.java.core.foundational.syntax.type.integer;

/**
 * 整數的極限以及內存大小
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-26 12:59
 * @website www.ittimeline.net
 * @since JDK11
 */
public class IntegerLimitsTest {


    public static void main(String[] args) {

        //這裏的%d表示整數佔位符,會被對應的數值替換
        System.out.printf("byte所能存儲的最大值是%d,所能存儲的最小值是%d,佔據的字節數量是%d \n",Byte.MAX_VALUE,Byte.MIN_VALUE,Byte.BYTES);
        System.out.printf("short所能存儲的最大值是%d,所能存儲的最小值是%d,佔據的字節數量是%d \n",Short.MAX_VALUE,Short.MIN_VALUE,Short.BYTES);
        System.out.printf("int所能存儲的最大值是%d,所能存儲的最小值是%d,佔據的字節數量是%d \n",Integer.MAX_VALUE,Integer.MIN_VALUE,Integer.BYTES);
        System.out.printf("long所能存儲的最大值是%d,所能存儲的最小值是%d,佔據的字節數量是%d \n",Long.MAX_VALUE,Long.MIN_VALUE,Long.BYTES);
    }
}

在使用對應的數據類型時,需要注意不要超過其存儲的極限(即最大值和最小值),否則程序會發生錯誤。

2.5.2 大整數BigInteger

日常開發中使用的整數是byte,int,long以及對應的包裝類,整數默認是int,而long類型的常量值後面需要添加L後綴,如果想要使用比Long更大範圍的數據,可以使用java.math包中的BigInteger類。

package net.ittimeline.java.core.foundational.syntax.type.integer;

import java.math.BigInteger;

/**
 * Java
 * Java整型有byte short int long 四種類型,常用的有byte,int和long
 * 整數默認是int
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-22 18:54
 * @website www.ittimeline.net
 * @since JDK11
 */
public class IntegerTest {

    public static void main(String[] args) {

        byte bt=-128;
        System.out.println("bt = "+bt);
        //
        int INT_MAX_VALUE=Integer.MAX_VALUE;
        System.out.println("int max value  is "+INT_MAX_VALUE);
        //long類型的變量值如果超過了int的表示範圍,需要使用L後綴
        //全球人口數量
        long totalPopulation=76_0000_0000L;
        System.out.println("totalPopulation = "+totalPopulation);

        //如果想要表示宇宙的星球數量,假如是1萬億億 long類型也不能夠存儲
        //long starQuantity=1_0000_0000_0000_0000_0000L;

        //此時可以使用JDK提供的BigInteger來存儲大整數
        String starQuantityStr="100000000000000000000";
        BigInteger starQuantity=new BigInteger(starQuantityStr);
        System.out.println("starQuantity = "+starQuantity);

    }

}

2.5.3 整數的四種進制類型

在Java中,整數支持四種進制類型,分別是二進制、八進制、十進制和十六進制。其中JDK1.7以後支持二進制,以0b開頭,而八進制是以0開頭,十六進制是以0x開頭

package net.ittimeline.java.core.foundational.syntax.type.integer;

/**
 * 整數的四種進制類型
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-26 13:10
 * @website www.ittimeline.net
 * @since JDK11
 */
public class IntegerRadix {

    public static void main(String[] args) {

        byte binary=0b1100;
        System.out.println("二進制變量binary = "+binary);


        short oct=012;
        System.out.println("八進制進制變量oct = "+oct);


        int value=12;
        System.out.println("十進制變量value = "+value);

        long hex=0x12;
        System.out.println("十六進制變量hex = "+hex);
    }
}

在日常企業開發中基本使用的都是十進制的整數,但是在JDK源碼以及其他場景中中會使用到其他進制,
Integer類就使用了十六進制的常量來表示int的取值範圍。
int取值範圍表示

2.5.4 數值字面量使用下劃線

如果Java源文件中存在着很長的數字字面量(即變量值),不易閱讀,此時可以使用JDK7以後新增的特性:數值字面量使用下劃線來分割數值,使其更加容易閱讀。
我們可以在整數和浮點數的數值之間使用下劃線,編譯器在編譯時會刪除這些下劃線。

package net.ittimeline.java.core.foundational.syntax.type.integer;

/**
 * 數值字面量使用下劃線
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-26 14:51
 * @website www.ittimeline.net
 * @since JDK11
 */
public class IntegerFloatUnderScoreTest {
    public static void main(String[] args) {

        //很長的變量值,不容易閱讀
        long number=12000000000000L;
        //數值使用下劃線分割,更加容易閱讀,編譯器在編譯時會刪除下劃線
        System.out.println("number = "+ number);
        number=12_0000_0000_0000L;
        //因此在輸出number變量的值時不會看到下劃線
        System.out.println("number = "+ number);

        double value=3.1415_926;
        System.out.println("value = "+value);
    }
}

2.6 浮點型

2.6.1 浮點型的兩種表示方式

浮點數就是生活中常用的小數,例如銀行的利率,股市的漲跌等等都是浮點數。
Java中的浮點數類型分爲單精度浮點型float和雙精度浮點型double兩種,默認是double類型,如果想要使用float類型,變量值後面加上f後綴,浮點數可以使用十進制和科學計數法兩種表示方式。

package net.ittimeline.java.core.foundational.syntax.type.floats;

/**
 * Java浮點型
 * 數學意義上的小數就是浮點型
 * float和double是Java的兩種浮點類型
 * 浮點數默認是double,如果想使用float,變量值後面跟f後綴
 * <p>
 * 浮點數在進行運算時存在着誤差
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-22 19:21
 * @website www.ittimeline.net
 * @since JDK11
 */
public class FloatTest {

    public static void main(String[] args) {


        //float類型的變量值後面要加上f後綴,否則會出現編譯錯誤
        float flt = 12.0f;
        //浮點類型默認是double
        double dbl = 12.0;

        //使用科學計數法表示浮點數
        double value = 1.2e1;

        System.out.println("flt = " + flt);
        System.out.println("dbl = " + dbl);
        System.out.println("value = " + value);


        double source = 3.1415926;
        //3.1415926 等價於 31415926e-7
        double target = 31415926e-7;

        System.out.println("source =" + source);
        System.out.println("target =" + target);


    }

}

2.6.2 浮點型的極限以及存儲方式

float佔據四個字節(Byte),也就是32位(bit),double佔據八個字節(Byte),也就是64位,而由於浮點數的存儲機制和整數的不一樣,Java的浮點數準守IEEE754標準,採用二進制的科學計數法表示浮點數。
對於float,第一位是符號位,接下來八位表示指數,接下來23位表示尾數。
對於double,第一位是符號位,接下來11尾數表示指數,接下來52表示尾數。

float所能表示的最大值會比佔據8個字節的long都要大。

package net.ittimeline.java.core.foundational.syntax.type.floats;;

/**
 * 浮點類型的極限
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-26 15:09
 * @website www.ittimeline.net
 * @since JDK11
 */
public class FloatLimitsTest {

    public static void main(String[] args) {

        //這裏的%e表示整數佔位符,會被對應的科學計數法替換
        System.out.printf("float所能存儲的最大值是%e,所能存儲的最小值是%e,佔據的字節數量是%d \n",Float.MAX_VALUE,Float.MIN_VALUE,Float.BYTES);
        //使用科學計數法表示float最大值
        float floatMaxExponent=3.402823e+38f;
        //使用十進制小數表示float最大值
        Float floatMax=340282300000000000000000000000000000000f;

        System.out.println("floatMaxExponent = "+floatMaxExponent);
        System.out.println("floatMax = "+floatMax);

        //由於浮點數的存儲機制不同佔據四個字節的float表示的數據極限比佔據八個字節的Long還要大
        System.out.printf("long所能存儲的最大值是%d,所能存儲的最小值是%d,佔據的字節數量是%d \n",Long.MAX_VALUE,Long.MAX_VALUE,Long.BYTES);
        System.out.printf("double所能存儲的最大值是%e,所能存儲的最小值是%e,佔據的字節數量是%d \n",Double.MAX_VALUE,Double.MIN_VALUE,Double.BYTES);
    }
}

2.6.3 浮點數精度問題

單精度的float有效位數是7位,即小數點後能保留7位,第八位會進行四捨五入處理。
雙精度的double有效位數是16位,即小數點後保留16位,第十七位會進行四捨五入處理。

如果在使用float或者double的小數時,超過了有效位數進行相關的運算時會得到錯誤的結果。

package net.ittimeline.java.core.foundational.syntax.type.floats;;

/**
 * 浮點數運算的精度問題
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-26 15:13
 * @website www.ittimeline.net
 * @since JDK11
 */
public class FloatPrecisionTest {

    public static void main(String[] args) {


        float floatValue=1.123_456_789f;
        //輸出結果是1.1234568 1.123456789,小數點後截取7位,第8位會進行四捨五入
        System.out.println("floatValue = "+floatValue);

        double doubleValue=1.111_222_333_444_555_666_777;
        //輸出結果是1.1112223334445557  1.111222333444555666777,小數點後截取16位,第17位會進行四捨五入
        System.out.println("doubleValue = "+doubleValue);



        //浮點類型的數據在運算時運算結果會有誤差

        float floatSource=2.0f;
        //float類型的浮點數小數有效位數是7位
        float floatTarget=1.2_222_222f;
        //0.7777778
        float floatResult=floatSource-floatTarget;
        System.out.println("float source = "+floatSource);
        System.out.println("float target = "+floatTarget);
        //運算結果爲 0.7777778   因爲float的有效位數是7位
        System.out.println("float result = "+floatResult);

        //double類型的 2.0-1.1獲取的計算結果是錯誤的
        double doubleSource=2.0;
        double doubleTarget=1.1;
        double doubleResult=doubleSource-doubleTarget;
        System.out.println("double source = "+doubleSource);
        System.out.println("double target = "+doubleTarget);
        //運算結果爲 0.8_999_999_999_999_999   因爲double的有效位數是16位
        System.out.println("double result = "+doubleResult);


        //如果數據超過了有效位數,在進行相關運算時(例如這裏的關係運算:相等)也會得到錯誤的結果
        double source=1.000_000_000_000_000_001;
        double target =1.000_000_000_000_000_002;

        System.out.println("source == target ? "+(source==target));

    }
}

如果想要獲取更高的精度,例如金融計算的業務場景中,會使用到更高精度,此時可以使用java.math包中的BigDecimal來完成。

package net.ittimeline.java.core.foundational.syntax.type;

import java.math.BigDecimal;

/**
 * 無損精度計算
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-26 16:37
 * @website www.ittimeline.net
 * @since JDK11
 */
public class BigDecimalTest {


    public static void main(String[] args) {

        //使用字符串構建BigDecimal對象
        BigDecimal sourceBigDecimal = new BigDecimal("2.0");
        BigDecimal targetTargetDecimal = new BigDecimal("1.1");
        //調用BigDecimal提供的subtract方法實現減法運算 解決了浮點數double計算的精度問題
        BigDecimal resultBigDecimal = sourceBigDecimal.subtract(targetTargetDecimal);
        System.out.println("resultBigDecimal = " + resultBigDecimal);


        double source=1.000_000_000_000_000_001;
        double target =1.000_000_000_000_000_002;

        BigDecimal doubleSourceBigDecimal=new BigDecimal(source);
        BigDecimal doubleTargetBigDecimal=new BigDecimal(target);
        /**
         *         使用BigDecimal對象提供的equals方法判斷是否相等 這裏的結果是true
         *         在使用BigDecimal時不能使用double構造BigDecimal對象,否則會得到錯誤的結果
         */
        System.out.println("doubleSource equals  doubleTarget ?  "+doubleSourceBigDecimal.equals(doubleTargetBigDecimal));



        //將上面的數字轉換爲字符串之後就能獲取精確的運算結果
        String sourceStr="1.000000000000000001";
        String targetStr="1.000000000000000002";
        //只能使用String構造BigDecimal才能獲取精確的運算結果
        BigDecimal strSourceBigDecimal=new BigDecimal(sourceStr);
        BigDecimal strTargetBigDecimal=new BigDecimal(targetStr);

        System.out.println("strSource equals  strTarget ?  "+strSourceBigDecimal.equals(strTargetBigDecimal));

    }
}

2.7 布爾型

布爾類型只有boolean一個類型,而且其取值只能是true或則false。在日常開中boolean常常和關係、邏輯運算以及條件判斷語句一起使用。

package net.ittimeline.java.core.foundational.syntax.type;

/**
 * 布爾型
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-26 10:15
 * @website www.ittimeline.net
 * @since JDK11
 */
public class BooleanTest {

    public static void main(String[] args) {



        //產生2個0-1之間的隨機小數
        double source=Math.random();
        double target=Math.random();

        System.out.println("source = "+source);
        System.out.println("target = "+target);
        // >就是關係運算
        boolean result=source>target;
        System.out.println("result = "+result);
        //這裏等價於result==true
        if(result){
            System.out.println("source > target");
        }else{
            System.out.println("source < target");
        }
    }
}

2.8 字符型

Java中的字符使用char表示,用於存儲單個字符,字符型的變量值使用''包含。
由於Java使用16位的Unicode作爲編碼方式,而Unicode是國際組織制定的可以容納世界上所有文字和符號的字符編碼方案,因此Java程序支持各種語言的字符。

除此以外char還能使用Unicode表示字符,由於其佔據2個字節空間大小,其表示範圍是\u0000 - \uFFFF。在日常開發中還會使用到一些常用的轉義字符,例如實現換行的\n以及實現路徑轉義的\等等。

字符在計算機底層都是以數字的方式存儲的,例如字符'a'底層的數字是97,'A'底層的數字是65,字符'0'的底層數字是48,然後依次遞增。

package net.ittimeline.java.core.foundational.syntax.type;

/**
 * 字符型
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-26 10:15
 * @website www.ittimeline.net
 * @since JDK11
 */
public class CharacterTest {

    public static void main(String[] args) {

        //Java支持Unicode標準,可以存儲世界上所有國家的語言文字
        //英文
        char english='L';
        //中文
        char chinese='劉';
        //日文
        char japan='お';
        //韓文
        char korean='안';

        System.out.println("english = "+english);
        System.out.println("chinese = "+chinese);
        System.out.println("japan = "+japan);
        System.out.println("korean = "+korean);

        char A='\u0041';
        //大寫字母A對應的數字是65
        System.out.println("unicode \\u0041 對應的字符是 = "+A);
        char a='\u0061';
        //小寫的字母a對應的數字是97
        System.out.println("unicode \\u0061對應的字符是 = "+a);
        //字符0對應的數字是48
        char zero='\u0030';
        System.out.println("unicode \\u002F對應的字符是"+zero);



        char newLine='\n';
        System.out.print("hello"+newLine+"world");

        char path='\\';
        System.out.println("path = "+path);

    }
}

2.9 數據類型轉換

2.9.1 數據類型自動轉換

Java中的八種基本數據類型除了boolean之外,在進行算術運算時,會按照如下的規則進行自動類型轉換。

byte,short,char->int->long->float->double

當byte,short,char三種類型的變量運算時結果類型爲int

  • byte和byte運算的結果類型是int
  • byte和short運算的結果類型是int
  • byte和char運算的結果類型是int
  • char和char運算的結果類型是int
  • char和short運算的結果類型是int
  • int和int運算的結果類型是int
  • byte,short,int,long和float運算結果類型是float
  • byte,short,int,long,float和double運算結果類型是double

即表示範圍小的變量會自動提升爲表示範圍大的變量,這裏的表示範圍指的是數據類型對應的取值範圍,而不是數據類型佔用的內存空間,例如float取值範圍要大於long的取值範圍。

自動類型轉換可以在一定程度上避免進行運算的時候結果超過數據類型的極限而造成程序錯誤。

package net.ittimeline.java.core.foundational.syntax.convert;

/**
 * 自動類型轉換
 * 八種基本數據類型除了boolean之外在進行運算時會進行自動類型轉換
 *
 * 在進行運算時,容量小的數據類型的變量與容量大的大數據類型的變量做運算時,結果自動提升爲容量大的數據類型,防止運算時超過極限值。
 * 此時容量大小指的是,數據類型表示數的範圍大小,而不是佔用內存大小,比如float容量大於long的容量
 * byte -> short-> int-> long-> float ->double
 * byte,short,char->int->long->float->double
 *
 * byte、short、char運算後的結果類型必須是int
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-27 08:53
 * @website www.ittimeline.net
 * @since JDK11
 */
public class AutoConvert {
    public static void main(String[] args) {

        //byte和int運算的結果是int
        byte byteVal=12;
        int intVal=12;
        //如果用byte存儲運算結果,會編譯失敗
        int intResult=byteVal+intVal;
        System.out.println("intResult = "+intResult);


        float floatResult=byteVal+intVal;
        System.out.println("floatResult = "+floatResult);

        //容量小的變量值自動轉換爲容量大的變量
        short  shortVal=12;
        double dblValue=shortVal;


        char ch='a';
        int intNewValue=123;
        int intNewResult=ch+intNewValue;
        System.out.println("intNewResult = "+intNewResult);


         byte sourceByte=12;
         char targetChar=12;
         int  resultInt=sourceByte+targetChar;


        //short和char運算結果類型是int
        short shortNewVal=29;
        char newChar='b';
        int result=shortNewVal+newChar;

        // byte和byte運算也是int
        byte source=12;
        byte target=12;
        int sourceTarget=source+target;
        System.out.println("sourceTarget = "+sourceTarget);


        //int
        int maxTarget=Integer.MAX_VALUE;
        int maxSource=Integer.MAX_VALUE;

        //這裏已經超出了int表示的最大值,因此輸出的結果是錯誤的
        int maxResult=maxSource+maxTarget;
        System.out.println("maxResult = "+maxResult);

    }
}

2.9.2 數據類型強制類型轉換

而在某些應用場景下我們還可能會使用到強制類型轉換,例如數據庫查詢返回的結果是long類型,但是需要強制轉換爲int類型。
強制類型轉換是自動類型轉換的逆運算,使用強轉符()實現,如果強轉的變量超過目標類型的最大值會損失精度。

package net.ittimeline.java.core.foundational.syntax.convert;

/**
 * 強制類型轉換
 * 強制類型轉換是自動類型轉換的逆運算
 * 需要使用強轉符:()
 * 強制類型轉換可能會丟失精度
 * @author liuguanglei [email protected]
 * @create 2019-07-27 09:08
 * @website www.ittimeline.net
 * @since JDK11
 */
public class NarrowConvert {


    public static void main(String[] args) {

        double dblVal=12.8;
        System.out.println("dblVal = "+dblVal);
        //強制類型轉換 (強轉類型)
        int intVal=(int)dblVal;
        //強制轉換可能會損失精度
        System.out.println("intVal = "+intVal);

        //如果轉換的變量值(例如這裏的12)在強制轉換類型的表示範圍之內(例如這裏的byte)則不會損失精度
        long longVal=12;
        byte byteVal=(byte)longVal;
        System.out.println("longVal = "+longVal+ " byteVal = "+byteVal);


        int sourceVal=128;
        byte targetVal=(byte)sourceVal;

        //這裏會損失精度,因爲128已經超過了byte存儲的最大值
        System.out.println("sourceVal = "+sourceVal+ " targetVal = "+targetVal);



    }
}

在給變量賦值時,如果變量的值沒有超過變量類型的極限,賦值時也會發送自動類型轉換,但是如果賦值時變量的值超過了變量類型的極限,那麼此時就需要使用到強制類型轉換實現。

package net.ittimeline.java.core.foundational.syntax.convert;

/**
 * 類型轉換的特殊情況
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-27 09:18
 * @website www.ittimeline.net
 * @since JDK11
 */
public class ConvertFeature {

    public static void main(String[] args) {
        //整型常量默認爲int,浮點常量默認爲double


        //雖然long類型的變量值必須加上L後綴,但是這裏的123就是int,這裏實際上就是發生了自動類型轉換
        long longSourceVal=123;

        System.out.println("int max"+Integer.MAX_VALUE);
        // 因爲2147483648超過了int表示的最大值,所以這裏必須加上L後綴
        long bigSource=2147483648L;
        System.out.println(" bigLongSource = "+bigSource);



        //3.14默認是double類型,在賦值是必須使用強制類型轉換
        //因爲將表示範圍大的值賦值給表示範圍小的變量必須強制類型轉換
        float fltVal= (float) 3.14;

        //整型默認的是int類型
        byte byteVal=12;
        int result=byteVal+1;

        //浮點型默認是double
        double dblVal=12.3+byteVal;
        System.out.println("dblVal = "+dblVal);



    }
}

2.10 String

2.10.1 字符串變量

日常開發中最常用的數據類型是String,它用於存儲字符串,使用" "包含起來,String位於java.lang包下,屬於引用類型的一種,底層是字符數組。

String類型變量的定義以及與char類型的比較

package net.ittimeline.java.core.foundational.syntax.type;

/**
 * 字符串變量
 * <p>
 * String用於存儲字符串(多個字符),屬於引用數據類型
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-27 09:22
 * @website www.ittimeline.net
 * @since JDK11
 */
public class StringTest {

    public static void main(String[] args) {
        //String類型的變量定義 變量值使用""包含
        String str = "Hello World";

        String charConent = "c";
        System.out.println("charContent = " + charConent);

        //空字符
        char emptyC = ' ';
        System.out.println("emptyC= [" + emptyC + "]");
        //空字符串
        String emptyStr = " ";
        System.out.println("emptyStr= [" + emptyStr + "]");
    }
}

2.10.2 字符串連接

String可以和八種基本數據類型使用加號(+)做連接運算,運算的結果類型是String。
String類型與基本數據類型的連接運算,如果加號前後有String類型的變量,那麼此時的加號就是表示連接,如果+前後沒有String,此時的加號表示算術運算的加法。

package net.ittimeline.java.core.foundational.syntax.type;

/**
 * 字符串與八種基本數據類型的運算
 * 字符串可以和八種基本數據類型進行連接運算,使用+表示連接,運算的結果類型是String類型
 * +符號前後有String表示連接,沒有String表示算術運算的加法
 *
 * @author liuguanglei [email protected]
 * @create 2019-07-27 09:29
 * @website www.ittimeline.net
 * @since JDK11
 */
public class StringOperatorTest {
    public static void main(String[] args) {

        String info="";
        int age=18;
        String name="劉光磊";
        double height=176.0;
        boolean isMarry=false;
        long id=362352355643454356L;

        info="id : "+id+"姓名:"+name+"\n年齡:"+age+"\n身高:"+height+"\n是否已婚"+isMarry;
        System.out.println("******個人信息******");
        System.out.println(info);


        //判斷+表示字符串連接還是算術運算的加法
        char charVal='a';
        int number=10;
        String str="hello";
        //第一個加法前後都不是String,因此表示加法,而不是字符串連接,而a表示97,第二個加法後面是String,因此表示字符串連接
        //最後的運算結果是107hello
        System.out.println(charVal+number+str);
        //第一個加法後面是String,運算結果是ahello10
        System.out.println(charVal+str+number);
        //第一個加法後面是String,運算結果是ahello10
        System.out.println(charVal+(str+number));
        //第一個加法前後都不是String,因此加號表示算術運算符的加法運算,最後的運算結果是107hello
        System.out.println((charVal+number)+str);

        String star="*";
        char tab='\t';
        String content=star+tab+star;
        System.out.println("content ="+content);

    }

}

2.11 數據在內存中的存儲方式

數據在內存中有三種表現方式:原碼、反碼和補碼
數據在內存中都是以二進制的補碼存儲,在理解補碼之前首先得理解原碼以及反碼。

原碼就是一個數據本身的二進制表現形式,而數值可以分爲有符號和無符號兩種。
有符號數其二進制表示最高位(最左邊)是符號位,1表示負數,0表示正數。

  • 例如無符號數15的原碼使用一個字節表示爲0000 1111
  • 例如有符號15的原碼使用一個字節表示爲0000 1111
  • 例如有符號-15的原碼使用一個字節表示爲1000 1111

反碼
無符號數的反碼等於原碼
例如無符號數15的反碼等於原碼,即無符號數15的反碼用一個字節表示爲0000 1111

有符號數正數的反碼也等於原碼
例如有符號正數15的反碼等於原碼,即有符號數15的反碼用一個字節表示爲0000 1111

有符號負數的反碼是原碼最高位不變,其他位取反
例如有符號負數-15的反碼是原碼最高位不變,其他位取反用一個字節表示爲1111 0000

補碼
無符號數的補碼等於反碼
例如無符號數15的補碼等於反碼,即無符號數15的補碼使用一個字節表示爲0000 1111

有符號正數的補碼等於反碼
例如有符號正數15的補碼等於反碼,即有符號正數15的補碼使用一個字節表示爲0000 1111

有符號負數的補碼等於反碼加1
例如有符號負數-15的補碼等於反碼1111 0000加1,即有符號負數15的補碼使用一個字節表示爲11111 0001

數值 是否有符號 原碼 反碼 補碼
15 0000 1111 0000 1111 0000 1111
15 0000 1111 0000 1111 0000 1111
-15 1000 1111 1111 0000 1111 0001

無符號數以及有符號正數,計算機存儲的是原碼,因爲原碼等於反碼
有符號負數計算機存儲的是補碼,補碼等於原碼取反加1,原碼等於補碼取反加1。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章