目录
第一章:注释
1.1 概述
1.2 Java 中的注释
第二章:关键字
2.1 概述
2.2 Java 中的关键字
第三章:标识符
3.1 概述
3.2 标识符的命名规则(必须遵守)
3.3 标识符的命名规范
第四章:数据类型以及包装类型的常量池技术
4.1Java 中的基本数据类型
4.2浮点型系列
4.3包装类型的常量池技术
Integer 缓存源码:
Character 缓存源码:
Boolean 缓存源码:
4.4自动装箱与拆箱原理
什么是自动拆装箱
第五章:变量
5.1 变量的概念
5.2 变量的作用
5.3 变量的三要素
5.4 变量的作用域
5.5 变量使用的注意事项
5.6 变量的声明、赋值和使用语法
5.6.1 变量的声明语法
5.6.2 变量的赋值语法
5.6.3 变量的使用语法
第六章:两种常见的输出语句
第七章:基本数据类型转换
7.2 自动类型转换(隐式类型转换)
7.3 强制类型转换(显示类型转换)
7.4 特殊的数据类型转换
第一章:注释
1.1 概述
- 注释就是对代码的解释和说明。
- 注释的目的是让人们能够更加轻松的了解代码,为代码添加注释,是十分必要的,它不会影响程序的编译和执行。
1.2 Java 中的注释
- Java 中的注释有
单行注释
、多行注释
和文档注释
三种。
- 单行注释:以
//
开头,以换行
结束,格式如下:
// 注释内容
- 多行注释:以
/*
开头,以*/
结尾,格式如下:
/* 注释内容 */
- 文档注释:以
/**
开头,以*/
结尾,格式如下:
/** 注释内容 */
javadoc
命令可以抽取每个类、方法中的文档注释,生成API
手册。
- 示例:
package day02; /** * 这里是一个文档注释,通常包括对类或方法的介绍,还有作者、日期等信息。 * * @author 作者 * @version 1.0 * @since 2022-11-15 */ public class HelloWorld { /* 多行注释:注释内容可以分很多行编写。 注意:多行注释不能嵌套,嵌套会导致多行注释提前结束。 main函数是整个程序的入口。 main函数的声明格式是固定的。 每一个类中最多只有一个main函数。 */ public static void main(String[] args) { // 单行注释:在命令行窗口打印一句话 // 单行注释仅对当前行有效 System.out.println("Hello World"); } }
第二章:关键字
2.1 概述
- 关键字是指在程序中,Java 已经定义好的单词,具有特殊含义。
- 关键字的特点:全都是
小写字母
。
2.2 Java 中的关键字
注意:
- 关键字一共50个,其中
const
和goto
是保留字。
true
、false
和null
看起来像关键字,但从技术角度,它们是特殊的布尔值和空值。
第三章:标识符
3.1 概述
- 简单的讲,凡是程序员自己命名的部分都可以称为标识符。换言之,给类、变量、方法、包等命名的字符序列就是标识符。
3.2 标识符的命名规则(必须遵守)
- 规则是硬性规定,一旦违反,程序就会在编译过程中报错。
- ① Java 中的标识符只能使用
26
个英文字母大小写,0~9
的数字,下划线_
和美元符号$
。
- ② 不能使用 Java 的关键字或保留字和特殊值。
- ③ 数字不能开头。
- ④ 不能包含空格。
- ⑤ 严格区分大小写。
3.3 标识符的命名规范
- 规范是柔性规范:违反规范,不会导致编译报错,但是如果不遵守基本的规范,可能会被大家鄙视。
- ① 见名知意。
- ② 类名、接口名等:每个单词的首字母都大写,形式:
XxxYyyZxx
。
- ③ 变量、方法名等:从第二个单词开始首字母大写,其余字母小写,形式:
xxxYyyZzz
。
- ④ 包名等:每一个单词都小写,单词之间使用点
.
分隔,形式:com.github
。
- ⑤ 常量名等:每一个单词都大写,单词之间使用下划线
_
分隔,形式:XXX_YYY_ZZZ
。
第四章:数据类型以及包装类型的常量池技术
4.1Java 中的基本数据类型
Java 中有 8 种基本数据类型,分别为:
- 6 种数字类型:
-
- 4 种整数型:byte、short、int、long
-
- 2 种浮点型:float、double
- 1 种字符类型:char
- 1 种布尔型:boolean。
这 8 种基本数据类型的默认值以及所占空间的大小如下:
基本类型 | 位数 | 字节 | 默认值 | 取值范围 |
byte | 8 | 1 | 0 | -128 ~ 127 |
short | 16 | 2 | 0 | -32768 ~ 32767 |
int | 32 | 4 | 0 | -2147483648 ~ 2147483647 |
long | 64 | 8 | 0L | -9223372036854775808 ~ 9223372036854775807 |
char | 16 | 2 | 'u0000' | 0 ~ 65535 |
float | 32 | 4 | 0f | 1.4E-45 ~ 3.4028235E38 |
double | 64 | 8 | 0d | 4.9E-324 ~ 1.7976931348623157E308 |
boolean | 1 | |||
false | true、false |
对于 boolean,官方文档未明确定义,它依赖于 JVM 厂商的具体实现。逻辑上理解是占用 1 位,但是实际中会考虑计算机高效存储因素。
另外,Java 的每种基本类型所占存储空间的大小不会像其他大多数语言那样随机器硬件架构的变化而变化。这种所占存储空间大小的不变性是 Java 程序比用其他大多数语言编写的程序更具可移植性的原因之一(《Java 编程思想》2.2 节有提到)。
4.2浮点型系列
- ① float :单精度浮点型
-
- 占内存:
4 Byte
。
- 占内存:
-
- 精度:
科学计数法的小数点后6~7位
。
- 精度:
注意:如果要表示某个常量小数是 float 类型,那么需要在数字后面加 f
或 F
,否则就是 double 类型。
- ② double :双精度浮点型
-
- 占内存:
8 Byte
。
- 占内存:
-
- 精度:
科学计数法的小数点后15~16位
。
- 精度:
注意:
- Java 里使用 long 类型的数据一定要在数值后面加上 L,否则将作为整型解析。
char a = 'h'
char :单引号,String a = "hello"
:双引号。
这八种基本类型都有对应的包装类分别为:Byte
、Short
、Integer
、Long
、Float
、Double
、Character
、Boolean
。
包装类型不赋值就是 Null ,而基本类型有默认值且不是 Null。
另外,这个问题建议还可以先从 JVM 层面来分析。
基本数据类型直接存放在 Java 虚拟机栈中的局部变量表中,而包装类型属于对象类型,对象实例都存在于堆中。相比于对象类型, 基本数据类型占用的空间非常小。
《深入理解 Java 虚拟机》 :局部变量表主要存放了编译期可知的基本数据类型 (boolean、byte、char、short、int、float、long、double)、对象引用(reference 类型,它不同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)。
4.3包装类型的常量池技术
Java 基本类型的包装类的大部分都实现了常量池技术。
Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character
创建了数值在 [0,127] 范围的缓存数据,Boolean 直接返回 True or False。
Integer 缓存源码:
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } private static class IntegerCache { static final int low = -128; static final int high; static { // high value may be configured by property int h = 127; } }
Character 缓存源码:
public static Character valueOf(char c) { if (c <= 127) { // must cache return CharacterCache.cache[(int)c]; } return new Character(c); } private static class CharacterCache { private CharacterCache(){} static final Character cache[] = new Character[127 + 1]; static { for (int i = 0; i < cache.length; i++) cache[i] = new Character((char)i); } }
Boolean 缓存源码:
public static Boolean valueOf(boolean b) { return (b ? TRUE : FALSE); }
如果超出对应范围仍然会去创建新的对象,缓存的范围区间的大小只是在性能和资源之间的权衡。
两种浮点数类型的包装类 Float
,Double
并没有实现常量池技术。
Integer i1 = 33; Integer i2 = 33; System.out.println(i1 == i2);// 输出 true Float i11 = 333f; Float i22 = 333f; System.out.println(i11 == i22);// 输出 false Double i3 = 1.2; Double i4 = 1.2; System.out.println(i3 == i4);// 输出 false
下面来看一下问题。下面的代码的输出结果是 true 还是 false 呢?
Integer i1 = 40; Integer i2 = new Integer(40); System.out.println(i1==i2);
Integer i1=40
这一行代码会发生装箱,也就是说这行代码等价于 Integer i1=Integer.valueOf(40)
。因此,i1
直接使用的是常量池中的对象。而Integer i2 = new Integer(40)
会直接创建新的对象。
因此,答案是 false 。
记住:所有整型包装类对象之间值的比较,全部使用 equals 方法比较。
4.4自动装箱与拆箱原理
什么是自动拆装箱
- 装箱:将基本类型用它们对应的引用类型包装起来;
- 拆箱:将包装类型转换为基本数据类型;
举例:
Integer i = 10; //装箱 int n = i; //拆箱
上面这两行代码对应的字节码为:
L1 LINENUMBER 8 L1 ALOAD 0 BIPUSH 10 INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer; PUTFIELD AutoBoxTest.i : Ljava/lang/Integer; L2 LINENUMBER 9 L2 ALOAD 0 ALOAD 0 GETFIELD AutoBoxTest.i : Ljava/lang/Integer; INVOKEVIRTUAL java/lang/Integer.intValue ()I PUTFIELD AutoBoxTest.n : I RETURN
从字节码中,可以发现装箱其实就是调用了 包装类的valueOf()
方法,拆箱其实就是调用了 xxxValue()
方法。
因此,
Integer i = 10
等价于Integer i = Integer.valueOf(10)
int n = i
等价于int n = i.intValue();
注意:如果频繁拆装箱的话,也会严重影响系统的性能。应该尽量避免不必要的拆装箱操作。
第五章:变量
5.1 变量的概念
- 变量:在程序执行的过程中,其值可以发生改变的量。
5.2 变量的作用
- 变量的作用:用来存储数据,代表内存的一块存储区域,这块内存中的值是可以改变的。
5.3 变量的三要素
- 数据类型。
- 变量名。
- 值。
5.4 变量的作用域
- 概念:一个变量的有效范围。
- 变量必须在有效范围内使用。
- 具体范围:在 Java 语言中,变量的作用域就是它所在的一组
{}
。
- 错误示例:
public class VariableDemo{ public void method(){ { boolean flag = true; } System.out.println(flag);// 此处代码有问题 } }
5.5 变量使用的注意事项
- ① 先声明后使用。
- ② 在使用之前必须初始化(看情况,如果是类属性,系统会根据其数据类型,自动赋予初始化值)。
- ③ 变量有作用域。
- ④ 在同一个作用域中不能有同样的变量名,换言之,一个变量在作用域中只能使用一次。
5.6 变量的声明、赋值和使用语法
5.6.1 变量的声明语法
- 语法:
数据类型 变量名;
- 示例:
package day02; /** * 变量 * * @author GUO * @version 1.0 * @since 2022-11-15 13:22 */ public class VariableDemo { public static void main(String[] args) { // 声明变量 int age; String name; double weight; char gender; boolean isMarry; } }
5.6.2 变量的赋值语法
- 语法:
变量名 = 值;
- 示例:
package day02; /** * 变量 * * @author GUO * @version 1.0 * @since 2022-11-15 13:22 */ public class VariableDemo { public static void main(String[] args) { // 声明变量 int age; String name; double weight; char gender; boolean isMarry; // 赋值 age = 18; name = "许大仙"; weight = 80.20; gender = '男'; isMarry = false; } }
5.6.3 变量的使用语法
- 语法:
通过变量名直接引用
- 示例:
package day02; /** * 变量 * * @author GUO * @version 1.0 * @since 20212-11-15 13:22 */ public class VariableDemo { public static void main(String[] args) { // 声明变量 int age; String name; double weight; char gender; boolean isMarry; // 赋值 age = 18; name = "许大仙"; weight = 80.20; gender = '男'; isMarry = false; // 变量的使用 System.out.println(age); System.out.println(name); System.out.println(weight); System.out.println(gender); System.out.println(isMarry); } }
第六章:两种常见的输出语句
- 换行输出语句:输出内容,完毕后进行换行,格式如下:
System.out.println("输出内容");
- 直接输出语句:输出内容,完毕后不做任何处理,格式如下:
System.out.print("输出内容");
注意事项:
- ① 换行输出语句,括号内可以什么都不写,只做换行处理。
- ② 直接输出语句,括号内什么都不写,直接报错。
- ③ 如果输出语句的括号内有多向内容,那么必须使用
+
连接起来。
- ④ 如果某些内容想要原样输出,就用
""
引起来;如果想要输出变量中额内容,则不要将变量名用""
引起来。
- 示例:
package day02; /** * 打印输出语句 * * @author GUO * @version 1.0 * @since 2022-11-15 13:22 */ public class PrintDemo { public static void main(String[] args) { // 带有换行效果的输出 System.out.println("Hello Java"); // 不带有换行效果的输出 System.out.print("Hello Java"); System.out.print("Hello Java"); // 调用print()函数的时候,不传参数,编译直接报错 // System.out.print(); // "age"是一个字面量,也可以说是一个字符串常量 System.out.println("age"); int age = 18; // age是一个变量,在打印语句中会输出这个变量的值 System.out.println(age); // 输出很多内容的时候,可以使用 + 做字符串连接 System.out.println("age = " + age); } }
第七章:基本数据类型转换
7.1 概述
●在 Java 程序中,不同的基本数据类型的值经常需要进行互相转换,Java 语言所提供的七种数值类型之间可以相互转换,基本数据类型转换有两种方式:自动类型转换 和 强制类型转换 。
7.2 自动类型转换(隐式类型转换)
●自动类型转换的概念:将取值范围小的类型 自动提升为 取值范围大的类型 。
●基本数据类型的转换规则如下所示:
●自动类型转换的场景:
●① 当将存储范围小的值(常量值、变量值、表示式计算的结果值)赋值给存储范围大的变量时:
int i = 'A'; //char自动升级为int double d = 10; // int自动升级为double byte b = 127; // 右边的整数常量值必须在 -128 ~ 127 范围内 long num = 12345678; // 右边的整数常量如果在int范围内,编译和运行都可以通过,这里涉及到数据类型转换 long bigNum = 1234567898103433433L; // 右边的整数常量值如果超过int范围,必须加L,否则编译不通过
●② 当存储范围小的数据类型和存储范围大的数据类型一起混合运算时,会先转换为存储范围大的数据类型,然后再计算:
int i = 10; byte b = 10; double d = 10; double sum = i + b + d; System.out.println(sum); // 混合运算,升级为double
●③ 当 byte 、short 、char 数据类型进行算术运算的时候,会按照 int 类型处理:
byte b1 = 1; byte b2 = 2; // byte b3 = b1 + b2; // 编译报错,b1 + b2 自动升级为int char c1 = '0'; char c2 = 'A'; System.out.println(c1 + c2); // 113
●④ boolean 类型不参与。
7.3 强制类型转换(显示类型转换)
●强制类型转换:将 取值范围大的类型 强制转换成 取值范围小的类型 。
●语法:
注意:强制类型转换可能会损失精度或溢出。
●强制类型转换的场景:
●① 当将存储范围大的值(常量值、变量值、表示式计算的结果值)赋值给存储范围小的变量时:
inti=(int) 3.14;// 强制类型转换,损失精度
doubled= 1.2; intnum=(int)d;// 损失精度
inti=200; byteb=(byte)i; System.out.println("b = "+b);// 溢出 -56
●② boolean 类型不参与。
●③ 当某个值想要提升数据类型的时候,也可以使用强制数据类型:
inti=1; intj=2; doubled=(double)i/j; System.out.println(d);
注意:③ 场景下的强制类型转换是没有风险的。
7.4 特殊的数据类型转换
●① 任意数据类型的数据和 String 类型进行 + 运算的时候,结果一定是 String 类型。
System.out.println(""+1+2);//12
●② String 类型不能强制类型转换,转为其他类型:
Stringstr="123"; intnum=(int)str;// 错误
Stringstr="123"; intnum=Integer.parseInt(str);// 正确