Java 数据类型与基础语法+易错点
Java 数据类型与基础语法
一、Java 数据类型体系
1.1 两大类型的核心本质区别
Java 是强类型语言,所有变量必须先声明类型再使用,整体分为两类,二者在内存存储、赋值逻辑、运算规则上完全不同:
| 分类 | 包含内容 | 存储本质 | 内存位置(典型场景) | 赋值行为 |
|---|---|---|---|---|
| 基本数据类型 | 8种内置基础类型 | 直接存储数值本身 | 局部变量在栈内存;成员变量随对象在堆内存 | 赋值是值拷贝,两个变量互不影响 |
| 引用数据类型 | 数组、类、接口、字符串、枚举等 | 存储对象的内存首地址(引用) | 引用本身在栈,对象实体在堆内存 | 赋值是地址拷贝,多个引用指向同一个堆实体 |
易错点(错误的认为:
- 基本数据类型一定存在栈内存
- 纠正:只有方法内的局部基本变量存在栈中;类的成员基本变量(Field)会跟随对象存储在堆内存。
- 引用类型就是“存地址”,和基本类型只是存储内容不同
- 纠正:核心差异是赋值与传参逻辑。引用类型赋值后,两个变量操作的是同一个对象;基本类型赋值后,两个变量完全独立。
- 经典错题:
int a = 10; int b = a; b=20;a的值不变;但数组赋值后修改元素,原数组会同步变化。
- String 是基本数据类型
- 纠正:String 是引用类型(类),只是Java对它做了特殊的常量池优化,语法上看起来像基本类型,本质仍是对象。
1.2 八大基本数据类型深度拆解
1.2.1 整型家族(byte/short/int/long)
| 类型 | 占用空间 | 取值范围 | 标准语法与细节 |
|---|---|---|---|
| byte | 1字节(8位) | -128 ~ 127 | 最小整型,多用于字节流、文件/网络传输;整数字面量默认int,赋值给byte时,编译期校验数值是否在范围内 |
| short | 2字节(16位) | -32768 ~ 32767 | 过渡型整型,实际开发极少使用 |
| int | 4字节(32位) | -2^31 ~ 2^31-1(约±21亿) | Java默认整型,所有整数字面量默认是int类型 |
| long | 8字节(64位) | -2^63 ~ 2^63-1 | 长整型,字面量末尾必须加 L(推荐大写,小写l易和数字1混淆) |
1.2.2 浮点型家族(float/double)
| 类型 | 占用空间 | 精度 | 标准语法与细节 |
|---|---|---|---|
| float | 4字节(32位) | 单精度,约6~7位有效数字 | 字面量末尾必须加 F/f;不加F的小数默认是double类型,无法直接赋值给float |
| double | 8字节(64位) | 双精度,约15~16位有效数字 | 字面量末可以加上或省略D/d。Java默认浮点型,精度高于float,但同样存在精度丢失 |
1.2.3 字符型(char)
- 占用空间:2字节(16位),采用Unicode编码
- 取值范围:0 ~ 65535
- 标准赋值方式:
char c1 = 'a'; // 单个字符 char c2 = 97; // 直接写ASCII/Unicode数值,对应字符'a' char c3 = '\u0061'; // Unicode转义写法,对应'a' char c4 = '\n'; // 转义字符(换行、制表符等)
1.2.4 布尔型(boolean)
- 取值:仅
true和false,无其他值 - 空间说明:逻辑上占1位;但JVM编译后会用int类型代替boolean(false对应0,true对应1);boolean数组中每个元素占1字节。不存在“1bit的变量”这种底层实现。
易错点(错误的认为:
- 偏差:long类型的l大小写都一样
- 纠正:语法上都合法,但小写
l和数字1视觉上极易混淆,开发规范强制要求写大写L。
- 纠正:语法上都合法,但小写
- 偏差:char只能存单个英文字母,不能存中文
- 纠正:char采用Unicode编码,占2字节,完全可以存储单个中文字符(如
char c = '中';是合法的)。
- 纠正:char采用Unicode编码,占2字节,完全可以存储单个中文字符(如
- 偏差:char是字符串的一种,和String类似
- 纠正:char是基本类型,只能存1个字符;String是引用类型,可以存任意长度的字符序列。
- 偏差:boolean可以和数字互相转换,0是false,非0是true
- 纠正:Java中boolean完全独立,不能和任何数值类型做转换、运算,
if(1)这种写法在Java中直接编译报错。
- 纠正:Java中boolean完全独立,不能和任何数值类型做转换、运算,
- 偏差:float f = 3.14; 是合法写法
- 纠正:3.14默认是double类型,直接赋值给float会编译报错,必须写成
3.14f。
- 纠正:3.14默认是double类型,直接赋值给float会编译报错,必须写成
1.3 基本数据类型转换规则
1.3.1 自动类型转换(隐式转换)
标准结构与规则
取值范围小的类型,可以自动、无损失地转换为取值范围大的类型,编译器自动完成,无需额外代码。
完整转换优先级(范围从小到大,箭头方向可自动转换):byte → short → int → long → float → double
补充:char 可自动转换为 int 及以上类型;char 和 byte、short 之间不能自动互转。
易错点(错误的认为:
- long是8字节,float是4字节,所以long比float范围大,long转float需要强转
- 纠正:取值范围和占用字节数没有绝对正比关系。float的取值范围远大于long(float能表示到10^38,long最大只有9e18),因此 long → float 是自动转换,无需强转。
- 代价:long转float可能丢失低位精度,但语法上允许自动转换。
- byte可以自动转short,所以char也可以自动转byte/short
- 纠正:char是无符号的,取值范围0~65535,和byte、short的有符号范围不重叠,三者之间不能自动互转,必须强转。
1.3.2 强制类型转换(显式转换)
标准语法结构
(目标数据类型) 待转换的变量/表达式
当取值范围大的类型转成范围小的类型时,必须手动强转,编译器不会自动执行。
认知偏差与易错点
- 偏差:强制转换会四舍五入
- 纠正:强制转换是直接截断高位、保留低位,不会四舍五入。
- 示例:
(int)3.99结果是3,不是4。
- 偏差:强转只是语法要求,不会影响数值
- 纠正:超出目标类型范围时,会发生数据溢出,结果完全不符合预期。
- 示例:
byte b = (byte)128;结果是-128(二进制溢出循环),不是128。
- 偏差:强转优先级低于算术运算
- 纠正:强转运算符优先级高于加减乘除。
- 示例:
(byte)10 + 20的结果是int类型(只把10转成byte,运算时又提升回int),正确写法是(byte)(10 + 20)。
1.3.3 表达式运算的自动类型提升(最高频考点)
标准核心规则(分两步执行)
所有算术运算表达式,都会先做类型提升,再执行运算,规则固定:
- 第一步:小整型统一升int
所有byte、short、char类型的变量,只要参与算术运算,运算前自动提升为int类型。 - 第二步:多类型统一向大范围对齐
如果表达式中有比int范围更大的类型(long/float/double),所有操作数统一提升为表达式中范围最大的那个类型,最终结果也是该类型。
例如:int + long → 结果为long;long + float → 结果为float。
特殊规则1:常量折叠(编译期优化)
如果表达式中全部都是常量字面量,没有任何变量,编译器会在编译阶段直接计算结果,并校验结果是否在目标类型范围内;如果在范围内,无需强转也能赋值。
byte b = 10 + 20; // 编译通过:编译期算出30,在byte范围内
- 边界:被
final修饰的常量变量,也会参与常量折叠;普通变量一定触发运行时类型提升。
特殊规则2:复合赋值运算符自带隐式强转
+=、-=、*=、/=、%= 这类复合赋值运算符,底层等价于「运算 + 强制类型转换」。
byte b = 10;
b += 1;
// 底层等价于:b = (byte)(b + 1);
易错点(错误的认为:
- byte + byte 结果是byte
- 纠正:只要参与运算,两个byte都会先升int,结果一定是int,赋值给byte必须强转。
- 复合赋值运算符不会出错,比普通赋值更安全
- 纠正:复合赋值只是编译不报错,但运行时依然可能溢出。
- 示例:
byte b = 127; b += 1;编译通过,但运行后b的值变成-128,发生溢出。
- :
short s = 1; s = s + 1;和s += 1;效果完全一样- 纠正:语法效果不同,前者编译报错(int转short需要强转),后者编译通过(隐式强转);数值结果在不溢出时一致,但底层逻辑不同。
- 常量折叠也适用于变量运算
- 纠正:只要表达式里有变量,就一定触发运行时类型提升,哪怕变量的值是固定的。
1.4 浮点型精度问题深度解析
底层原理
float和double遵循 IEEE 754 二进制浮点标准,用“符号位+指数位+尾数位”的方式存储小数。
十进制的有限小数(如0.1、0.2),转换成二进制后可能是无限循环小数,float/double只能存储近似值,因此存在天然的精度丢失。
易错点(错误的认为:
- 只有float有精度问题,double是精确的
- 纠正:double只是精度更高、误差更小,同样存在精度丢失,只是在小数位更多的地方才会体现。
- 可以用
==判断两个浮点数是否相等- 纠正:绝对禁止。两个字面量不同的浮点数,可能因精度丢失存储为同一个值;两个逻辑上相等的浮点数,也可能因计算路径不同出现微小误差,导致
==返回false。 - 正确做法:判断两个数的差值的绝对值是否小于一个极小的误差阈值(如1e-6)。
- 纠正:绝对禁止。两个字面量不同的浮点数,可能因精度丢失存储为同一个值;两个逻辑上相等的浮点数,也可能因计算路径不同出现微小误差,导致
- 金额计算用double就够了,误差很小可以忽略
- 纠正:金融、支付、金额场景必须使用
BigDecimal类,浮点误差在多次累加后会被放大,造成资金计算错误。
- 纠正:金融、支付、金额场景必须使用
二、Java 基础运算符
2.1 算术运算符
标准运算符:+ - * / % ++ --
- 除法
/:两个整数相除,结果默认取整(截断小数部分,不是四舍五入);想要小数结果,必须至少有一个操作数是浮点型。 - 取余
%:求除法的余数,余数的符号和被除数一致。- 示例:
5 % 2 = 1,-5 % 2 = -1,5 % -2 = 1
- 示例:
- 自增
++/ 自减--- 前缀式(
++a):先自增,再拿自增后的值参与表达式运算 - 后缀式(
a++):先拿当前值参与表达式运算,运算结束后再自增
- 前缀式(
易错点(错误的认为:
- 整数除法会四舍五入
- 纠正:直接截断小数部分,
3/2结果是1,不是2。
- 纠正:直接截断小数部分,
- 取余只能用于正数
- 纠正:负数也可以取余,核心规则是余数符号和被除数相同,这是高频错题。
int a = 10; a = a++;执行后a会加1- 纠正:结果a还是10。后缀自增是“先取值,再加1”,先把a的原值10取出来,然后a自增成11,最后把取出的10赋值给a,覆盖了自增结果。
2.2 赋值运算符
标准结构
- 基本赋值:
= - 复合赋值:
+=-=*=/=%=等 - 执行顺序:从右向左,先计算右边表达式的值,再赋值给左边的变量。
易错点(错误的认为:
int a = b = c = 10;是非法写法- 纠正:赋值运算符支持连续赋值,从右向左依次执行,该写法合法。
- 复合赋值只是简写,和普通赋值完全等价
- 纠正:在窄类型运算中不等价,复合赋值自带隐式强转,普通赋值没有。
2.3 比较运算符
标准运算符
== != > < >= <=
- 所有比较运算符的运算结果都是 boolean 类型。
易错点(错误的认为:
- 偏差:基本类型和引用类型的
==规则一样- 纠正:
- 基本类型:
==比较的是数值本身 - 引用类型:
==比较的是内存地址(是否为同一个对象),不是内容
- 基本类型:
- 纠正:
=和==只是写法不同,功能差不多- 纠正:
=是赋值,==是比较,完全是两个运算符;if(a = 10)这种写法在Java中编译报错(因为赋值结果是int,不能作为boolean条件)。
- 纠正:
2.4 逻辑运算符
标准分类与真值表
用于连接 boolean 类型的表达式,分为短路和非短路两类:
| 运算符 | 名称 | 运算规则 | 短路特性 |
|---|---|---|---|
&& |
短路与 | 两侧条件全为 true 时结果才为 true;任意一侧为 false,结果直接为 false | 左侧表达式结果为 false 时,右侧表达式完全不执行 |
|| |
短路或 | 两侧条件任意一个为 true 结果就为 true;两侧全为 false,结果才为 false | 左侧表达式结果为 true 时,右侧表达式完全不执行 |
& |
逻辑与 | 最终运算结果和 && 完全一致 |
无短路机制,无论左侧结果如何,两侧表达式一定会执行 |
| |
逻辑或 | 最终运算结果和 || 完全一致 |
无短路机制,无论左侧结果如何,两侧表达式一定会执行 |
! |
逻辑非 | 对布尔值取反,true 变为 false,false 变为 true | 单目运算符,仅作用于单个表达式,不存在短路 |
易错点(错误的认为:
- 短路和非短路只是性能区别,结果永远一样
- 纠正:当右边表达式有副作用(如自增、方法调用、修改变量)时,执行结果会不同。
- 示例:
int a = 10; boolean res = false && (++a > 5); // 结果:a还是10,因为短路,右边++a没执行 // 如果换成&,a就会变成11
&只是位运算符,不能当逻辑运算符用- 纠正:
&和|有双重身份:两边是boolean时是逻辑运算符;两边是整数时是位运算符。
- 纠正:
- 逻辑运算符可以连接数字,0为假非0为真
- 纠正:Java中逻辑运算符只能连接boolean表达式,
if(1 & 2)是位运算,结果是整数,不能当条件。
- 纠正:Java中逻辑运算符只能连接boolean表达式,
2.5 三元运算符
标准语法结构
条件表达式 ? 结果值1 : 结果值2
- 执行逻辑:条件为true,返回结果值1;为false返回结果值2。
- 本质:是一个有返回值的表达式,必须接收返回值,不能单独作为语句。
易错点(错误的认为:
- 三元运算符可以代替if-else
- 纠正:三元运算符是表达式,必须有返回值;if-else是语句,可以没有返回值。复杂逻辑优先用if-else,三元只适合简单的二值选择。
- 两个结果值类型不同会编译报错
- 纠正:会触发自动类型提升,统一为范围更大的类型。
- 示例:
int a = true ? 10 : 3.14;编译报错,因为结果会提升为double,不能直接赋值给int。
Java 运算符优先级总表
优先级数字越小,优先级越高;同优先级运算符按「结合性」决定执行顺序。
| 优先级 | 运算符分类 | 运算符 | 结合性 |
|---|---|---|---|
| 1(最高) | 后缀运算符 | .、[]、(参数)、表达式++、表达式-- |
从左到右 |
| 2 | 一元运算符 | ++表达式、--表达式、+(正)、-(负)、!、~ |
从右到左 |
| 3 | 乘性运算符 | *、/、% |
从左到右 |
| 4 | 加性运算符 | +、- |
从左到右 |
| 5 | 移位运算符 | <<、>>、>>> |
从左到右 |
| 6 | 关系运算符 | <、>、<=、>=、instanceof |
从左到右 |
| 7 | 相等运算符 | ==、!= |
从左到右 |
| 8 | 按位与 | & |
从左到右 |
| 9 | 按位异或 | ^ |
从左到右 |
| 10 | 按位或 | | |
从左到右 |
| 11 | 逻辑与 | && |
从左到右 |
| 12 | 逻辑或 | || |
从左到右 |
| 13 | 三元运算符 | ? : |
从右到左 |
| 14(最低) | 赋值运算符 | =、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=、>>>= |
从右到左 |
三、流程控制语句
3.1 分支结构
3.1.1 if-else 分支
标准结构
- 单分支:
if(条件) { 执行体 } - 双分支:
if(条件) { 执行体1 } else { 执行体2 } - 多分支:
if(条件1) { 执行体1 } else if(条件2) { 执行体2 } ... else { 兜底 }
易错点(错误的认为:
- if后面不写大括号,也能控制多行代码
- 纠正:if/else后面如果没有大括号,只能控制紧随其后的第一条语句,后面的代码和if无关。
- 悬挂else问题
- 规则:else永远和离它最近的、未匹配的if配对,和缩进无关。
- 易错场景:多层if嵌套不写大括号时,else的匹配结果和视觉缩进不一致,极易出逻辑bug。
3.1.2 switch-case 分支
标准结构
switch(表达式) {
case 常量值1:
执行语句;
break;
case 常量值2:
执行语句;
break;
default:
兜底执行语句;
}
- 支持的表达式类型:byte、short、char、int、String(JDK7+)、枚举
- 不支持:long、float、double、boolean(因为无法精确匹配等值)
核心特性:case穿透
某个case匹配成功后,如果该case后没有break,程序会顺序执行后续所有case的代码,直到遇到break或switch结束,不做二次匹配。
易错点(错误的认为:
- case后面的值可以是变量
- 纠正:case后面必须是编译期常量(字面量、final常量),不能是普通变量。
- default必须写在最后
- 纠正:default可以写在任意位置,但执行时机永远是「所有case都不匹配时」才执行;写在中间时如果不写break,也会触发向下穿透。
- case穿透是bug,必须避免
- 纠正:合理利用穿透可以简化代码,比如多个case执行同一段逻辑时,就可以利用穿透省略重复代码。
- switch的表达式可以是任意类型
- 纠正:不支持long、float、double,因为浮点有精度问题,无法做精确的等值匹配;boolean也不支持。
3.2 循环结构
3.2.1 for 循环
标准结构与执行顺序
for(初始化语句; 循环条件; 迭代语句) {
循环体
}
执行顺序:
- 初始化语句:只在循环开始前执行1次
- 判断循环条件:true则执行循环体,false则结束循环
- 执行循环体
- 执行迭代语句
- 回到第2步重复
易错点
- for循环的三部分都必须写
- 纠正:三部分都可以省略,
for(;;)就是死循环(条件默认为true)。
- 纠正:三部分都可以省略,
- 差一错误(边界错误)
- 新手高频错误:循环条件写成
i <= arr.length导致数组越界,正确的遍历条件是i < arr.length。
- 新手高频错误:循环条件写成
- 偏差:初始化语句中定义的变量,循环外也能使用
- 纠正:for循环初始化中定义的变量,只在循环内部有效,循环结束后无法访问。
3.2.2 while / do-while 循环
标准结构
- while:先判断,后执行,循环体可能一次都不执行
- do-while:先执行一次循环体,再判断条件,循环体至少执行一次
do { 循环体 } while(条件); // 末尾分号不能省略
易错点(错误的认为:
- do-while末尾的分号可写可不写
- 纠正:必须写,省略会编译报错,这是新手高频语法错误。
- while循环和for循环本质不同
- 纠正:功能上完全等价,for适合循环次数已知的场景,while适合次数未知的场景,二者可以互相改写。
3.3 循环跳转关键字
标准作用
- break:立即终止当前所在的整个循环,或终止switch分支。
- continue:跳过本次循环的剩余代码,直接进入下一次循环的条件判断。
易错点(错误的认为:
- break可以跳出所有嵌套循环
- 纠正:默认只能跳出当前层循环;想要跳出多层,需要使用标签(label)语法,但日常开发极少使用。
- break可以用在if语句里
- 纠正:break只能用在循环和switch中,单独写在if里编译报错(if不是循环/switch结构)。
- continue会结束整个循环
- 纠正:continue只跳过本次,循环还会继续执行下一次。
四、数组
4.1 数组的本质与核心特性
标准定义
数组是相同数据类型元素的有序集合,是Java中最基础的容器,本身是引用类型(对象)。
核心特性:
- 元素类型必须统一
- 长度在创建时确定,一旦创建,长度不可改变
- 元素通过索引访问,索引从0开始,范围:
0 ~ 长度-1 - 在堆内存中占用连续的存储空间,这也是索引随机访问效率为O(1)的原因
易错点(错误的认为:
- 数组是基本数据类型
- 纠正:数组是引用类型,数组变量存的是堆中数组实体的首地址,数组对象继承自Object类。
- 数组长度可以动态增加/减少
- 纠正:数组定长,不能动态扩容。想要动态长度的容器,需要使用ArrayList等集合。
- 数组只能存基本类型
- 纠正:既可以存基本类型,也可以存引用类型;存引用类型时,数组里存的是对象的地址。
4.2 数组的声明与初始化
4.2.1 数组声明
标准语法
// 推荐写法,语义清晰:int类型的数组,变量名arr
数据类型[] 数组名;
// C语言兼容写法,不推荐
数据类型 数组名[];
- 注意:声明时不能指定数组长度,
int[5] arr;是编译错误。 - 仅声明的数组,没有分配堆内存,不能直接使用。
4.2.2 静态初始化
创建时直接指定所有元素,系统自动计算长度,适合元素已知的场景。
// 完整格式
数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, ...};
// 简化格式(声明和初始化在同一行时可用)
数据类型[] 数组名 = {元素1, 元素2, ...};
4.2.3 动态初始化
创建时只指定长度,系统自动给所有元素赋默认值,适合先确定容量、后赋值的场景。
数据类型[] 数组名 = new 数据类型[数组长度];
不同类型的默认初始值
| 类型分类 | 默认值 |
|---|---|
| byte/short/int/long | 0 |
| float/double | 0.0 |
| char | ‘\u0000’(空字符,不是空格) |
| boolean | false |
| 所有引用类型 | null |
易错点(错误的认为:
- 静态初始化和动态初始化可以混合使用
- 纠正:不能混合,
new int[3]{1,2,3}是编译错误,要么指定长度,要么指定元素,二选一。
- 纠正:不能混合,
- 偏差:简化格式
int[] arr = {1,2,3};可以先声明再赋值- 纠正:简化格式只能在声明并初始化的同一行使用;先声明再赋值必须用完整格式。
- 局部数组的元素没有默认值
- 纠正:数组只要在堆中创建成功,元素就会被赋予默认值;这里要区分:数组变量(局部变量)必须手动初始化才能使用,但数组对象的元素有默认值。
- char数组的默认值是空格
- 纠正:是’\u0000’空字符,打印出来看起来像空格,但本质不是空格字符。
4.3 数组元素访问与length属性
标准用法
- 访问元素:
数组名[索引],既可以取值,也可以赋值 - 获取长度:
数组名.length,是属性不是方法,返回int类型
易错点
- 索引从1开始
- 纠正:索引从0开始,最大索引 = 长度 - 1。
- length是方法,要加括号
- 纠正:数组的length是属性,不加括号;字符串的length()才是方法,注意区分。
- 可以通过修改length来改变数组长度
- 纠正:length是只读属性,只能读取不能修改;数组创建后长度不可变。
4.4 数组遍历
4.4.1 普通for循环遍历
int[] arr = {10,20,30};
for(int i = 0; i < arr.length; i++){
System.out.println(arr[i]);
}
- 特点:可以拿到索引,既能读元素也能修改元素,最灵活。
4.4.2 增强for循环(foreach)
int[] arr = {10,20,30};
for(int num : arr){
System.out.println(num);
}
- 特点:代码简洁,无法获取索引,只能读取元素,不能修改数组中的元素值。
- 底层原理:数组的增强for循环,编译器会自动转成普通for循环;集合的增强for循环底层是迭代器。
易错点(错误的认为:
- 增强for循环可以修改数组元素
- 纠正:对于基本类型数组,增强for里的变量是元素的副本,修改它不会影响原数组。
- 补充:对于引用类型数组,修改对象的属性会生效,但修改引用本身(让变量指向新对象)不会影响原数组。
- 增强for循环比普通for循环性能更好
- 纠正:对于数组,二者编译后代码几乎一致,性能没有差异,只是语法更简洁。
4.5 数组内存原理与引用赋值
标准内存模型
- 栈内存:存储局部变量(数组引用),保存数组对象在堆中的首地址
- 堆内存:存储数组对象实体,所有元素数据都存在这里
核心易错点:引用赋值
int[] arr1 = {1,2,3};
int[] arr2 = arr1; // 地址拷贝,两个引用指向同一个数组对象
arr2[0] = 100;
System.out.println(arr1[0]); // 输出100,原数组被修改
- 新手高频误区:以为是把数组元素复制了一份,实际只是复制了地址,两个变量操作同一个数组。
4.6 数组常见运行时异常
- ArrayIndexOutOfBoundsException(数组索引越界异常)
- 触发场景:访问的索引 < 0 或 >= 数组长度
- 高频易错:长度为0的数组(
new int[0]),访问arr[0]也会越界
- NullPointerException(空指针异常)
- 触发场景:数组变量的值为null,却去访问数组元素、length属性
- 易错区分:null数组 和 长度为0的数组 完全不同,前者没有堆对象,后者有对象但没元素
4.7 二维数组(基础拓展)
本质
二维数组本质是数组的数组,即一个数组里的每个元素又是一个一维数组。
认知偏差
- 偏差:二维数组必须是行列对齐的矩阵
- 纠正:第二维的每个数组长度可以不一样,例如:
int[][] arr = new int[3][]; // 只指定第一维长度,第二维可以分别初始化 arr[0] = new int[2]; arr[1] = new int[5];
五、补充基础概念
5.1 Field(字段/属性)
- 标准定义:在类中定义的成员变量,用于描述类/对象的数据特征。
- 认知偏差:Field和局部变量只是位置不同
- 纠正:二者在内存位置、默认值、作用域、生命周期上完全不同:
- 成员变量:在堆中,有默认值,作用于整个对象
- 局部变量:在栈中,无默认值,作用于方法/代码块内部
- 纠正:二者在内存位置、默认值、作用域、生命周期上完全不同:
5.2 注解(Annotation)
- 标准定义:以
@开头,用于给代码添加元数据(标记、配置信息) - 认知偏差:注解就是注释,不影响程序运行
- 纠正:注释给人看,编译器忽略;注解给程序看,编译期和运行期都可以被读取并执行对应逻辑,是框架的核心语法。
更多推荐



所有评论(0)