第二篇:Java 基础语法:变量、数据类型、运算符与类型转换

学习 Java,首先要掌握的就是变量、数据类型、运算符和类型转换。这些内容看起来比较基础,但后面学习流程控制、数组、方法以及面向对象时都会频繁用到。

本文通过代码示例,对这几个知识点进行系统整理。

一、变量

1. 什么是变量

程序在运行过程中,经常需要临时保存一些数据,例如姓名、年龄、商品价格和考试成绩。

变量就是用来保存这些数据的。

Java 中声明变量的基本格式如下:

复制代码
数据类型 变量名 = 初始值;

例如:

复制代码
int age = 18;
double price = 29.9;
String name = "张三";

其中:

  • intdoubleString 是数据类型
  • agepricename 是变量名
  • 1829.9"张三" 是变量的值

变量也可以先声明,再赋值:

复制代码
int score;
score = 95;

System.out.println(score);

需要注意,局部变量在使用之前必须完成赋值。

下面的代码会编译失败:

复制代码
int score;
System.out.println(score);

因为此时 score 还没有确定的值。

2. 修改变量的值

变量中的数据可以发生变化:

复制代码
int age = 18;

age = 20;

System.out.println(age);

运行结果:

复制代码
20

第二次赋值会覆盖变量原来的值。

不过,变量的数据类型一旦确定,通常就不能保存其他类型的数据:

复制代码
int age = 18;

// age = "二十";
// 编译错误,int 类型不能保存字符串

3. 变量的命名规则

Java 中的变量名需要遵守以下规则:

  1. 可以由字母、数字、下划线和美元符号组成。
  2. 不能以数字开头。
  3. 不能使用 Java 关键字。
  4. 变量名区分大小写。
  5. 变量名中不能包含空格。
  6. 建议做到见名知意。

正确示例:

复制代码
int age;
int studentCount;
double productPrice;
String userName;

错误示例:

复制代码
// int 2age;
// 不能以数字开头

// int class;
// class 是 Java 关键字

// int user-name;
// 不能包含减号

Java 中的变量名通常使用小驼峰命名法。

小驼峰命名法的特点是:

  • 第一个单词的首字母小写
  • 后续单词的首字母大写

例如:

复制代码
String studentName;
int maxScore;
double orderAmount;

4. 变量的作用域

变量只能在它所在的大括号范围内使用,这个范围称为变量的作用域。

复制代码
public class VariableDemo {
    public static void main(String[] args) {
        int age = 18;

        if (age >= 18) {
            String message = "已经成年";
            System.out.println(message);
        }

        // System.out.println(message);
        // 编译错误,message 只能在 if 的大括号中使用
    }
}

在这个例子中,message 声明在 if 的大括号中,所以离开这个范围之后就不能继续使用。

5. 常量

如果一个变量初始化后不允许再次修改,可以使用 final 关键字。

复制代码
final double PI = 3.1415926;
final int MAX_COUNT = 100;

final 修饰的变量只能赋值一次:

复制代码
final int MAX_COUNT = 100;

// MAX_COUNT = 200;
// 编译错误,不能再次赋值

常量名通常全部使用大写字母,多个单词之间使用下划线连接。

复制代码
final int MAX_LOGIN_COUNT = 5;
final double DEFAULT_DISCOUNT = 0.9;

二、Java 中的数据类型

Java 是一门强类型语言,每个变量都需要明确自己的数据类型。

Java 中的数据类型主要分为两类:

  1. 基本数据类型
  2. 引用数据类型

三、基本数据类型

Java 一共有 8 种基本数据类型。

类型 占用空间 示例 主要用途
byte 1 字节 byte level = 10; 保存较小的整数
short 2 字节 short year = 2026; 保存短整数
int 4 字节 int age = 18; 保存常用整数
long 8 字节 long number = 100L; 保存较大的整数
float 4 字节 float height = 1.75F; 保存单精度小数
double 8 字节 double price = 19.99; 保存双精度小数
char 2 字节 char grade = 'A'; 保存单个字符
boolean 与具体实现有关 boolean result = true; 保存逻辑值

1. 整数类型

Java 中有 4 种整数类型:

  • byte
  • short
  • int
  • long

示例:

复制代码
byte level = 10;
short year = 2026;
int population = 100000;
long distance = 9999999999L;

日常开发中,整数一般优先使用 int。只有数据可能超出 int 的取值范围时,才考虑使用 long

整数默认是 int 类型。如果一个整数超过了 int 的取值范围,需要在数字末尾添加 L

复制代码
long population = 8_000_000_000L;

