一、Java 中的 字面量(直接量)
1、定义
字面量 (直接量 )是代码中直接表示 值 的字面形式 ,无需通过变量 或计算 获得。
2、分类
2.1、整型(整数直接量)
十进制 :123十六进制:0x 10、0X 10 表示十进制 中的 16 。 八进制:0 10 表示十进制 中的 8 。 八进制表示法比较容易混淆 。所以,很少 有程序员使用八进制常数 。 二进制:0b 10、0B 10 表示十进制 中的 2 。 长整型 :100L
2.2、浮点型(浮点数直接量)
单精度后缀 :3.14f、3.14F双精度后缀 :3.14 或 3.14d
2.3、字符与字符串(字符直接量)
字符 :‘A’、‘汉’、‘中’转义字符 :\n(换行)、\t(制表符)等。
2.4、字符串(字符串直接量)
2.5、布尔型(布尔直接量)
2.6、空引用(空引用直接量)
int a = 10 ;
String s = "abc" ;
boolean b = true ;
3、 特点
不可变 :直接量的值 在代码中固定,无法修改 。无存储位置 :直接量本身不是变量,只是值的字面表示。内存优化 :字符串直接量 会被 JVM 放入 字符串常量池 ,实现重用 。
二、Java 中的 常量(Constans)
1、定义
常量是程序运行期间值 不可变 的变量 ,通常通过final 关键字 声明。 * 即:通过 final 关键字 声明的变量 是常量 。
关键字 final 表示这个变量只能被赋值一次 。一旦赋值,就不能再更改 了。 常量名 使用全大写,有多个单词时,用 _ 隔开。
final int MAX_VALUE = 100 ;
final String GREETING = "Hello world" ;
final var PI = 3.14 ;
var MAX = 100 ;
enum Color { RED, GREEN, BLUE }
在 Java 中,可能经常需要创建一个常量以便在多个类的多个方法中使用。
通常将这些常量称为 类常量 (class constant)。 可以使用关键字 static final 设置一个 类常量 。
public class HongTiHuan {
public static final int MAX = 100 ;
private static final double PI = 3.1415926 ;
public static final String GREETING = "Hello" ;
static final String MESSAGE = GREETING + " World!" ;
static final double CIRCUMFERENCE = 2 * Math . PI * 10 ;
public static final String DB_URL;
static {
DB_URL = "jdbc:mysql://localhost:3306/mydb" ;
}
}
2、分类
2.1、编译时常量
值在编译时 确定(如:final int X = 5 + 3;),会被编译器 优化 (类似直接量 )。 必须满足的条件:
final 修饰的 基本类型 或 String 。局部变量 (声明时 直接赋值 ) 或 类变量 (声明 时直接赋值 或 在静态块中初始化 )。
实例变量 就算是在声明时 直接赋值 。编译后,赋值的字节码指令 ,被放在构造器 中。
值由 字面量 或 常量表达式 构成 (不是运行时计算 )。
public class HongTiHuan {
static final double CIRCUMFERENCE = 2 * Math . PI * 10 ;
public static void main ( String [ ] args) {
System . out. println ( "CIRCUMFERENCE:" + CIRCUMFERENCE) ;
final String finalWorld2 = "hello" ;
System . out. println ( "finalWorld2:" + finalWorld2) ;
}
}
2.2、运行时常量
值在运行时 确定(如 final int NOW = LocalTime.now().getHour();)。
public class HongTiHuan {
public static final double AREA = Math . PI * Math . pow ( 10 , 2 ) ;
int age = 20 ;
public static String DB_URL;
static {
DB_URL = "jdbc:mysql://localhost:3306/mydb" ;
}
public static void main ( String [ ] args) {
System . out. println ( "AREA:" + AREA) ;
HongTiHuan hongTiHuan = new HongTiHuan ( ) ;
System . out. println ( hongTiHuan. age) ;
System . out. println ( "DB_URL:" + DB_URL) ;
String hw = "hello world" ;
System . out. println ( "hw:" + hw) ;
}
}
3、特点
不可变 :常量一旦初始化后,值不能再修改。存储位置 :常量是变量 ,有明确的内存地址 。
4、编译时常量化 – (类似:宏替换)
4.1、概述
在 Java 中,编译时常量化(Compile-Time Constant) :
是指某些 变量 或 表达式的值 在编译阶段就能被确定 ,并被编译器直接替换 为字面量 的过程。 这种常量化的核心是值不可变 ,且其值在编译时即可完全计算 出来。
4.2、示例
public class HongTiHuan {
static final double CIRCUMFERENCE = 2 * Math . PI * 10 ;
public static final double AREA = Math . PI * Math . pow ( 10 , 2 ) ;
int age = 20 ;
public static String DB_URL;
static {
DB_URL = "jdbc:mysql://localhost:3306/mydb" ;
}
public static void main ( String [ ] args) {
System . out. println ( "CIRCUMFERENCE:" + CIRCUMFERENCE) ;
System . out. println ( "AREA:" + AREA) ;
HongTiHuan hongTiHuan = new HongTiHuan ( ) ;
System . out. println ( hongTiHuan. age) ;
System . out. println ( "DB_URL:" + DB_URL) ;
String hw = "hello world" ;
System . out. println ( "hw:" + hw) ;
final String finalWorld2 = "hello" ;
System . out. println ( "finalWorld2:" + finalWorld2) ;
}
}
public class HongTiHuan {
static final double CIRCUMFERENCE = 62.83185307179586 ;
public static final double AREA = Math . PI * Math . pow ( ( double ) 10.0F , ( double ) 2.0F ) ;
int age = 20 ;
public static String DB_URL = "jdbc:mysql://localhost:3306/mydb" ;
public static void main ( String [ ] args) {
System . out. println ( "CIRCUMFERENCE:62.83185307179586" ) ;
System . out. println ( "AREA:" + AREA) ;
HongTiHuan hongTiHuan = new HongTiHuan ( ) ;
System . out. println ( hongTiHuan. age) ;
System . out. println ( "DB_URL:" + DB_URL) ;
String hw = "hello world" ;
System . out. println ( "hw:" + hw) ;
String finalWorld2 = "hello" ;
System . out. println ( "finalWorld2:hello" ) ;
}
}
4.3、小结
变量类型 是否可发生宏替换 必要条件 static final 类变量✅ 是 基本类型 / String,声明时或静态块中赋常量值 final 实例变量❌ 否 值在运行时确定 ,属于对象级别 final 局部变量✅ 是(局部) 基本类型 / String,声明时赋常量值
4.4、应用 – 字符串比较
单独使用 “” 引号创建的字符串都是常量,编译期就已经确定存储到常量池中; 使用 new String(“”) 创建的对象会存储到堆内存中,是运行期新创建的; 使用只包含常量的字符串连接符如 “aa” + “bb” 创建的也是常量。
使用包含变量 的字符串连接符(如:“aa” + s1 )创建的对象是运行期才创建的,存储在堆中;
public static void main ( String [ ] args) {
String nb1 = "final" ;
String nb2 = "test" ;
String nb4 = nb1 + nb2;
final String nb6 = nb1 + nb2;
String nb = "finaltest" ;
final String nb11 = "final" ;
final String nb22 = "test" ;
String nb5 = nb11 + nb22;
String nb3 = "final" + "test" ;
System . out. println ( nb == nb3) ;
System . out. println ( nb == nb4) ;
System . out. println ( nb == nb5) ;
System . out. println ( nb == nb6) ;
System . out. println ( nb4 == nb6) ;
}
三、Java 中的 变量
与所有程序设计语言一样,Java 也使用变量 来存储值 。
Java语言是一个 强类型语言 。
所有变量,必须先声明类型 ,后使用 。 指定类型的变量只能装 该类型对应的数据 。
1、定义
【修饰符】类型 field名 = 默认值;
2、变量的声明、赋值、使用、修改
声明 :向栈内存 申请空间 。
对于基本类型 的变量(如:int、float 等),声明时系统会为其分配固定的内存空间。
如:int 类型占用 4 字节,double 类型占用 8 字节。 对于引用类型 的变量(如:对象、数组等),声明时不会直接分配内存来存储数据 。
而是分配一个存储引用值的内存空间。 这个引用指向实际对象 或数组的内存地址 。 赋值 :向内存中填内容 。
new 指令就是向 堆内存申请空间,并为 成员变量 赋予默认值 ,此时对象处于半初始化状态 。
使用 :通过名字调用内存中的值 。修改 :用新的值替代旧的值 。
int vacationDays;
vacationDays = 12 ;
int vacationDays1 = 12 ;
3、局部变量(可以有的修饰符:final)
方法中的 参数 、方法或 语句块内部定义的 变量 。
方法里的局部变量,仅在该方法内有效。 代码块里的局部变量,仅在代码块内有效。 形参,在整个方法内有效。
规则:
声明一个局部变量 后,必须用赋值语句 显式地初始化 变量。
在使用局部变量 之前,必须显式初始化 它们,否则将发生编译错误 。
public class Example {
public static void main ( String [ ] args) {
int x;
System . out. println ( x) ;
}
}
在 Java 10 中,如果可以从变量的初始值 推导出变量 的数据类型 。
那么,可以用 var 关键字 声明局部变量 ,而无须指定数据类型 。
即:从等号右边 明显看出数据类型 ,在这种情况下都可以使用 var 表示法。 注意:var 关键字 只能用于方法 中的局部变量 ,参数 和字段 的数据类型 必须声明 。
var date = new Date ( ) ;
4、实例变量 / 对象属性
从有实例开始,实例变量就存在了。 实例被销毁,实例变量就不存在了。 0~N个,程序每创建 一个实例,系统就为实例变量分配一块内存。
规则:系统会为成员变量执行默认的初始化。
整型初始化为 0 浮点型初始化为 0.0 boolean 类型初始化为 false char 类型的初始化为 ‘\u0000’ 引用数据类型初始化为 null 。
5、类变量 / 静态属性 / 类属性
从类开始,类变量就存在了。 一个 JVM 里,类信息只有一个。 每个 JVM 最多只加载一个类一次,系统只为类变量分配一块内存。
规则:系统会为成员变量执行默认的初始化。
整型初始化为 0 浮点型初始化为 0.0 boolean 类型初始化为 false char 类型的初始化为 ‘\u0000’ 引用数据类型初始化为 null 。
public class AboutNull {
static int staticFiled = 123 ;
int ordinaryFiled = 123 ;
private static void staticMethod ( ) { System . out. println ( "静态方法:staticMethod" ) ; }
private void ordinaryMethod ( ) { System . out. println ( "普通方法:ordinaryMethod" ) ; }
public static void main ( String [ ] args) {
AboutNull aboutNull = null ;
System . out. println ( aboutNull instanceof AboutNull ) ;
aboutNull. staticMethod ( ) ;
System . out. println ( aboutNull. staticFiled) ;
System . out. println ( aboutNull. ordinaryFiled) ;
aboutNull. ordinaryMethod ( ) ;
aboutNull = new AboutNull ( ) ;
System . out. println ( aboutNull instanceof AboutNull ) ;
}
}
注意:当程序 通过实例来访问 类变量 时----由于类变量本身就不属于实例 。
6、为什么成员变量命名不建议用 isXXX?