博客 / 詳情

返回

【Java 從入坑到放棄】No 3. 變量與數據類型

前情回顧

  1. No 1. 搭建 Java 開發環境
  2. No 2. 玩轉 IDEA

在之前的文章中,我們已經介紹瞭如何搭建 Java 開發環境以及如何使用 IDEA,現在就開始正式學習 Java 語言的相關語法吧!😎

本文內容預告如下:

  1. 變量
  2. 數據類型
  3. 變量作用域
  4. 常量

變量

什麼是變量?

所謂變量,就是用來命名一個數據的標識符,在 Java 中,變量又可以分為兩種:

  • 基本類型的變量
  • 引用類型的變量
// 基本類型的變量
int id = 1;
// 引用類型的變量
String name = "村雨遙";

其中 int 是基本數據類型,表示這是一個整型數;而 String 則是引用類型,表示這是一個引用類型;

idname 則是標識符,也就是我們所説的 變量

= 則是賦值操作符,而 1 則是基本類型的值,村雨遙 則是引用類型的值;

變量的特點

變量的最重要的一個特點就是可以重新賦值;

public class Main {
    public static void main(String[] args) {
        // 定義int類型變量id,並賦予初始值1
        int id = 1; 
        // 打印該變量的值,觀察是否為1
        System.out.println(id); 
         // 重新賦值為2
        id = 2; 
        // 打印該變量的值,觀察是否為2
        System.out.println(id); 
    }
}

變量命名規則

變量命名也是一門學問,並不是我們想怎麼命名就怎麼命名,日常開發中最常見的變量命名規則主要有如下幾條:

  1. 強制:變量命名只能使用 字母(大小寫均可)、數字、$、_
  2. 強制:變量名不能使用關鍵字(就是 Java 中內置的一些關鍵字,如 int、for、long…);
  3. 強制:變量第一個字符不能使用數字,只能用字母、$_
  4. 更多命名規則推薦參考阿里巴巴推出的《Java 開發手冊》,下載鏈接:https://github.com/cunyu1943/...

常見關鍵字

這是一種事先定義好的,有特定意義的標識符,也叫做保留字。對於 Java 編譯器有着特殊意義,用來表示一種數據類型,或者表示程序的結構等。此外,關鍵字不能用作變量名、方法名、類名、包名和參數名。常見的關鍵字可以分為如下幾類,具體的關鍵字如下圖所示:

  • 訪問控制類
  • 類、方法及變量修飾符類
  • 程序控制類
  • 錯誤處理
  • 包相關
  • 基本類型
  • 變量引用
  • 保留字

Java 關鍵字

數據類型

基本數據類型

Java 中,共有 8 中基本數據類型,由 Java 語言預定好的,每個數據類型都屬於關鍵字,而且每種基本變量都有其對應的封裝類,這 8 中基本數據類型分別是:

  • 整型(4 種)
  • 浮點型(2 種)
  • 字符型(1 種)
  • 布爾型(1 種)
數據類型 bit 字節 封裝類 數據範圍 默認值
byte 8 1 Byte $-2^7$ ~ $2^7-1$ 0
short 16 2 Short $-2^{15}$ ~ $2^{15}-1$ 0
char 16 2 Character \u0000 ~ \uffff($0$ ~ $65535$) u0000
int 32 4 Integer $-2^{31}$ ~ $2^{31}-1$ 0
long 64 8 Long $-2^{63}$ ~ $2^{63}-1$ 0L
float 32 4 Float $3.4e^{-45}$ ~ $1.4e^{38}$ 0.0f
double 64 8 Double $4.9e^{-324}$ ~ $1.8e^{308}$ 0.0D
boolean 1 不確定 Boolean truefalse false

注意:

  1. boolean 一般用 1 bit 來存儲,但是具體大小並未規定,JVM 在編譯期將 boolean 類型轉換為 int,此時 1 代表 true0 代表 false。此外,JVM 還指出 boolean 數組,但底層是通過 byte 數組來實現;
  2. 使用 long 類型時,需要在後邊加上 L,否則將其作為整型解析,可能會導致越界;
  3. 浮點數如果沒有明確指定 float 還是 double,統一按 double 處理;
  4. char 是用 單引號 '' 將內容括起來,只能存放一個字符,相當於一個整型值(ASCII 值),能夠參加表達式運算;而 String 是用 雙引號 "" 將內容括起來,代表的是一個地址值;
  5. Java 在內存中是採用 Unicode 表示,所以無論是一箇中文字符還是英文字符,都能用 char 來表示;

那麼如何個一個基本類型變量賦值呢?

在 Java 中,基本數據類型屬於 Java 的一種內置的特殊數據類型,不屬於任何類,所以可以直接對其進行賦值;給基本類型的變量賦值的方式就叫做 字面值

float score = 89.0f;
int age = 26;

引用數據類型

常見引用數據類型

數據類型 默認值
數組 null
null
接口 null

而對於引用數據類型,我們經常是需要 new 關鍵字來進行賦值,但是引用類型中的 接口是不能被實例化的,我們需要對其進行實現

