三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Java 常用语法极简通关(二):八种基本类型与 String——Java 类型世界的两大阵营

Java 常用语法极简通关(二):八种基本类型与 String——Java 类型世界的两大阵营

开篇:一个"物资采购结算"的小程序

第一章我们看到了 Java 程序的骨架,这一章往里走,看看装数据的"容器"——类型。还是老规矩,先看一段活的代码:煤矿物资采购的结算程序,算出各种物料的金额并汇总。

public class PurchaseApp { public static void main(String[] args) { // 物料1:锚杆 String itemName1 = "锚杆"; int quantity1 = 1200; // 数量(根) double price1 = 18.5; // 单价(元) // 物料2:液压油 String itemName2 = "液压油"; int quantity2 = 40; // 数量(桶) double price2 = 320.0; // 单项金额 = 数量 × 单价 double amount1 = quantity1 * price1; double amount2 = quantity2 * price2; // 汇总 double total = amount1 + amount2; long totalInFen = (long) (total * 100); // 折算成"分",转成整数 // 是否超过预算 double budget = 40000.0; boolean overBudget = total > budget; // 采购员等级(用单个字符表示) char buyerLevel = 'A'; System.out.println(itemName1 + " 金额:" + amount1 + " 元"); System.out.println(itemName2 + " 金额:" + amount2 + " 元"); System.out.println("合计:" + total + " 元(" + totalInFen + " 分)"); System.out.println("是否超预算:" + overBudget); System.out.println("采购员等级:" + buyerLevel); } }

运行结果:

锚杆 金额:22200.0 元 液压油 金额:12800.0 元 合计:35000.0 元(3500000 分) 是否超预算:false 采购员等级:A

这段代码里,Java 的八种基本类型出现了六种(intdoublebooleancharlong,外加转换),剩下的byteshortfloat我们马上讲到。先立一个总纲:

Java 的类型分两大阵营:八种基本类型(primitive)是"值"本身;其余一切——String、数组、你自己写的类——都是引用类型。

这两个阵营的行为差异,是新手无数 bug 的源头。本章讲透它们。

第一部分:八种基本类型——一张表就够了

Java 有且只有八种基本类型,分四类:

分类类型占用空间举例日常使用频率
整数byte1 字节(-128~127)byte b = 100;
整数short2 字节short s = 5000;
整数int4 字节(约 ±21 亿)int age = 30;极高,整数默认用它
整数long8 字节long fen = 3500000L;中,int 装不下时用
小数float4 字节float f = 3.14F;
小数double8 字节double price = 18.5;极高,小数默认用它
字符char2 字节char level = 'A';
布尔booleanboolean ok = true;极高

按本系列"只讲常用"的原则,给你三条极简结论:

  1. 整数就用int,除非确定会超过 21 亿(比如毫秒时间戳、以"分"为单位的大金额),那就用long,数值后面加Llong t = 1723000000000L;

  2. 小数就用doublefloat要加F后缀、精度还低,业务代码里基本不用,知道它存在即可。

  3. byteshortfloat日常几乎不手写,多在底层 IO、旧代码里出现,见到了能看懂就行。

两个细节:

  • 写整数字面量时,Java 默认当 int 处理;写小数字面量默认当 double 处理。所以float f = 3.14;会报错(3.14 是 double,不能直接塞进更小的 float),必须写3.14F