推荐使用大写 L,因为小写 l 和数字 1 比较相似,不容易分辨。

数字中间的下划线只用于提高可读性,不会影响数值:

复制代码
int money = 1_000_000;

System.out.println(money);

运行结果:

复制代码
1000000

2. 浮点类型

Java 中有两种浮点类型:

  • float
  • double

示例:

复制代码
float height = 1.75F;
double price = 199.99;

Java 中的小数字面量默认是 double 类型。

float 变量赋值时,需要在数字末尾添加 F

复制代码
float score = 95.5F;

下面的写法会编译失败:

复制代码
// float score = 95.5;
// 95.5 默认是 double 类型

在实际开发中,普通小数一般使用 double。不过,double 也存在精度问题:

复制代码
double result = 0.1 + 0.2;

System.out.println(result);

运行结果可能是:

复制代码
0.30000000000000004

因此,在计算商品价格、账户余额等数据时,不建议直接使用 floatdouble,可以使用 BigDecimal

复制代码
import java.math.BigDecimal;

public class BigDecimalDemo {
    public static void main(String[] args) {
        BigDecimal first = new BigDecimal("0.1");
        BigDecimal second = new BigDecimal("0.2");

        BigDecimal result = first.add(second);

        System.out.println(result);
    }
}

运行结果:

复制代码
0.3

创建 BigDecimal 时,建议传入字符串,避免把浮点数本身的误差带进去。传入的是字符串 "0.1",但 BigDecimal 内部会把它解析成高精度十进制数字,不是直接拿字符串做拼接!

3. 字符类型

char 用于保存单个字符,字符需要使用单引号。

复制代码
char letter = 'A';
char number = '8';
char chinese = '中';

char 只能保存一个字符:

复制代码
char grade = 'A';

// char name = '张三';
// 编译错误,包含了两个字符

需要区分字符和字符串:

复制代码
char letter = 'A';
String text = "A";

单引号表示字符,双引号表示字符串。

char 类型本质上保存的是字符对应的编码值,因此它可以参与整数运算:

复制代码
char letter = 'A';

System.out.println((int) letter);
System.out.println(letter + 1);

运行结果:

复制代码
65
66

4. 布尔类型

boolean 用来表示逻辑状态,只有两个值:

复制代码
boolean isLogin = true;
boolean isDeleted = false;

布尔类型经常用于条件判断:

复制代码
int age = 20;
boolean isAdult = age >= 18;

if (isAdult) {
    System.out.println("已经成年");
}

Java 中不能使用 01 代替布尔值:

复制代码
// boolean result = 1;
// 编译错误

这也是 Java 和部分编程语言之间的区别。

四、引用数据类型

除了 8 种基本数据类型之外,其他大部分类型都属于引用数据类型,例如:

  • 字符串
  • 数组
  • 接口
  • 枚举

示例:

复制代码
String name = "张三";
int[] scores = {90, 85, 100};
Object object = new Object();

引用类型可以赋值为 null

复制代码
String name = null;

null 表示当前变量没有指向任何对象。

基本数据类型不能直接赋值为 null

复制代码
// int age = null;
// 编译错误

五、算术运算符

算术运算符主要用于数学计算。

运算符 作用 示例
+ 加法 a + b
- 减法 a - b
* 乘法 a * b
/ 除法 a / b
% 取余 a % b

示例:

复制代码
int a = 10;
int b = 3;

System.out.println(a + b);
System.out.println(a - b);
System.out.println(a * b);
System.out.println(a / b);
System.out.println(a % b);

运行结果:

复制代码
13
7
30
3
1

1. 整数除法

两个整数相除,得到的结果仍然是整数,小数部分会被直接舍弃。

复制代码
int result = 10 / 3;

System.out.println(result);

运行结果:

复制代码
3

如果希望得到小数结果,至少要让其中一个操作数变成浮点数:

复制代码
double result = 10.0 / 3;

System.out.println(result);

也可以使用类型转换:

复制代码
int a = 10;
int b = 3;

double result = (double) a / b;

System.out.println(result);

2. 取余运算

% 用于计算两个数相除之后的余数。

复制代码
int result = 10 % 3;

System.out.println(result);

运行结果:

复制代码
1

取余运算经常用来判断奇数和偶数:

复制代码
int number = 10;

if (number % 2 == 0) {
    System.out.println("偶数");
} else {
    System.out.println("奇数");
}

六、自增和自减运算符

++ 表示变量加 1,-- 表示变量减 1。

复制代码
int number = 10;

number++;
System.out.println(number);

