5.[Java 基础]介绍数据类型


1. 数据类型分类

Java 是一种强类型的语言, 这意味着每个变量在编译时就有确定的类型, 变量类型限制了这个变量能被赋予的值, 并限制了在这个值上能进行的操作

强类型语言在编译时语法检查更严格, 减少了错误的出现, 强类型包含两个方面的含义:

  1. 所有的变量必须先声明, 后使用
  2. 不同的数据类型, 在内存中分配了不同大小的内存空间
  3. 指定类型的变量只能接受与之匹配的类型值

Java 语言支持的类型可分为两大类

分类 描述
基本数据类型
Primitive Type
基本数据类型包括 boolean类型和数值类型,
数值类型包括整型(byte, short, int, long, char) 和浮点类型( float, double)
引用数据类型
Reference Type
引用数据类型就是对一个对象的引用, 对象包括 对象数组 两种,
引用数据类型包括 , 接口, 数组, 空类型(null type)

空类型(null type) 就是 null 值的类型, null 类型没有名称, 所以不能声明一个 null类型的数据, 当对象引用为空的时候就是一个 null 类型, null (只能)可以转换为任何引用类型, 但是 null 类型不能转换为基本类型的数据.

2. 基本数据类型分类

Java 基本数据类型分为 Boolean 和 数值类型, 数值类型又分为 整型 和 浮点类型, 如下表所示:

分类1 分类2 分类3 字节数
数值类型 整型 byte 1 字节
数值类型 整型 short 2 字节
数值类型 整型 int 4 字节
数值类型 整型 long 8 字节
数值类型 浮点类型 float 4 字节
数值类型 浮点类型 double 8 字节
布尔类型 布尔类型 boolean 1 字节
字符类型 字符类型 char 2 字节

注意:这里并不包含 String 类型, 因为 String 并不是基本类型, 而是一个引用类型.

3. 整型

  • Java 各整数类型有固定的范围和字段长度, 不受具体操作系统的影响, 以保证 Java 程序的可以执行.
  • int 是最常使用的数据类型, 也是整型类型数据的默认类型
  • 如果直接将一个较小的值 ( 在byte 或 short 取值范围内) 直接赋值给一个 byte 或 short 类型的变量, 系统会自动将该值当成 byte 或 short 来处理.
  • 如果使用一个巨大的整数, 数值范围超过了 int 的取值范围, Java 并不会把该整数当成 long 处理, 如果希望将一个整数值当成 long 处理, 应该在这个数值后面增加 L 作为后缀.

整型包含以下 4 中基本数据类型

类型 大小 取值范围
byte 1 字节, 8 位 -128 ~ 127
$(-2^7)$ ~ $(2^7-1)$
short 2字节, 16 位 -32768 ~ 32767
$(-2^{15})$ ~ $(2^{15}-1)$
int 4 字节, 32 位 -2147483648 ~ 2147483647
$(-2^{31})$ ~ $(2^{31}-1)$
long 8 字节, 64 位 $(-2^{63})$ ~ $(2^{63}-1)$

位( bit): 是计算机中的最小存储单位

字节(byte): 计算机中最基本存储单元

1 byte = 8 bit

bit,byte,short 存储示例

// 定义变量时会自动将 100 当成 byte 类型处理
byte b1 = 100;

// 若将一个大于 byte取值范围的数值赋予给 byte 类型, 不会报错, 但是产生溢出导致数值异常
byte b2 = (byte)128;
System.out.println(b2); // -128

// 这是因为补码溢出
// 一个字节127是最大正数, 再加1就超过出了变成了-128,最小的负数,称补码溢出,这是补码的特性

// 定义变量时会会自动将 200 当成 short 类型处理
short s1 = 200;

// 若想把 99999999999999 赋值给 long 类型需要在末尾增加 L , 
// 否则会将该值作为 int处理,  但是已经超过 int 取值范围 所以会报错
long L1 = 99999999999999L;

4. 数值进制

4.1 进制介绍

进制就是进位制,是人们规定的一种进位方法。 对于任何一种进制—X进制,就表示某一位置上的数运算时是逢X进一位,二进制就是逢二进一,八进制是逢八进一,十进制是逢十进一,十六进制是逢十六进一。

Java进制分为二进制,八进制,十进制,十六进制, 但是计算机只能处理2进制的数据和指令。