  • char用单引号,只能包一个字符:'A''中'都合法。boolean只有truefalse,没有第三态,也不能用 0 和 1 代替。

第二部分:类型转换——自动的和强制的

案例里有两处转换,正好把两种转换方式都演示了。

自动转换(小杯倒进大杯,不用管)

double amount1 = quantity1 * price1; // int × double → double

quantity1是 int,price1是 double,int 乘之前会被自动提升为 double,结果是 double。规则一句话:范围小的类型放进范围大的类型,自动转,不丢数据。转换链是:

byte → short → int → long → float → double char ↗

所以int i = 'A';合法(i 的值是 65,字符的本质是 Unicode 编码数字),double d = 100;也合法。

强制转换(大杯倒进小杯,自己负责)

long totalInFen = (long) (total * 100);

total * 100是 double,要装进 long——范围大的进范围小的,可能丢数据,编译器要求你显式确认,写法是在值前面加(目标类型)

double d = 9.99; int i = (int) d; // i 是 9,不是 10!强转直接砍掉小数,不做四舍五入

新手必记(int)是"截断"不是"四舍五入"。想四舍五入用Math.round(),第十章讲工具类时会细说。

第三部分:String——最常用的引用类型

基本类型讲完了,现在看另一大阵营的代表。String 是 Java 里使用频率最高的类型,没有之一,但它不是基本类型,是一个类。这个事实引出三个必知点。

必知点一:字符串是不可变的(immutable)

String s = "锚杆"; s = s + "(12m)";

第二行并不是"修改了原来的字符串",而是新建了一个字符串对象,让 s 指向新对象,旧对象等待垃圾回收。日常用没问题,但在循环里反复+拼接会产生大量临时对象——性能坑,第四章讲 StringBuilder 时解决它。

必知点二:字符串拼接用+,其他类型自动转字符串

System.out.println("合计:" + total + " 元");

任何类型和字符串用+拼接,都会先被转成字符串。注意一个顺序陷阱:

System.out.println("结果:" + 1 + 2); // 输出:结果:12 System.out.println("结果:" + (1 + 2)); // 输出:结果:3

+从左往右算,第一行里"结果:" + 1先拼成了字符串,后面的 2 只能跟着拼;加括号让加法先算就对了。

必知点三(重点):比较字符串内容,必须用 equals,不能用 ==

这是 Java 新手最经典的坑,没有之一。看这段代码:

String a = new String("锚杆"); String b = new String("锚杆"); System.out.println(a == b); // false ← 惊不惊喜? System.out.println(a.equals(b)); // true

内容明明一样,==却返回 false。原因在于两大阵营的本质区别:

  • 基本类型:变量里存的就是值本身,==比较的就是值,int x = 5; int y = 5;x == y为 true,天经地义。

  • 引用类型:变量里存的是对象的地址(内存中的位置)。ab是两个不同的对象,地址不同,所以==为 false。==对引用类型回答的问题是"是不是同一个对象",而不是"内容一不一样"。

想比较内容,要用 String 类提供的equals方法:

String input = "维修"; if (input.equals("维修")) { // 正确姿势 System.out.println("生成维修工单"); }

实际开发中更稳妥的写法是把已知的字面量放前面,避免 null 报错:

if ("维修".equals(input)) { ... }

这种写法即使input是 null 也不会抛空指针异常——空指针(NullPointerException)是 Java 程序最常见的事故,第八章异常处理会专门讲。

补一个容易混淆的点:直接写双引号的字符串字面量会被 JVM 放进"字符串常量池"复用,所以:

String x = "abc"; String y = "abc"; System.out.println(x == y); // 居然是 true!常量池里同一个对象

正因为这种"有时 true 有时 false"的不确定性,规矩只有一条:比较字符串内容永远用 equals,忘掉 == 在字符串上的存在

常踩的坑(排雷清单)

  1. 字符串用 == 比较:本章最大的坑,见上。内容比较一律equals

  2. 整数相除丢掉小数int result = 7 / 2;结果是 3,不是 3.5——int 除 int 得 int。想要小数,至少一边写成 double:7.0 / 2(double) 7 / 2

  3. 强转当四舍五入用(int) 9.99得 9。要四舍五入请用Math.round()

  4. long 忘记加 Llong t = 1723000000000;编译报错,因为字面量默认 int,超范围了。加L就好。

  5. boolean 写 0/1if (flag == 1)在 boolean 上行不通,Java 的 boolean 和数字完全不通婚。

  6. char 和 String 混用引号'维修'(两个字符进单引号)编译报错;String s = 'A';也报错——类型不匹配。单引号 char、双引号 String,泾渭分明。

本章小结

  • Java 类型分两大阵营:八种基本类型存值本身,引用类型(String、数组、类)存地址。

  • 日常取舍:整数int、大额long L、小数double、真假boolean、单字符char 'A',其余三种认识即可。

  • 转换:小进大自动转,大进小加(类型)强转,强转是截断不是四舍五入。

  • String 是类、不可变;拼接用+(注意从左到右的顺序陷阱)。

  • 比较字符串内容用equals,永远不用==——引用类型的==比的是地址。

下一章:运算符与流程控制——通过一个"巡检成绩评级 + 批量统计"的案例,把 if、switch、三种循环讲透,重点拆解 switch 的 break 穿透和增强 for 为什么成为遍历的主流。

← 返回列表