目录
第一章:注释
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 特殊的数据类型转换
单行注释
、 多行注释
和 文档注释
三种。//
开头,以 换行
结束,格式如下:// 注释内容
/*
开头,以 */
结尾,格式如下:/* 注释内容 */
/**
开头,以 */
结尾,格式如下:/**注释内容 */
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");} }
小写字母
。注意:
const
和 goto
是保留字。true
、 false
和 null
看起来像关键字,但从技术角度,它们是特殊的布尔值和空值。26
个英文字母大小写,0~9
的数字,下划线 _
和美元符号 $
。XxxYyyZxx
。xxxYyyZzz
。.
分隔,形式:com.github
。_
分隔,形式:XXX_YYY_ZZZ
。Java 中有 8 种基本数据类型,分别为:
这 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 Byte
。科学计数法的小数点后6~7位
。注意:如果要表示某个常量小数是 float 类型,那么需要在数字后面加 f
或 F
,否则就是 double 类型。
8 Byte
。科学计数法的小数点后15~16位
。注意:
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 类型,它不同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)。
Java 基本类型的包装类的大部分都实现了常量池技术。
Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character
创建了数值在 [0,127] 范围的缓存数据,Boolean 直接返回 True or False。
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 propertyint h = 127;} }
public static Character valueOf(char c) {if (c <= 127) { // must cachereturn 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);}}
public static Boolean valueOf(boolean b) {return (b ? TRUE : FALSE); }
如果超出对应范围仍然会去创建新的对象,缓存的范围区间的大小只是在性能和资源之间的权衡。
两种浮点数类型的包装类 Float
,Double
并没有实现常量池技术。
Integer i1 = 33; Integer i2 = 33; System.out.println(i1 == i2);// 输出 trueFloat i11 = 333f; Float i22 = 333f; System.out.println(i11 == i22);// 输出 falseDouble 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 方法比较。
举例:
Integer i = 10; //装箱 int n = i; //拆箱
上面这两行代码对应的字节码为:
L1LINENUMBER 8 L1ALOAD 0BIPUSH 10INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;PUTFIELD AutoBoxTest.i : Ljava/lang/Integer;L2LINENUMBER 9 L2ALOAD 0ALOAD 0GETFIELD AutoBoxTest.i : Ljava/lang/Integer;INVOKEVIRTUAL java/lang/Integer.intValue ()IPUTFIELD AutoBoxTest.n : IRETURN
从字节码中,可以发现装箱其实就是调用了 包装类的valueOf()
方法,拆箱其实就是调用了 xxxValue()
方法。
因此,
Integer i = 10
等价于 Integer i = Integer.valueOf(10)
int n = i
等价于 int n = i.intValue();
注意:如果频繁拆装箱的话,也会严重影响系统的性能。应该尽量避免不必要的拆装箱操作。
{}
。public class VariableDemo{public void method(){{boolean flag = true;}System.out.println(flag);// 此处代码有问题} }
数据类型 变量名;
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;} }
变量名 = 值;
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;} }
通过变量名直接引用
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 语言所提供的七种数值类型之间可以相互转换,基本数据类型转换有两种方式:自动类型转换 和 强制类型转换 。
●自动类型转换的概念:将取值范围小的类型 自动提升为 取值范围大的类型 。
●基本数据类型的转换规则如下所示:
●自动类型转换的场景:
●① 当将存储范围小的值(常量值、变量值、表示式计算的结果值)赋值给存储范围大的变量时:
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 自动升级为intchar c1 = '0'; char c2 = 'A'; System.out.println(c1 + c2); // 113
●④ boolean 类型不参与。
●强制类型转换:将 取值范围大的类型 强制转换成 取值范围小的类型 。
●语法:
注意:强制类型转换可能会损失精度或溢出。
●强制类型转换的场景:
●① 当将存储范围大的值(常量值、变量值、表示式计算的结果值)赋值给存储范围小的变量时:
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);
注意:③ 场景下的强制类型转换是没有风险的。
●① 任意数据类型的数据和 String 类型进行 + 运算的时候,结果一定是 String 类型。
System.out.println(""+1+2);//12
●② String 类型不能强制类型转换,转为其他类型:
Stringstr="123"; intnum=(int)str;// 错误
Stringstr="123"; intnum=Integer.parseInt(str);// 正确