// 初始化一個對象
Pet dog = new Pet();
// 初始化一個數組
int[] arr = new int[10];

String

對於引用數據類型中的 String,我們需要特別關注。

String 不同於 char,它屬於引用類型,而 char 屬於基本數據類型。用雙引號 "" 括起來表示字符串,一個字符串能夠保存 0 個到任意個字符,它一旦創建就不能被改變。

而針對字符串,如果我們要打印一些特殊的字符,比如字符串本來就包含 ",那麼這個時候就需要藉助於轉義字符 \,最常見的轉義字符主要有:

轉義字符 含義
\" 字符 "
\' 字符 '
\\ 字符 \
\n 換行符
\t 製表符 Tab
\r 回車符
那多個字符串之間或者字符串和其他類型數據之間,該如何進行連接呢?

Java 編譯器中,對於字符串和其他數據類型之間,可以使用 + 進行連接,編譯器會自動將其他數據類型自動轉換為字符串,然後再進行連接;

String 既然是不可變,那有什麼優點呢?
  1. 用於緩存 hash

由於 Stringhash 值被頻繁使用,它的不可變性使得 hash 值也不可變,此時只需要進行一次計算;

  1. 字符串常量池(String Pool)的需要

如果一個 String 對象已經被創建過,那麼就會優先從字符串常量池中獲取其引用,其不可變性確保了不同引用指向同一 String 對象;

  1. 安全性

我們經常用 String 作為我們方法的參數,其不變性能夠保證參數不可變;

  1. 線程安全

String 的不可變性讓它天生 具備線程安全,能夠在多個線程中方便使用而不用考慮線程安全問題。

String、StringBuilder、StringBuffer 對比,該如何選擇?
可變性 線程安全 適用場景
String 不可變 安全 操作少量的數據
StringBuffer 可變 安全,內部使用 synchronized 進行同步 多線程操作字符串緩衝區下操作大量數據
StringBuilder 可變 不安全 單線程操作字符串緩衝區下操作大量數據,性能高於 StringBuffer
通過 new String(“xxx”) 創建字符串的兩種情況?

使用 new 的方式創建字符串對象,會有兩種不同的情況:

  1. String Pool 中不存在 “xxx”

此時會創建兩個字符串對象,“xxx” 屬於字符串字面量,因此在編譯期會在 String Pool 中創建一個字符串對象,用於指向該字符串的字面量 “xxx”;然後 new 會在堆中創建一個字符串對象;

  1. String Pool 中存在 “xxx”

此時只需要創建一個字符串對象,由於 String Pool 中已經存在指向 “xxx” 的對象,所以直接在堆中創建一個字符串對象;

數據類型轉換

對於基本數據類型,不同類型之間是可以相互轉換的,但是需要滿足一定的條件;

從小到大自動轉,從大到小強制轉

即就是,對於低精度的數據類型,如果要轉換為高精度的數據類型,直接將低精度的值賦給高精度的值即可;

但對於高精度的數據類型,如果想要轉換為低精度的數據類型,則需要採用 強制轉換 的手段,但此時需要承擔精度丟失的風險,就像從一個大杯子往一個小杯子裏倒水,你要做好小杯子可能裝不下溢出的情況;

int a = 110;
long b = 113;
// 低精度轉高精度,由於 long 的範圍比 int 大,所以可以自動轉
b = a;
// 高精度住哪低精度,由於 long 的範圍比 int 大,所以需要強制轉
a = (int)b;

隱式轉換(自動類型轉換)

當滿足如下條件時,如果將一種類型的數據賦值給另一種數據類型變量時,將執行自動類型轉換:

  1. 兩種數據類型彼此兼容;
  2. 目標數據類型的取值範圍大於源數據類型;

一般而言,隱式轉換的規則是從低級類型數據轉換為高級類型數據,對應規則如下:

  • 數值類型byte -> short -> int -> long -> float -> double
  • 字符類型轉整型char -> int

顯式轉換(強制類型轉換)

那既然滿足上述兩個條件時會發生隱式轉換,那不滿足同時我們又想進行數據類型轉換時,我們該怎麼辦呢?

這個時候就需要我們的 顯式轉換 登場了,其語法格式如下:

(type) variableName;

我們舉個 🌰 來説下:

int num = 3;
double ans = 5.0;
// 要將 double 類型的值賦值給 int,則需要強制轉換
num = (int)ans;

注意:強制轉換可能會導致精度丟失,所以一般情況下儘量能不用就不用。

常見數據類型轉換方法

  1. 字符串與其他類型之間的轉換
  • 其他類型 -> 字符串
  1. 調用類的串轉換方法:X.toString()
  2. 自動轉換:"" + X
  3. 利用 String 的方法:String.valueOf(X)
// 方法 1
String str1 = Integer.toString(int num);
String str2 = Long.toString(long num);
String str3 = Float.toString(flaot num);
String str4 = Double.toString(double num);
// 方法 2
String str = "" + num ; // num 是 int、long、float、double 類型

