基础语法概念

1.java、jdk、jre、jvm

基础关系:JDK>JRE>JVM

  • JVM:Java虚拟机,是运行Java字节码的场所
  • JRE:Java运行时环境,包含了JVM和运行所需的核心类库,只能运行Java程序,不能开发
  • JDK:Java开发工具包,包含了JRE和开发工具(如编译器),既能开发Java程序,也能运行Java程序
  • Java:它是一种编程语言,我们利用JDK提供的工具,编写能在JVM上运行的代码

详细说明

JVM (Java Virtual Machine) ——Java虚拟机

作用:编译好的 .class 文件(字节码)解释或编译成当前操作系统能够识别的机器码并执行

特点:一次编译,到处运行(不同的系统平台有不同的JVM版本),不包含任何开发工具或核心库

JRE (Java Runtime Environment) —— Java运行时环境

组成:JRE = JVM + Java核心类库(如 langutiliomath 等包下的类)

用途:只能运行已经写好的Java程序

局限:**它不包含编译器(javac)**和其他开发工具,所以无法在JRE环境下编写并编译Java源代码

JDK (Java Development Kit) ——Java开发工具包

组成:JDK = JRE + 开发工具

开发工具:

  • javac:Java编译器(将 .java 源文件编译成 .class 字节码)
  • java:启动JVM运行程序的工具
  • jar:打包工具
  • javadoc:文档生成器
  • 调试、监控工具(如 jconsolejvisualvm

特点:需要编写并编译Java程序,就必须安装JDK

2.关键字、标识符、注释

概念定义与作用关键点
关键字Java语言预定义的单词,具有特殊含义全小写,不能作标识符,例如classpublicstatic
标识符程序员自定义的名称遵循命名规则(字母、数字、_、$,首字符不能是数字,避开关键字)
注释用于解释代码的文本,不参与编译单行//、多行/* */、文档注释/** */,注意嵌套限制

常见关键字分类

  • 访问控制privateprotectedpublic
  • 类、方法、变量修饰符abstractclassextendsfinalimplementsinterfacenativenewstaticstrictfpsynchronizedtransientvolatile
  • 程序控制breakcontinuereturndowhileifelseforinstanceofswitchcasedefault
  • 错误处理trycatchfinallythrowthrows
  • 包相关importpackage
  • 基本类型booleanbytechardoublefloatintlongshort
  • 变量引用superthisvoid
  • 保留字gotoconst(虽然未被使用,但仍是保留字,不可用作标识符)

注意truefalsenull虽然不属于关键字,但属于字面常量,同样不能用作标识符。

命名惯例(建议遵守,提高可读性)

  • 类名:大驼峰命名法(PascalCase),每个单词首字母大写,如PersonStudentInfo
  • 方法名、变量名:小驼峰命名法(camelCase),第一个单词首字母小写,后续单词首字母大写,如getNametotalCount
  • 常量名:全部大写,单词间用下划线分隔,如MAX_VALUEPI
  • 包名:全部小写,单词间用点分隔,如com.example.myapp

3. 基本数据类型

Java共有8种基本数据类型(primitive types),分为四类:

类型关键字占用字节取值范围/表示默认值包装类
整型byte1-128 ~ 127(2^7)0Byte
short2-32768 ~ 32767(2^15)0Short
int4-2147483648 ~ 2147483647(2^31)0Integer
long8-2^63 ~ 2^63-10LLong
浮点型float4约 ±3.40282347E+38F(6-7位有效数字)0.0fFloat
double8约 ±1.79769313486231570E+308(15位有效数字)0.0dDouble
字符型char20 ~ 65535(Unicode字符)‘\u0000’Character
布尔型boolean未明确定义(通常1字节)true / falsefalseBoolean

boolean 在虚拟机中通常用 int 表示,数组类型则用 byte[] 实现,但语言层面不关心大小。

char 是无符号类型,可以存放汉字

基本数据类型相互转换

自动类型转换(隐式转换)

两个条件:类型是兼容小转大

byte → short → int → long → float → double
         ↑
        char
  • char 可以自动转换为 int 及更大的类型(因为 char 是无符号整数,int 能容纳其所有值)。
  • 整数类型(byte/short/int/long)可以自动转换为 float/double,但可能损失精度(因为 float/double 的表示方式不同,尾数有限)。
强制类型转换(显式转换)

当需要将取值范围大的类型转换为取值范围小的类型时,必须使用强制类型转换,语法为 (目标类型) 变量。这种转换可能丢失信息(精度或数值范围)。

double d = 3.14159;
float f = (float) d;      // double → float,可能损失精度
long l = 12345678901L;
int i = (int) l;          // long → int,可能发生溢出
short s = (short) i;      // int → short,可能溢出

易错点

(1)整数溢出问题

int max = Integer.MAX_VALUE;    // 2147483647
int min = Integer.MIN_VALUE;    // -2147483648
System.out.println(max + 1);    // 输出 -2147483648
System.out.println(min-1);      // 输入 2147483647
  • 超出类型的范围后,数值会回绕
  • 考虑累加的边界问题,使用long更大范围

(2)浮点数精度丢失

double d1 = 0.1;
double d2 = 0.2;
System.out.println(d1 + d2); // 0.30000000000000004
  • 易错点:直接用 == 比较浮点数,或用于金额计算
  • 解决方案:使用 BigDecimal 或设定误差范围(如 Math.abs(a-b) < 1e-6

(3)char 的加减和转义

char c = 'A';
c = c + 1; // 编译错误:int 不能直接赋给 char
c += 1;    // 正确:复合赋值隐含强制转换
System.out.println(c); // 'B'

char 本质上是一个无符号整数,可以进行算术运算,但结果会自动提升为 int

c = c + 1

执行 c + 1 时,Java 会进行二元数值提升,将 char 转换为 int,因此表达式的结果类型是 int,

int 类型的结果赋值给 char 类型的变量 c 属于窄化转换,可能损失精度(例如 int 值可能超出 char 的范围 0~65535),

Java 要求显式转换,所以直接赋值会报编译错误:不兼容的类型: 从int转换到char可能会有损失

c += 1

复合赋值运算符 += 在 Java 中定义为:E1 op= E2 等价于 E1 = (T) ((E1) op (E2)),其中 TE1 的类型,

  • 因此 c += 1 实际相当于 c = (char) (c + 1);,即自动包含了强制类型转换

    char c = 'A';
    int a = c + 1;
    System.out.println(a);  //66
    char b = (char) (c + 1);
    System.out.println(b);  //B
    

    在算术表达式中,所有小于 int 的整型(byte、short、char)会自动提升为 int,可能导致需要强制转换才能赋值回原类型。

(4)boolean 与整数不可互换

boolean flag = true;
if (flag) {}   // 正确
if (1) {}      // 编译错误

(5)包装类缓存

包装类默认缓存范围补充说明
Integer-128 到127可通过 -XX:AutoBoxCacheMax 调整
Character0 到127
Byte-128 127Byte 类型的取值范围本身就是 -128127,所以相当于缓存了全部可能的值
Short-128 到 127只缓存了该类型取值区间(-3276832767)中最高频使用的一部分。
Long-128 到 127同样只缓存了该类型取值区间中最高频使用的一部分。
Float 和 Double没有缓存机制
Booleantruefalse本质上也是全部缓存
  • 自动装箱也会触发缓存:当使用自动装箱(例如 Long a = 100L;)时,其底层调用的就是 valueOf() 方法,所以同样会享受缓存机制。

  • 比较值请用 equals():虽然缓存范围相同,但请一定注意,这个缓存机制是针对对象的。在 -128127 范围内,valueOf() 返回的是同一个缓存对象,用 == 比较会返回 true;但超出此范围,就会创建新对象,用 == 比较会返回 false。因此,比较包装类的数值是否相等时,永远都应该使用 equals() 方法

  • new 关键字不会触发缓存:务必注意,如果你使用 new 关键字来创建包装类对象(如 new Integer(100)),JVM 会强制创建一个全新的对象,不会从缓存中获取。这是很多初学者容易踩的坑 。

(6)三元运算符的类型自动提升

现象:三元运算符 ?: 的后两个操作数类型不同时,会进行二进制数值提升。

Object o1 = true ? new Integer(1) : new Double(2.0);
System.out.println(o1); // 1.0,而不是1

因为 IntegerDouble 混合时,Integer 被拆箱并提升为 double,结果自动装箱为 Double

**(7)short、byte 赋值陷阱 **

直接赋值整数常量时,如果常量在范围内,编译器允许隐式转换;但如果使用变量,则必须强制转换。

byte b1 = 10;           // 正确,常量在范围内
byte b2 = 128;          // 错误,超出范围
byte b3 = (byte)128;    // 强制转换,结果为 -128(溢出)

int a = 10;
byte b4 = a;            // 编译错误,int 不能直接赋给 byte
byte b5 = (byte) a;     // 正确

(8)默认值:局部变量 vs 成员变量

成员变量(类变量、实例变量)有默认值,但局部变量必须显式初始化,否则编译报错。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