进制 开头字母 说明
2 进制 0b 或 0B 由 0,1 组成,计算机底层都是以 2 进制保存的, Java 从 JDK7 开始增加对二进制的支持
8 进制 0 由 0~7 组成
10 进制 以非0数字 由 0~9 组成,整数默认为十进制。
16 进制 以 0x 或 0X 由 09 ,a,b,c,d,e,f 组成(af 不区分大小写)
  • 示例
// 定义一个十进制数 100
int a = 100;

// 定义一个 转十进制后为 100 的 二进制数(0B1100100 与 100相等 )
int b = 0B1100100;

// 定义一个 转十进制后为 100 的 八进制数(0B1100100 与 100相等 )
int c = 0144;

// 定义一个 转十进制后为 100 的 十六进制数(0B1100100 与 100相等 )
int d = 0X64;

4.2 进制码

在计算机内,有符号数有3种表示法:原码、反码和补码。所有数据的运算都是采用补码进行的。

进制码 说明
原码 就是二进制定点表示法,即最高位为符号位,“0”表示正,“1”表示负,其余位表示数值的大小。
反码 正数的反码与其原码相同;负数的反码是对其原码逐位取反,但符号位除外。
补码 正数的补码与其原码相同;负数的补码是在其反码的末位加1。

4.3 进制转换

  • 使用代码进制转换
  // 十进制转成八进制
  Integer.toOctalString(100)
  // 144

  // 十进制转成二进制
  Integer.toBinaryString(100)
  // 1100100

  // 十六进制转成十进制
  Integer.valueOf("64", 16).toString()
  // 100

  // 八进制转成十进制
  Integer.valueOf("144", 8).toString()
  // 100

  // 二进制转十进制
  Integer.valueOf("1100100", 2).toString()
  // 100

5. 字符型

5.1 字符类型介绍

  • 字符型通常用于标识单个字符, 字符型值必须使用单引号 ' ' 括起来, 比如 char c1='a';

  • Java 语言中, char 的本质是一个整数, 在输出时使用 16 位的 Unicode 字符集作为编码方式.

  • 可以直接给 char 赋值一个整数, 会按照对应的 Unicode 输出( 97 -> a )

  • char 类型是可以进行运算的, 相当于一个整数, 因为它有对应的 Unicode 码

  • 字符型存储到计算机中, 需要将字符对应的码值(整数)找出来, 比如 a ,

    • 存储 ‘a’ -> 码值 97 -> 二进制(1100001) ->存储
    • 读取: 二进制 ( 1100001 ) -> 97 -> ‘a’ -> 显示
  • 字符值有如下三种表示形式:

  1. 通过单个字符来指定字符值, 如: ‘a’, ‘b’, ‘1’, ‘2’ 等
  2. 通过转义字符表示特殊字符类型 如: ‘\n’, ‘ \t’ 等
  3. 直接用 Unicode 值来表示字符类型, 格式为: ‘\uXXXX’, 其中 XXXX 代表一个十六进制的整数.
  • 字符型也可以采用十六进制编码方式来表示, 范围是 \u0000 ~ \uFFFF 一共可以表示 65536个字符, 其中前 256 个 (\u0000 ~ \u00FF)字符和 ASCII 码中的字符完全吻合.
public class CharTest {
    public static void main(String[] args) {
        // 1. 指定单个字符作为字符值
        char c1 = 'a';
        System.out.println(c1); // a
        int i1 = c1;
        System.out.println(i1); // 97

        // 2. 使用 Unicode 编码值设定字符值
        char c2 = '\u8000';
        System.out.println(c2);

        // 3. 在 Java 中 char 本质是一个整数, 默认输出时, 是 Unicode 码对应的字符,
        // 定义 '好' 字符串
        char c3 = '好';
        System.out.println(c3); // 好
        // 要输出 char 对应的 int 型字符值 可以将 char 强转成 int 类型
        System.out.println((int)c3); // 22909

        // 4. char类型可以参与运算,相当于一个整数, 因为 char 都对应一个 Unicode 码
        System.out.println('a'+1); // 98

        char c4 = 'a'+1;
        System.out.println(c4); // b
        System.out.println((int)c4); // 98 -> 对应ASCII 码值
    }
}

5.2 常用编码格式

  • ASCII 码 介绍

ASCII 码是上世纪 60 年代, 美国制定的一套字符编码(使用一个字节), 为了统一了英文字符与二进制位之间的关系。

ASCII 码一共规定了 128 个字符编码, 只占用一个字节的后面 7 位, 最前面的 1 位统一规定是 0 。