// 方法 3
String str1 = String.valueOf(int num);
String str2 = String.valueOf(long num);
String str3 = String.valueOf(float num);
String str4 = String.valueOf(double num);
  • 字符串 - > 其他類型
  1. 調用 parseXXX 方法,比如 parseLong、parseFloat、parseDouble...
  2. 先調用 valueOf(),方法,然後再調用 xxxValue() 方法;
// 方法 1
int num1 = Integer.parseInt(String str);
Long num2 = Long.parseLong(String str);
Float num3 = Float.parseFloat(String str);
Double num4 = Double.parseDouble(String str);

// 方法 2
int num1 = Integer.valueOf(String str).intValue();
Long num2 = Long.valueOf(String str).longValue();
Float num1 = Float.valueOf(String str).floatValue();
Double num1 = Double.valueOf(String str).doubleValue();
  1. int、float、double 之間的轉換
  • float -> double
float num = 1.0f;
Float num1 = new Float(num);
double num2 = num1.doubleValue();
  • double -> float
double num = 100.0;
float num1 = (float)num;
  • double -> int
double num = 100.0;
Double num1 = new Double(num);
int num2 = num1.intValue();
  • int -> double
int num = 200;
double num1 = num;

變量作用域

我們已經學會了如何定義變量,也知道了使用各種數據類型來定義變量。但是還有一點不知道大家有沒有注意到,如果我們的定義變量在不同的位置,其作用是不是相同的呢?

這就涉及到變量的作用域,一般根據其作用域的不同,可以分為:

  • 成員變量:定義在方法體和語句塊外,不屬於任何一個方法,能在整個類中起作用;
  • 局部變量:定義在方法或方法體中的變量,作用域是其所在的代碼塊;

成員變量

成員變量又可以分為 全局變量(又叫實例變量)靜態變量(也叫類變量),兩者的區別如下:

名稱 修飾符 訪問方式 生命週期
全局變量 對象名.變量名 一旦對象被引用,則實例變量就存在
靜態變量 static 類名.變量名 同類共生死,只有當類被 GC 回收時才會被銷燬
public class Person {
    // 成員變量,全局變量
    String name; 
    // 成員變量,全局變量
    int age; 

    // 成員變量,靜態變量
    public static final String wechatPublic = "公眾號:村雨遙"; 
    // 成員變量,靜態變量
    public static final String website = "http://cunyu1943.site"; 
}

局部變量

成員變量指定義在方法或方法體中的變量,作用域是其所在的代碼塊,可以分為如下三種:

  • 形參
public class Main {
    // 方法中的參數
    public static void func(int num) {
        System.out.println("num = " + num);
    }

    public static void main(String[] args) {
        func(3);
    }
}
  • 方法內定義
public class Main {
    public static void main(String[] args) {
        int num = 10;
        if (num > 5) {
            // 聲明一個 int 類型的局部變量
            int tmp = 5; 
            System.out.println("tmp = " + tmp);
            System.out.println("num = " + num);
        }
        System.out.println("num = " + num);
    }
}
  • 代碼塊定義
public class Main {
    public static void func() {
        try {
            System.out.println("Hello!Exception!");
        } catch (Exception e) { // 異常處理塊,參數為 Exception 類型
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        func();
    }
}

常量

簡介

既然有變量,那就有與之相對的常量(也就是值是固定的,不能再變)。

常量又叫做字面常量,是通過數據直接來表示的,在程序運行過程中不能發生改變。通常我們把 Java 中用 final 關鍵字所修飾的成員變量叫做常量,它的值一旦給定就無法再進行改變!

分類

Java 中使用 final 關鍵字來聲明常量,其語法格式如下:

final 數據類型 常量名 = 常量初始值;
public class Main{
    public static void main(String[] args){
        // 聲明一個常量並賦值
        final int num = 1024;
        
        // 再次賦值,將導致編譯錯誤
        num = 1943;
        
        // 聲明一個常量但不賦值
        final int id;
        // 因為聲明時未賦值,所以可以進程初次賦值
        id = 1;
        // 常量已經賦值過了,再次賦值將導致編譯錯誤
        id = 2;
    }
}

常量可以分為如下 3 種類型:

  • 靜態常量final 之前用 public staic 修飾,表示該常量的作用域是全局的,我們不用創建對象就能夠訪問它。
  • 成員常量:類似於成員變量,但是最大的不同在於它不能被修改。
  • 局部常量:作用類似於局部變量,不同之處也在於不能修改。
public class Main{
    // 靜態變量
    public static final dobule PI = 3.14;
    
    // 成員常量
    final int num = 1024;
    
    public static void main(String[] args){
        // 局部變量
        final long count = 1000;
    }
}

PS:final 修飾變量後,該變量則變為常量。而 final 也還可以用來修飾類和方法,修飾方法時,表示這個方法不能被重寫(但可以重載);修飾類時,則表明該類無法被繼承。這些東西這時候你可能會覺得很陌生,不過等我們後續學習了面向對象之後,你就會發現其實很簡單。

總結

碼字不易,如果覺得對您有所幫助,可以點贊關注一波哦!🙏

博主水平有限,對於文中可能出現的錯誤,還請各位批評指正,來評論區一起聊天吧!

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.