number--;
System.out.println(number);

运行结果:

复制代码
11
10

自增运算符放在变量前面和后面,单独使用时没有区别:

复制代码
int a = 10;
a++;

int b = 10;
++b;

如果参与表达式计算,执行顺序就不同了。

1. 前置自增

前置自增会先把变量加 1,再使用变量的值。

复制代码
int number = 10;
int result = ++number;

System.out.println(number);
System.out.println(result);

运行结果:

复制代码
11
11

2. 后置自增

后置自增会先使用变量原来的值,再把变量加 1。

复制代码
int number = 10;
int result = number++;

System.out.println(number);
System.out.println(result);

运行结果:

复制代码
11
10

实际开发中,不建议在一个复杂表达式里使用多个自增或自减运算符,否则代码很难阅读。

七、赋值运算符

最常见的赋值运算符是 =

复制代码
int age = 18;

Java 还提供了复合赋值运算符。

运算符 示例 说明
+= a += 2 加后赋值
-= a -= 2 减后赋值
*= a *= 2 乘后赋值
/= a /= 2 除后赋值
%= a %= 2 取余后赋值

示例:

复制代码
int number = 10;

number += 5;
System.out.println(number);

number *= 2;
System.out.println(number);

运行结果:

复制代码
15
30

复合赋值运算符会自动完成一次类型转换:

复制代码
short number = 10;
number += 1;

上面的代码可以正常编译。

但是下面的代码会编译失败:

复制代码
short number = 10;

// number = number + 1;
// 编译错误

原因是 short 参与算术运算时会被提升为 int,所以 number + 1 的结果是 int 类型,不能直接赋值给 short

number += 1 实际上相当于:

复制代码
number = (short) (number + 1);

八、比较运算符

比较运算符用于比较两个数据,计算结果一定是 boolean 类型。

运算符 作用
== 判断是否相等
!= 判断是否不相等
> 大于
< 小于
>= 大于或等于
<= 小于或等于

示例:

复制代码
int age = 18;

System.out.println(age == 18);
System.out.println(age != 18);
System.out.println(age > 16);
System.out.println(age <= 20);

运行结果:

复制代码
true
false
true
true

字符串不能直接使用双等号比较内容

对于基本数据类型,== 比较的是具体数值。

复制代码
int a = 10;
int b = 10;

System.out.println(a == b);

但是对于引用类型,== 比较的通常是两个变量是否指向同一个对象。

复制代码
String first = new String("Java");
String second = new String("Java");

System.out.println(first == second);
System.out.println(first.equals(second));

运行结果:

复制代码
false
true

比较字符串内容时,应使用 equals() 方法:

复制代码
String language = "Java";

if ("Java".equals(language)) {
    System.out.println("内容相同");
}

把确定不为 null 的字符串写在前面,还能避免空指针异常。

九、逻辑运算符

逻辑运算符用于连接多个条件。

运算符 作用
&& 逻辑与
|| 逻辑或
! 逻辑非

1. 逻辑与

&& 两边的条件都为 true,最终结果才是 true

复制代码
int age = 20;
boolean hasTicket = true;

boolean canEnter = age >= 18 && hasTicket;

System.out.println(canEnter);

运行结果:

复制代码
true

2. 逻辑或

|| 两边只要有一个条件为 true,最终结果就是 true

复制代码
boolean isMember = false;
boolean hasCoupon = true;

boolean canDiscount = isMember || hasCoupon;

System.out.println(canDiscount);

运行结果:

复制代码
true

3. 逻辑非

! 用于对布尔值取反。

复制代码
boolean isLogin = true;

System.out.println(!isLogin);

运行结果:

复制代码
false

4. 短路运算

&&|| 具有短路效果。

使用 && 时,如果左边已经是 false,右边不会继续执行:

复制代码
int number = 0;

boolean result = number != 0 && 10 / number > 1;

System.out.println(result);

因为 number != 0false,所以右边的除法不会执行,也就不会发生除零异常。

使用 || 时,如果左边已经是 true,右边也不会继续执行。

复制代码
int age = 20;

boolean result = age >= 18 || age++ > 30;

System.out.println(result);
System.out.println(age);

运行结果:

复制代码
true
20

由于左边已经是 true,所以右边的 age++ 没有执行。

十、三元运算符

三元运算符适合处理简单的二选一逻辑。

基本格式:

复制代码
条件 ? 条件成立时的结果 : 条件不成立时的结果

示例:

复制代码
int age = 20;

String message = age >= 18 ? "成年人" : "未成年人";

System.out.println(message);