ASCII 码表示了 128 个字符,而一个字节可以表示 256 个字符, 但是随着计算机的普及, ASCII 的缺点渐渐显露出来, 就是 ASCII 码不能表示所有字符。例如中文, 日文等字符, ASCII 码无法表示。

  • Unicode 编码介绍

Unicode 编码能够将世界上所有符号都纳入其中, 每一个符号都给予一个独一无二的编码, 使用 Unicode 编码几乎没有乱码的问题。

Unicode 编码中英文字母和中文字母都占用 2 个字节, 这对存储空间来说是一种浪费。

Unicode 编码最多可以表示 $2^{16}$ (65536)个字符。

Unicode 编码 0 -127 的字符与 ASCII 的编码是一样的, 比如 ‘a’ 在 ASCII 编码是0x61, 在 Unicode 编码是 ox0061, 对应都是 97, 因此 Unicode 编码兼容 ASCII 编码。

  • UTF-8 编码介绍

UTF-8 编码是在互联网上使用最广的一种编码, 它在 Unicode 编码的基础上做了一些改进.

UTF-8 编码是一种变长的编码方式, 他可是使用 1-6 个字节表示一个符号, 根据不同的符号而变化长度.

使用大小可变的编码, 字母占 1 字节, 汉字占 3 字节

5.3 转义字符

Java 中常用的转义字符如下表

转义字符 说明 Unicode 表示
\b 退格符 \u0008
\n 换行符 \u000a
\r 回车符 \u000d
\t 制表符 \u0009
\“ 双引号 \u0022
\‘ 单引号 \u0027
\\ 反斜线 \u005c
  • 测试转义字符
public class EscapeCharacter{
  public static void main(String[] args){

    // \b : 退格符
    System.out.println("hello world !\b");
    // 打印 : hello world

    // \t : 制表位,  实现对齐功能
    System.out.println("java\tc\tc++");
    //打印 : java    c    c++

    // \n : 换行符
    System.out.println("java\nc\nc++");
    // 打印
    // java
    // c
    // c++

    // \\ : 一个斜杠 \
    System.out.println("C:\\Hello.java");
    // 打印 :  C:\Hello.java 

    // \" : 一个双引号 "
    System.out.println("打印双引号 : \"");
    // 打印 : 打印双引号 : " 

    // \' : 一个单引号 '
    System.out.println("打印单引号 : \'");
    //打印 :  打印单引号 : '

    // \r : 一个回车
    // 回车之后会退到当前行的首位
    System.out.println("你好, Java\r哈喽");
    // 打印 : 哈喽, Java
    // \r 会退到该前行的首位,  然后输出哈喽,  所以替换掉了"你好",  输出 "哈喽, Java"
  }
}

6. 浮点型

Java 中浮点类型有两种: float, double

类型 占用存储空间 范围
单精度 float 4 个字节, 32 位 $(-3.403^{38})$ ~ $(3.403^{38})$
双精度 double 8 个字节, 64 位 $(-1.798^{308})$ ~ $(1.798^{308})$
  • 浮点数在机器中存放形式是 浮点数 = 符号位 + 指数位 + 尾数位

  • 尾数部分可能丢失, 造成精度损失, (小数都是近似值)

  • Java 浮点类型与整型类似, 也有固定的范围和字段长度, 不受具体的操作系统影响, float 是 4 个字节, double 是 8 个字节

  • 通常情况下应该使用 double 类型, 因为它比 float 更精确

  • Java 中浮点类型的数值默认为 double 类型, 如果希望把浮点类型当成一个 float 处理, 应该在浮点数值后紧跟 f, 例如 3.14 默认是double 类型, 占用 64 位空间, 3.14f 则是 float 类型, 占用 32 位空间

表明单精度和双精度精确的范围不一样,

单精度(即 float)在计算机中存储占用 4 字节,32位

双精度(即 double)在计算机中存储占用 8 字节,64位

精度格式说明

