1 Java 标识符
在 Java 语言中, 有类, 对象, 方法, 变量, 接口和自定义数据类型等等, 他们的名字并不是确定的, 需要我们自己命名. 而 Java 标识符就是用来给类, 对象, 方法, 变量, 接口和自定义数据类型命名用的.
命名规则说明:
标识符可以由字母, 数字, 下划线 (_), 美元符($) 组成, 但不包含 @,#, 空格等其他特殊字符, 不能以数字开头. 例如: 1name 是不合法的. 注意: Java 标识符是可以允许中文命名的, 因为 Java 内部使用了 Unicode 字符集.
标识符不能是 Java 关键字和保留字(Java 预留的关键字, 以后的 Java 升级版本中可能作为关键字), 但可以包含关键字和保留字. 例如: 不可以使用 for 作为标识符, 但是 myfor 是可以的.
标识符是严格区分大小写的, 同时也没有长度的限制. 例如: Myfor 和 myfor 是两个不同的标识符.
标识符的命名也不能随意而为, 最好是能反映其作用的, 做到看其名知其意.
Java 语言中具有特殊用途的词, 被称为关键字. Java 中常用的关键字, 如下所示:
abstract | extends | break | byte | case | catch |
char | class | continue | default | do | double |
else | if | boolean | false | true | public |
interface | long | int | float | short | void |
final | finally | try | for | static | this |
null | return | new | import | throw | throws |
switch | super | while | do | private | protected |
package | instanceof | native | implements | synchronized | volatile |
下面这个 Java 代码中的标识符, 由于错误命名的标识符, 导致这个 Java 文件不能编译成功, 会直接报标识符相关的错误.
- public class MyFirst {
- /**
- * 错误命名的标识符
- */
- String 1a = "test";
- String u#a = "test";
- String u@a = "test";
- String void = "test";
- String b a = "test";
- /**
- * 正确命名的标识符
- */
- String _a = "test";
- String $a = "test";
- String aa = "test";
- public static void main(String[] args) {
- System.out.println("Hello World!");
- }
- }
2 Java 数据类型
Java 是一种强类型语言, 每一个变量都必须声明其类型. Java 的数据类型分有两大类: 基本类型 (又称内置数据类型) 和引用类型.
2.1 基本类型
Java 提供了八种基本类型, 其中有六种数字类型(四个整数型, long,short,int 和 byte, 两个浮点型, float 和 double), 一种字符型, char, 还有一种布尔型, boolean.
2.1.1 整数型
byte
byte 数据类型是 8 位, 有符号的, 以二进制补码表示的整数, 默认值是 0, 在 Java 中占用 1 个字节.
其可以以 8 位, 即 8 个 0,1 表示. 8 位的第一位是符号位, 即 0000 0001 表示数字 1,1000 0000 表示 - 1. 所以其最大值是 0111 1111, 即 127(2^7-1); 最小值是 1111 1111, 即 - 128(-2^7). 从而可以知道, Java 中一个 byte 字节的范围是 - 128~127.
例子:
- byte a = 10;
- byte b = -10;
注意: 其他的整数型, 如 short,int 和 long, 也是类似的用法, 都可以以位数 0,1 表示, 均有最大值和最小值, 区别就是它们的位数不同.
short
short 数据类型是 16 位, 有符号的, 以二进制补码表示的整数, 其默认值是 0, 在 Java 中占用 2 个字节.
其可以以 16 位, 即 16 个 0,1 表示. 最大值是 32767(2^15 - 1), 最小值是 - 32768(-2^15).
例子:
- short a = 10000;
- short b = -10000;
- int
int 数据类型是 32 位, 有符号的, 以二进制补码表示的整数, 其默认值是 0, 在 Java 中占用 4 个字节.
其可以以 32 位, 即 32 个 0,1 表示. 最大值是 2,147,483,647(2^31 - 1), 最小值是 - 2,147,483,648(-2^31).
例子:
- int a = 1000;
- int b = -1000;
- long
long 数据类型是 64 位, 有符号的, 以二进制补码表示的整数, 其默认值是 0L, 在 Java 中占用 8 个字节.
其可以以 64 位, 即 64 个 0,1 表示. 最大值是(2^63-1), 最小值是(-2^63).
注意: 声明 long 类型, 最好是后面加上 "l" 或 "L", 例如:
- long a = 10000000;// 这样声明不会出错, 因为在 int 数据类型的范围内(21 亿内)
- long b = 100000000000000;// 这样就肯定会报错, 因为已经超过了 int 的范围, 必须改成 100000000000000L 才不会报错
2.1.2 浮点型
float
float 数据类型, 又被称为单精度类型, 是单精度, 32 位, 符合 IEEE 754 标准的浮点数, 尾数可以精确到 7 位有效数字, 而最后一位第八位是存在舍入误差不精确的, 其默认值是 0.0f, 在 Java 中占用 4 个字节.
float 数据类型的好处是在储存大型浮点数组的时候可节省内存空间, 但是不能用来表示精确的值, 如货币.
例子:
- float f = 123.3f;
- double
double 数据类型, 又被称为双精度类型, 是双精度, 64 位, 符合 IEEE 754 标准的浮点数, 精确程度是 float 的两倍, 即可精确到 16 位有效数字, 而最后一位第 17 位是存在舍入误差不精确的, 其默认值是 0.0d, 在 Java 中占用 8 个字节.
例子:
double d = 222.2;
注意: 浮点数的默认类型为 double 类型, 但是 double 数据类型同样不能用来表示精确的值, 如货币. 如果需要精确的数字计算, 可以使用 BigDecimal 类.
科学计数法
一种计数的方法, 通常用来表示比较大的数据, 其中的 E 或 e, 表示 10 的几次方. 如, 314e2, 表示 314 * 10^2, 即 31400;314e-2, 表示 314 * 10^-2, 即 3.14.
这种方法在 Java 中也是适用的.
- float f = 314e-2f; // 314 * 10^-2
- double d = 3.14e4; // 3.14 * 10^4
- System.out.println(f); // 输出 3.14
- System.out.println(d); // 输出 31400.0
2.1.3 字符型
char
char 类型是单一的 16 位 Unicode 字符, 占 2 个字节, 可以存储任何字符, 最大值是 \uffff(即为 65,535), 最小值是 \u0000(即为 0).
例子:
char a = 'A';
注意: 单引号是用来表示字符常量的, 例如'A'是一个字符, 它与 "A" 是不同的,"A" 表示含有一个字符的字符串.
char 类型是可以用来计算的, 因为 char 在 ASCII 等字符编码表中是有对应的数值的. 而在 Java 中的 char 类型字符运算时, 是直接当做 ASCII 表对应的整数来对待的.
- char a = 'A';
- int b = 1;
- int c = a+b;
- System.out.println(c); // 输出 66
Java 语言中还允许使用转义字符'\'来将其后的字符转位其他的含义, 例如, char c = '\n';// 表示换行符
下面列举一些比较常见的转义符.
转义符 | 含义 | Unicode 值 |
\n | 换行 | \u000a |
\r | 回车 | \u000d |
\t | 制表符(tab 键) | \u0009 |
\" | 双引号 | \u0022 |
\' | 单引号 | \u0027 |
\\ | 反斜杠 | \u005c |
2.1.4 布尔型
boolean 类型表示一位信息, 注意不是一个字节. 其只有两个值, true 和 false, 默认值是 false.
例子:
boolean a = true;
boolean 类型只是用来判断逻辑条件, 一般用于 if,while,do while.
2.2 引用类型
Java 为每种基本类型都提供了对应的封装类型(即引用类型):Byte,Short,Integer,Long,Float,Double,Character 和 Boolean. 引用类型就是一种对象类型, 它的值是指向内存空间的引用, 即类似于 c 语言中指针指向地址. 其实这里的引用还跟变量, 栈和堆是有关系的, 但是这不是本节的关键, 后续会有专门的一节来说明.
Java 中的引用类型还分有四种, 分别是强引用 (StrongReference), 软引用(SoftReference), 弱引用(WeakReference) 和虚引用 (PhantomReference). 其中, 强引用是我们使用最普遍的引用, 如果一个对象具有强引用, 那垃圾回收器宁愿抛出 OOM(OutOfMemoryError) 也不会回收它.
强引用(StrongReference)
这种引用是平时开发中最常用的, 例如 String strong = new String("Strong Reference") . 当一个实例对象具有强引用时, 垃圾回收器不会回收该对象, 当内存不足时, 宁愿抛出 OutOfMemeryError 异常也不会回收强引用的对象, 因为 JVM 认为强引用的对象是用户正在使用的对象, 它无法分辨出到底该回收哪个, 强行回收有可能导致系统严重错误.
软引用(SoftReference)
如果一个对象只有软引用, 那么只有当内存不足时, JVM 才会去回收该对象, 其他情况不会回收.
如下例子, 一般情况下内存充足的话, ss 指向的对象是不会被回收, 但是若内存不足则会把 ss 给回收掉.
- Book ss = new Book("NONO");
- SoftReference<Book> softReference = new SoftReference<>(ss);
- ss = null;
- System.gc();
- System.out.println("对象是否被回收:"+softReference.get());
软引用可以结合 ReferenceQueue 来使用, 当由于系统内存不足, 导致软引用的对象被回收了, JVM 会把这个软引用加入到与之相关联的 ReferenceQueue 中.
如下例子, 当系统内存不足时, 触发 gc, 这个 Book 就会被回收, 但 reference 将不会为 null.
- ReferenceQueue referenceQueue = new ReferenceQueue();
- SoftReference<Book> softReference = new SoftReference<>(new Book(), referenceQueue);
- Book book = softReference.get();
- Reference reference = referenceQueue.poll();
弱引用(WeakReference)
只有弱引用的对象, 当 JVM 触发 gc 时, 就会回收该对象. 与软引用不同的是, 不管是否内存不足, 弱引用都会被回收. 弱引用可以结合 ReferenceQueue 来使用, 当由于系统触发 gc, 导致软引用的对象被回收了, JVM 会把这个弱引用加入到与之相关联的 ReferenceQueue 中, 不过由于垃圾收集器线程的优先级很低, 所以弱引用不一定会被很快回收.
虚引用(PhantomReference)
虚引用是所有类型中最弱的一个. 一个持有虚引用的对象, 和没有引用几乎是一样的, 随时可能被垃圾回收器回收. 当试图通过虚引用的 get()方法取得强引用时, 总是会失败. 并且, 虚引用必须和引用队列一起使用, 它的作用在于跟踪垃圾回收过程.
当垃圾回收器准备回收一个对象时, 如果发现它还有虚引用, 就会在垃圾回收后, 销毁这个对象, 将这个虚引用加入引用队列. 程序可以通过判断引用队列中是否已经加入了虚引用, 来了解被引用的对象是否将要被垃圾回收. 如果程序发现某个虚引用已经被加入到引用队列, 那么就可以在所引用的对象的内存被回收之前采取必要的行动.
2.3 基本数据类型转换
2.3.1 自动类型转换
所谓自动类型转换, 总结起来就是一句话, 容量小的数据类型可以自动转换位容量大的数据类型.
例如, byte 类型可以自动转换为其他容量比它大的数字类型(如 int,short,float 等等). 下面直接看一个实例, 一切就清晰了.
- public class MyFirst {
- public static void main(String[] args) {
- byte a = 5;
- short b = 5;
- int c = 5;
- long d = 5;
- float e = 5.0f;
- double f = 5.0;
- // 测试自动类型转换, 容量最小的是 byte, 容量最大的是 double, 从小容量自动转换为大容量且不报错
- double g = a + b + c + d + e + f;
- System.out.println(g);
- }
- }
若在上面的例子中, 把最后的输出 g 的数据类型改为 float 类型 float g = a + b + c + d + e + f; , 则肯定会编译不通过, 报错 cannot convert from double to float .
2.3.2 强制类型转换
强制类型转换, 又称为显示类型转换, 即在其值符合被强制转换的类型的情况下, 我们可以将其强制转换为该类型. 下面看个实例便清楚了.
- public class MyFirst {
- public static void main(String[] args) {
- int a = 5;
- short b = (short) a;// 此处若没有 (short) 强制转换, 则肯定会编译不通过的
- System.out.println(b);
- }
- }
我们再回到 2.3.1 看下这个例子, 把 g 的数据类型改为 float 类型 float g = a + b + c + d + e + f; , 其实这里就只是因为 f 是 double 类型, 如果我们改成这样 float g = a + b + c + d + e + (float)f; , 将 f 的数据类型强制转换为 float, 程序就可以正常运行了.
其实强制类型转换, 还包括了引用类型的强制转换, 不过这里不说明, 后面在讲类的继承和接口实现的时候会讲到.
2.4 Java 字符串(String)
String 是一个特殊的包装类数据, 可以用 String str = new String("Java"); 的形式来创建, 也可以用 String str = "Java"; 的形式来创建. 但是, 他们的创建过程是不一样的, 下面具体说明下他们不一样的创建过程.
String str = "Java"; 的创建过程: 首先在常量池中查找是否存在内容为 "Java" 的字符串对象; 若不存在则会在常量池中创建一个 "Java" 的字符串对象, 并让 str 引用该对象; 若 "Java" 的字符串对象已经存在常量池中, 则会直接让 str 引用该对象.
注意: 常量池属于类信息的一部分, 而类信息是存在于 JVM 内存模型的方法区, 即常量池是存在于 JVM 的方法区的, 当类编译时就会被分配到内存中.
String str = new String("Java"); 的创建过程:
(1)定义一个 str 的 String 类型的引用并存放在栈中;
(2)在字符串常量池中判断是否存在内容为 "Java" 的字符串对象, 若不存在的话则在常量池中创建一个, 若存在则不需要创建;
(3)执行 new 操作, 在堆中创建一个指定的对象 "Java", 需要注意的是, 这里堆的对象是字符串常量池中 "Java" 对象的一个拷贝对象;
(4)让 str 指向堆中的 "Java" 对象, 即 str 存储的是堆中 "Java" 对象的地址.
下面举个例子, 让我们看得更加通透.
- public class MyFirst {
- public static void main(String[] args) {
- String a = "Java";
- String b = "Java";
- String c = new String("Java");
- String d = new String("Java");
- System.out.println(a==b); // true 因为均是指向常量池中的同一个对象
- System.out.println(a.equals(b));// true 因为他们的值相同
- System.out.println(c==d); // false 因为他们在栈中存储的地址不一样, 在堆中指向的对象也不一样
- System.out.println(c.equals(d));// true 因为他们的值相同
- }
- }
图解如下:
字符串的常用方法
返回类型 | 方法 | 说明 |
String | concat(String str) | 字符串的连接,将 str 字符串拼接到原来字符串的后面,并返回。 |
int | length() | 返回字符串的长度,这里的长度是指字符串中 Unicode 字符的数目。 |
char | charAt(int index) | 索引特定位置的字符,并返回该字符。 |
boolean | equals(Object anObject) | 字符串的比较,比较两个字符串的值是否相等,若相等则返回 true,否则返回 false。 |
int | compareTo(String anotherString) | 字符串的比较,比较两个字符串的值大小,若原有值大则返回大于 0 的整数,若原有值小则返回小于 0 的整数,若他们相等则返回 0。 |
String | substring(int beginIndex) substring(int beginIndex, int endIndex) | 从字符串中截取子字符串,从 beginIndex 位置起,到 endIndex 位置为止,但不包括 endIndex 位置的字符,截取子字符串,返回子字符串。 |
int | indexOf(int ch) indexOf(int ch, int fromIndex) indexOf(String str) indexOf(String str, int fromIndex) | 从字符串中获取对应字符第一次出现的位置,若整个字符串都没有该字符,则返回 - 1。 |
String | trim() | 去除原字符串的前后空格并返回。 |
下面看下这些常用方法对应的例子.
- public class MyFirst {
- public static void main(String[] args) {
- String a = "I like Java";
- String b = "very much!";
- System.out.println(a.concat(b));// a 和 b 字符串的拼接, 输出: I like Java very much!
- String c = "abc123";
- System.out.println(c.length());// c 字符串的长度, 输出: 6
- System.out.println(c.charAt(2));// 索引 c 字符串中的 2 位置的字符, 输出: c
- System.out.println(c.substring(2));// 截取从 2 位置开始到结尾的字符串, 输出: c123
- System.out.println(c.indexOf("b"));// 获取字符为 b 的第一次出现的位置, 输出: 1
- String d = "Java";
- String e = "Java";
- String f = "Java1";
- System.out.println(d.equals(e));// 比较 d 和 e 的值, 输出: true
- System.out.println(d.equals(f));// 比较 d 和 f 的值, 输出: false
- System.out.println(d.compareTo(e));// 比较 d 和 e 的值, 输出: 0
- System.out.println(d.compareTo(f));// 比较 d 和 f 的值, 输出:-1
- String g = "asdfgh";
- System.out.println(g.trim());// 去掉 g 的前后空格, 输出: asdfgh
- }
- }
3 总结
Java 标识符的命名, 以及 Java 关键字.
Java 数据类型, 分有基本类型和引用类型.
基本类型, 有六种数字类型(四个整数型, long,short,int 和 byte, 两个浮点型, float 和 double), 一种字符型, char, 还有一种布尔型, boolean.
引用类型, 有强引用, 软引用, 弱引用和虚引用, 其中我们平常普遍用到的就是强引用.
基本数据类型转换, 有自动类型转换和强制类型转换.
String 字符串, 一种特殊的包装类数据.
来源: https://www.cnblogs.com/sky-yemeng/p/11178460.html