还可以用它求两个数字中的较大值:

复制代码
int a = 10;
int b = 20;

int max = a > b ? a : b;

System.out.println(max);

如果判断逻辑比较复杂,建议使用 if-else,这样代码会更加清晰。

十一、字符串连接运算符

+ 的一边是字符串时,它的作用就不再是加法,而是拼接字符串。

复制代码
String name = "张三";
int age = 18;

System.out.println("姓名:" + name);
System.out.println("年龄:" + age);

需要注意表达式的计算顺序:

复制代码
System.out.println(10 + 20 + "Java");
System.out.println("Java" + 10 + 20);

运行结果:

复制代码
30Java
Java1020

Java 会按照从左到右的顺序进行计算。

第一行先计算 10 + 20,得到 30,然后再和字符串拼接。

第二行先得到 "Java10",后面的 20 也会继续进行字符串拼接。

如果想先进行加法,可以使用括号:

复制代码
System.out.println("计算结果:" + (10 + 20));

运行结果:

复制代码
计算结果:30

十二、运算符优先级

不同运算符的优先级不同。

复制代码
int result = 10 + 2 * 3;

System.out.println(result);

运行结果:

复制代码
16

乘法的优先级高于加法,所以先计算 2 * 3

如果希望先计算加法,可以添加括号:

复制代码
int result = (10 + 2) * 3;

System.out.println(result);

运行结果:

复制代码
36

实际编程时,如果一个表达式包含多种运算符,建议使用括号明确计算顺序。这样既方便自己阅读,也能减少理解错误。

十三、自动类型转换

当取值范围较小的数据类型转换为取值范围较大的数据类型时,Java 通常会自动完成转换。

常见的转换方向如下:

复制代码
byte -> short -> int -> long -> float -> double
                char -> int

示例:

复制代码
int number = 100;
long longNumber = number;
double doubleNumber = longNumber;

System.out.println(doubleNumber);

运行结果:

复制代码
100.0

完整示例:

复制代码
byte first = 10;
short second = first;
int third = second;
long fourth = third;
double fifth = fourth;

这种转换不需要手动添加类型,Java 会自动处理。

不过,自动类型转换并不代表绝对不会丢失精度。例如,将特别大的 long 转换为 floatdouble 时,仍然有可能出现精度损失。

十四、表达式中的类型提升

byteshortchar 在参与算术运算时,会自动提升为 int 类型。

复制代码
byte a = 10;
byte b = 20;

int result = a + b;

System.out.println(result);

下面的代码会编译失败:

复制代码
byte a = 10;
byte b = 20;

// byte result = a + b;
// 编译错误,a + b 的结果是 int

不同类型的数据一起运算时,结果通常会向取值范围更大的类型提升。

复制代码
int quantity = 3;
double price = 19.9;

double total = quantity * price;

System.out.println(total);

运行结果:

复制代码
59.699999999999996

这里也能看出浮点数存在精度问题。如果计算的是实际金额,应该使用 BigDecimal

十五、强制类型转换

当取值范围较大的类型转换为取值范围较小的类型时,需要使用强制类型转换。

基本格式:

复制代码
目标类型 变量名 = (目标类型) 原始数据;

示例:

复制代码
double price = 19.99;
int result = (int) price;

System.out.println(result);

运行结果:

复制代码
19

浮点数强制转换为整数时,小数部分会被直接舍弃,并不会进行四舍五入。

如果需要四舍五入,可以使用 Math.round()

复制代码
double number = 19.99;
long result = Math.round(number);

System.out.println(result);

运行结果:

复制代码
20

强制类型转换可能导致数据溢出

看下面的例子:

复制代码
int number = 130;
byte result = (byte) number;

System.out.println(result);

运行结果:

复制代码
-126

byte 的取值范围是 -128127,而 130 已经超出了这个范围,因此转换后的结果不是原来的数值。

所以,强制类型转换虽然能够通过编译,但不代表转换结果一定正确。

十六、字符串和基本类型之间的转换

实际开发中,从控制台、前端页面或配置文件中读取到的数据经常是字符串,因此需要掌握字符串和基本类型之间的转换。

1. 基本类型转换为字符串

可以使用 String.valueOf()

复制代码
int age = 18;
String ageText = String.valueOf(age);

System.out.println(ageText);

也可以通过字符串拼接完成:

复制代码
int age = 18;
String ageText = age + "";

两种方式都能实现转换,不过 String.valueOf() 的含义更加明确。

2. 字符串转换为整数

使用 Integer.parseInt()