Java 中可以使用十进制和科学计数法两种形式表示浮点数:

  1. 十进制: 这种形式就是简单的浮点数表现形式, 比如 3.14, 5.98, 浮点数必须包含小数点, 否则会当成 int 类型处理。
  2. 科学计数法: 如: 3.14E2 = 3.14 ✖️ 10^2, 只有浮点类型才能用科学计数法表示, 55000 是 int 类型, 如果表示为 5.5 ✖️ 10^2 则是浮点类型。
  • Java 中还提供了三个特殊的浮点数值: 正无穷大, 负无穷大和非数, 用于标识溢出和出错.
  1. 正无穷大: 使用正整数 除以 0 将得到正无穷大, 通过 double 或 float 的 POSITIVE_INFINITY 表示.

  2. 负无穷大: 使用负整数 除以 0 将得到负无穷大, 通过 double 或 float 的 NEGATIVE_INFINITY 表示.

  3. 非数: 0.0 除以 0.0 (被除数的0需要为浮点数0.0, 如果被除数为整数0, 则会抛出 除以 0 异常), 或对一个负数开方将得到一个非数. 通过 double 或 float 的 Nan 表示.

  • 所有正无穷大都是相等的, 所有负无穷大也是相等的, 非数与任何数值都不相等, NaN 与 NaN 也不相等.
public class FloatTest {
    public static void main(String[] args) {
        float f1 = 3.14f; //若 3.14 后不加 f, 则会报类型不匹配的错误
        System.out.println(f1); // 3.14

        double d1 = 3.14;
        System.out.println(d1); // 3.14
        double d2 = 3.14F;
        System.out.println(d2); // 3.140000104904175

        // 当小数点前面只有一个 0 时, 0 可以省略
        double d3 = .123; // 等价与 0.123
        System.out.println(d3); //0.123

        double d4 =  123;
        System.out.println(d4); // 123.0

        // 定义 double 类型的整无穷大
        double d5 = Double.POSITIVE_INFINITY;
        // 定义 float 类型的整无穷大
        float f2 = Float.POSITIVE_INFINITY;

        System.out.println(d5 == f2); //true

        // 得到非数
        System.out.println(0.0 / 0.0); // NaN

        // 判断两个非数是否相等
        System.out.println((0.0 / 0.0) == (0.0 / 0.0)); // false

        // 通常情况下 double 会比 float 更加精确
        float f3  = 1.23456789123F;
        double d6 = 1.23456789123;
        System.out.println(f3); //1.2345679
        System.out.println(d6); //1.23456789123

        // 运算后得到的结果是小数时, 要考虑精度缺失问题
        double d7 = 3.3;
        double d8 = 9.9/3;
        System.out.println(d7); // 3.3
        System.out.println(d8); // 3.3000000000000003

        // 当数值位数很多时, 可以用下划线对数值进行分割, 更直观的分辨数值中到底包含多少位:
        double d9 = 1.23_456_789;
        System.out.println(d9);
    }
}

7. 布尔类型

  • Boolean 类型占 1 个字节

  • 布尔类型只有一个 Boolean 类型, 用于表示逻辑上的 , Boolean 类型的数值只能是 truefalse 不能用其他数值表示

  • Java 中不允许这样, 也就是说其他类型的数据也不能转换成 Boolean 类型。(C 语言中 可以使用整数 0 或非 0 代替 false 和 true)

  • 字符串 “true” 和 “false” 不能转换成 Boolean 类型, 如果一个 Boolean 类型和字符串进行连接, 则 Boolean 会自动转换成字符串类型.

  • Boolean 类型的值或变量主要用来进行流程控制, 在 Java 语言中使用 Boolean 类型的变量或值可控制的流程主要有以下几种 :

  1. if 条件控制

  2. while 循环控制

  3. do while 循环控制

  4. for 循环控制

  5. 三目运算符 ( ? : )

public class BooleanTest {
    public static void main(String[] args) {

        boolean b1 = true;
        System.out.println(b1);
        boolean b2 = false;
        System.out.println(b2);

        // Boolean 类型与 String 连接
        System.out.println("boolean:"+ b2);

        boolean b3 = false;
        if(b3){
            System.out.println( "b3 = true");
        }else{
            System.out.println( "b3 = false"); // 打印 b3 = false
        }
    }
}

8. 类型转换 (基本类型)

编写程序有时不同类型需要进行转换, Java 提供了 7 种数据类型可以相互转换, 有自动和强制类型转换两种方式:

  • 自动转换 : 将数据范围小的类型赋给数据范围大的类型

  • 强制转换 : 将数据范围大的类型赋给数据范围小的类型

