基础篇-1.2Java世界的规章制度(上)
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字符串,一种特殊的包装类数据。
相关文章