复制代码
String text = "100";
int number = Integer.parseInt(text);

System.out.println(number + 20);

运行结果:

复制代码
120

3. 字符串转换为其他基本类型

复制代码
long longNumber = Long.parseLong("1000");
double price = Double.parseDouble("19.99");
float score = Float.parseFloat("95.5");
boolean result = Boolean.parseBoolean("true");

如果字符串不是合法的数字格式,程序会出现异常:

复制代码
String text = "Java";

// int number = Integer.parseInt(text);
// 运行时出现 NumberFormatException

可以使用 try-catch 处理这种情况:

复制代码
String text = "Java";

try {
    int number = Integer.parseInt(text);
    System.out.println(number);
} catch (NumberFormatException exception) {
    System.out.println("输入的内容不是有效整数");
}

十七、综合案例

下面通过一个简单的商品结算程序,把变量、数据类型、运算符和类型转换结合起来。

复制代码
public class OrderDemo {
    public static void main(String[] args) {
        String productName = "Java 入门教程";
        double unitPrice = 69.8;
        int quantity = 3;
        double discount = 0.9;

        double originalPrice = unitPrice * quantity;
        double finalPrice = originalPrice * discount;

        boolean freeShipping = finalPrice >= 99;

        System.out.println("商品名称:" + productName);
        System.out.println("购买数量:" + quantity);
        System.out.println("商品原价:" + originalPrice);
        System.out.println("优惠价格:" + finalPrice);
        System.out.println("是否包邮:" + (freeShipping ? "是" : "否"));
    }
}

运行结果:

复制代码
商品名称:Java 入门教程
购买数量:3
商品原价:209.39999999999998
优惠价格:188.45999999999998
是否包邮:是

由于 double 存在精度问题,商品金额更适合使用 BigDecimal

复制代码
import java.math.BigDecimal;
import java.math.RoundingMode;

public class OrderDemo {
    public static void main(String[] args) {
        String productName = "Java 入门教程";

        BigDecimal unitPrice = new BigDecimal("69.8");
        BigDecimal quantity = new BigDecimal("3");
        BigDecimal discount = new BigDecimal("0.9");

        BigDecimal originalPrice = unitPrice.multiply(quantity);

        BigDecimal finalPrice = originalPrice
                .multiply(discount)
                .setScale(2, RoundingMode.HALF_UP);

        boolean freeShipping =
                finalPrice.compareTo(new BigDecimal("99")) >= 0;

        System.out.println("商品名称:" + productName);
        System.out.println("商品原价:" + originalPrice);
        System.out.println("优惠价格:" + finalPrice);
        System.out.println("是否包邮:" + (freeShipping ? "是" : "否"));
    }
}

运行结果:

复制代码
商品名称:Java 入门教程
商品原价:209.4
优惠价格:188.46
是否包邮:是

十八、常见问题

1. 为什么两个整数相除没有小数

因为整数和整数运算,结果仍然是整数。

复制代码
double result = 10 / 3;

System.out.println(result);

虽然接收结果的是 double,但是 10 / 3 已经先完成了整数运算,所以结果是 3,最后才转换成 3.0

正确写法:

复制代码
double result = 10.0 / 3;

或者:

复制代码
double result = (double) 10 / 3;

2. 为什么两个 byte 相加不能赋值给 byte

因为 byteshortchar 参与算术运算时,会自动提升为 int

复制代码
byte a = 10;
byte b = 20;

int result = a + b;

3. 为什么不能使用双等号比较字符串内容

== 比较的是两个引用是否指向同一个对象,equals() 比较的才是字符串内容。

复制代码
String first = new String("Java");
String second = new String("Java");

System.out.println(first.equals(second));
相关推荐
Wang's Blog1 小时前
Java 项目实战: 外卖平台-后台退出功能与首页iframe架构
java·服务器·redis
Wang's Blog1 小时前
Java 项目实战: 外卖平台-软件开发流程与项目整体介绍
java·服务器·redis
她说..1 小时前
常见设计模式-模板方法模式
java·spring·设计模式·springboot
步行cgn1 小时前
BeanFactory 与 FactoryBean 的区别:面试深度解析
java·后端·spring
IT 行者1 小时前
JDK 27 正式发布:内存、安全、并发三路齐发
java
伍一514 小时前
hiprint-spring-boot打印组件介绍
java·hiprint
Wang's Blog9 小时前
Java 接入Redis: 服务启动停止与后台运行配置
java·服务器·redis
此时不提桶,更待何时10 小时前
01-04-B-垃圾回收面试与生产事故实战
java·jvm·面试