8.1 自动类型转换

  1. 如果系统支持把某种基本类型的数值直接赋值给另一种基本类型的变量称为自动类型转换.

  2. 当 Java 程序在进行赋值或运算时, 精度小的类型自动转换精度大的类型, 这个就是自动类型转换

  3. 把任何基本类型的值和字符串进行连接运算时, 基本类型的值将自动转换为字符串类型.

  4. 如果想要把基本类型的值转换为对应的字符串, 可以使用该值与空字符串拼接.

  5. 有多种类型的数据混合计算时, 系统首先自动将所有数据转成容量最大的那种数据类型, 然后再进行计算.

  6. 当我们把精度大的数据赋值给精度小的数据时, 就会报错, 反之就会进行自行类型转换.

  7. 类型自动提升原则: 表达式结果的类型自动提升为操作数中最大的类型

类型自动转换图

  1. byte, short 和 char 之间不会自动进行相互转换
  2. byte, short 和 char 三种类型可以进行计算, 在计算式先将它们转为 int 类型
  3. boolean 类型不参与转换
  • 自动类型转换测试代码
public class AutomaticTypeConversion {
    public static void main(String[] args) {
        // 1. 单个类型的自动转换
        // 初始化 int 类型变量 a , 值为 10
        int a = 10;
        // int 自动类型转换为 long
        long b = a;
        // long 自动类型转换为 float
        float c = b;
        // float 自动类型转换为 double
        double d = c;
        System.out.println(d); // 10.0

        // 将 double 类型的数据与 String 进行拼接, 类型自动转换为 String
        String e = d + "";
        System.out.println(e.getClass());
        System.out.println(e); //10.0

        // 2. 多个类型计算时的自动转换

        //1. 有多种类型的数据混合时, 系统首先自动将所有数据转成容量最大的那种数据类型, 然后再进行计算.
        int i1 = 1;

        // float f1 = i1 + 1.1; // 错误, 1.1 为 double 类型, 结果类型是 double

        double d1 = i1 + 1.1; // 正确, 1.1 为 double 类型, 结果类型是 double

        float f1 = i1 + 1.1F; // 正确, 1.1 为 float 类型, 结果类型是 float 类型

        //2. 当我们把精度大的数据赋值给精度小的数据时, 就会报错, 反之就会进行自行类型转换.

        byte b1 = 10; // 正确,
        //3. (byte,short) 和 char 之间不会自动进行相互转换.
        // char c1 = b1; // 错误, byte 类型不能直接转为 char
        int i2 = 10;
        //byte b2 = i2; // 错误 , 如果是变量赋值会做类型判断, i2 是 int 类型, 不能给 byte

        //4. (byte,short) 和 char 三种类型可以进行计算, 在计算式先将它们转为 int 类型.

        byte b3 = 10;
        char c3 = 30;

        // byte b5 = b3 + c3; // 错误 , 结果为 int类型
        int i3 = b3 + c3; // 正确
    }
}

8.2 强制类型转换

  1. 强制类型转换是是将精度高的数据类型转为精度低的数据类型 ( 与自动类型转换相反 )
  2. 在使用强制类型转换时, 需要加上强制类型转换符圆括号 ()
  3. 强制类型转换可能会造成精度降低或溢出, 所以在做强制类型转换时需要注意这点
  4. 强转符号只针对最近的操作数有效, 往往会使用小括号提升优先级
  5. char 类型可以保存 int 常量值, 但是不能保存 int 的变量值, 需要强转
  6. byte,short 和 char 类型在进行运算时, 当做 int 类型处理
  7. 把浮点类型数据强制转换为整数类型时, 会截断浮点数的小数部分
  8. 如果转换数值超过了目标类型, 则会造成溢出, 所以当使用强制类型转换时, 需要注意数据精度与数据有小范围, 以免造成异常

如下图所示, 如果想要把范围大的数据类型转换为范围小的数据类型, 则需要进行强制类型转换.

强制类型转换

  • 强制类型转换代码示例1
public class ConvertTypeForced {
    public static void main(String[] args) {
        // 定义 Double 类型变量 a
        double a = 3.14;
        // double类型 强制转换为 float 类型
        float b = (float) a;
        // float 类型 强制转换为 long 类型
        long c = (long)b;

        System.out.println(c); // 3
        // // long 类型 强制转换为 int 类型
        int d = (int)c;

        // // int 类型 强制转换为 byte 类型
        byte e = (byte)d;
        System.out.println(e); //3
    }
}
  • 强制类型转换代码示例2
public class ConvertForce {
    public static void main(String[] args) {
        int i1 = (int) 1.9; // 1.9 默认是 double 类型, 需要使用类型强制转换
        System.out.println(i1); // 1, 将 double 类型强制转换为 int , 会造成精度丢失

        int i2 = 200;
        byte b1 = (byte) i2; // 将 int 类型强制转为 byte ,
        System.out.println(b1); // -56 , 当 int类型数值超过 byte 取值范围时, 会出现溢出情况

        // 强制类型转换符号只对最近的操作符有效, 如果对表达式进行类型强转需要将表达式括起来.
        //int i3 = (int)
        int i3 = (int) (1.9 + 1.8 + 1);
        System.out.println(i3); // 4

        // char 类型可以保存 int 常量值, 但是不能保存 int 的变量值, 需要强转
        char c1 = 100; // 正确
        int i4 = 10;
        // char c2 = i4; // 错误
        char c2 = (char) i4; // 正确

        short s1 = 10; // 正确
        // s1 = s1 - 9; //  错误, 结果为 int 类型
        s1 = (short)(s1 - 9); //  正确使用类型强转
    }
}

8.3 表达式类型的自动提升

当一个算术表达式包含多个基本类型的值时, 整个算术表达式的数据类型将发生自动提升.

类型自动提升的规则如下:

  1. 所有的 byte, short, 和 char 类型将被提升到 int 类型.
  2. 整个算术表达式的数据类型自动提升到表达式中最高的类型.
  • 类型提升
public class TypePromotion {
    public static void main(String[] args) {
        // 初始化 int 类型变量 a ,  值为 10
        int a = 10;
        // int 自动类型转换为 long
        long b = 20;
        // long 自动类型转换为 float
        float c = 3.1F;
        // float 自动类型转换为 double
        double d = 5.6;

        var result = a+b+c+d;
        System.out.println(result); // 38.699998474121095

        // 当两个 int 类型的数进行相除时,  即使不能除尽,  也会把小数省略,  只保存整数部分
        System.out.println(a/3); //3

        // 当表达式中有字符串类型时,  当把加号(+) 放进表达式时,  表示的是连接运算符,  而不是 加号
        System.out.println("hello"+7+9); //hello79
    }
}

8.4 基本类型和String的转换

通常情况下, 字符串不能直接转换为基本数据类型, 但是可以通过基本数据类型对应的包装类实现字符串转为基本类型, 如把字符串转为 int 类型

  1. 在将 String 类型转换成基本数据类型时, 要确保 String 类型能够转成有效的数据
  2. 比如可以把 “100” 转成 int 类型, 但是不能把 “hello”转成 int
  3. 如果格式不正确, 就会抛出异常, 程序就会终止
  • String 转基本类型示例
public class ConvertString2Basic {
    public static void main(String[] args) {

        // 1. 基本类型 -> String
        int i1 = 100;
        float f1 = 99.0F;
        boolean b1 = true;

        String s1 = i1+"";
        String s2 = f1+"";
        String s3 = b1+"";
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);

        // 2. String -> 基本类型 , 使用基本类型的包装类进行强制类型转换
        int i2 = Integer.parseInt(s1);
        float f2 = Float.parseFloat(s2);
        boolean b2 = Boolean.parseBoolean(s3);
        System.out.println(i2);
        System.out.println(f2);
        System.out.println(b2);

        // 3. String -> char
        String s4 = "hello";
        char c1 = s4.charAt(0); // 得到 s4 的第一个字符
        System.out.println(c1); // 'h'
    }
}

Java 提供了如下包装类型:

基本类型 包装类
byte Byte
short Short
int Integer
long Long
char Character
float Float
double Double
boolean Boolean

9. 变量

9.1 变量的介绍

  • 变量相当于内存中的一个数据空间的表示, 可以把变量看做是一个房间的门牌号码, 通过门牌号码就可以找到房间, 而通过变量名就可以访问到变量值.

  • 无论使用哪种高级程序语言编写程序, 变量都是组成程序的基本要素

  • Java 变量有三个要素 : 变量名称, 变量类型, 变量值

  • java 声明变量的基本步骤

public class Var{
  public static void main(String [] args){
    // 1. 声明变量
    int a;
    // 2. 给变量赋值
    a = 100;
    // 3. 使用变量
    System.out.println(a)

    // 变量声明与赋值通常一步完成
    int b = 100;
    // 使用变量
    System.out.println(b)
  }
}
  • 使用变量的注意事项
  1. 变量必须先声明后使用
  2. 定义变量时,既可以指定初始值, 也可以不指定初始值
  3. 根据变量的有效范围不同, 还可以使用不同的修饰符
  4. 变量在同一个作用域内不能重名
  5. 变量表示内存中的一个存储区域, 不同的类型的变量, 占用空间大小不同

9.2 使用 var 定义变量

为了简化局部变量的声明, Java10 开始支持 var 定义局部变量, var 相当于一个动态类型, 使用 var 定义的局部变量的类型由编译器自动推断, 定义变量时分配了什么初始值, 那么该该变量就是什么类型.

与弱类型语言中的 var 不同, Java 中的 var 初始化之后就确定了类型, 在使用 var 定义局部变量时, 必须在指定同时对变量进行初始化值, 否则编译器无法推断类型.

public class TypeInference {
    public static void main(String[] args) {
        var a = 10;
        // a 的默认类型是 int

        var b = 3.14;
        // b 的默认类型是 double

        // a =1.23;
        // 会报错,  类型不兼容,  无法将 double 类型的值赋值给 int 类型的 a

        // var c;
        // 会报错,  因为不进行初始化无法推断类型

        var d = "hello word";
        // d 被初始化成字符串,  所以 d 被推断成 String
    }
}

9.3 直接变量

直接量或字面值 (Literal value) 是指在程序中通过源码直接给出的值, 如 int a = 10; 为 a 分配的初始值 10 就是 literal value.

9.3.1 直接变量类型

并不是所有数据类型都可以指定为直接量, 能指定直接量的类型有三种: 基本数据类型, 字符串类型和 null.

Java 中支持如下 8 种类型的直接量

类型 直接量说明
char char 类型的直接量有三种形式, 单引号括起来的字符, 转义字符和 Unicode 值表示的字符.
int int 类型的直接量为在程序中直接给出的整数, 可分为二进制, 八进制, 十进制, 十六进制 4 种
long long 类型的直接量在整型后面添加 L , 就变成了 Long 类型的直接量
float float 类型的直接量就是在一个浮点数后添加 F, 这个浮点数可以是标准小数也可以是科学计数法的形式
double double 类型的直接量就是直接给出一个标准小数或者科学计数法形式的浮点数
boolean boolean类型的直接量只有 true 和 false
String String 类型的直接量是用双引号括起来的字符串
null null类型的直接量只有 null 值

9.3.2 直接变量赋值

把一个直接量赋值给对应类型的变量即直接变量赋值, Java 也允许把直接量赋给另一种变量, 但这种赋值必须是系统所支持的自动类型转换, 例如把 int 直接量赋值给 long 类型的变量.除此之外不同类型的赋值可能稍有差异:

  • String 类型的直接量不能赋给其他类型的变量,

  • null 类型的直接量可以直接赋值给任何引用类型的变量, 包括 String 类型

  • Boolean 类型的直接量只能赋值给 Boolean 类型的变量,

当一个程序第一次使用某个字符串直接变量时, Java 会使用常量池(constant pool) 来缓存该字符串直接量, 如果后面用到该字符串时 Java 会直接使用常量池中的字符串直接量.

Java 会确保每个字符串常量只有一个, 不会产生多个副本.

常量池是指在编译期被确定, 并被保存在已编译的 class 文件中的一些数据, 它包括 关于 类, 方法, 接口中的常量, 也包括字符串直接量

  • 直接变量代码示例
public class LiteralValue {
    public static void main(String[] args) {
        int a = 10;
        double b = 10.1;
        char c = 'c';

        String str1 = "hello";
        String str2 = "hello";
        String str3 = "hel"+""+"lo";

        System.out.println(str1 == str2); // true
        System.out.println(str3 == str2); // true
    }
}

文章作者: hnbian
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hnbian !
评论
 上一篇
6.[Java 基础]介绍运算符 6.[Java 基础]介绍运算符
1. 运算符介绍运算符是一种特殊的符号, 用以表示数据的运算, 赋值和比较等操作。 运算符分类 算术运算符 赋值运算符 关系运算符 ( 比较运算符 ) 逻辑运算符 三元运算符 位运算符 ( 需要二进制基础 ) 2. 算术运算符Ja
2018-01-16
下一篇 
4.[Java 基础]介绍关键字 4.[Java 基础]介绍关键字
1. Java 关键字分类Java 关键字分类如下表格所示: 修饰符 class abstract extends final impleme
2018-01-10
  目录