基础篇-1.2Java世界的规章制度(上)

1 Java标识符

在Java语言中,有类、对象、方法、变量、接口和自定义数据类型等等,他们的名字并不是确定的,需要我们自己命名。而Java标识符就是用来给类、对象、方法、变量、接口和自定义数据类型命名用的。

命名规则说明:

  • 标识符可以由字母、数字、下划线(_)、美元符($)组成,但不包含@、#、空格等其他特殊字符,不能以数字开头。例如:1name 是不合法的。注意:Java标识符是可以允许中文命名的,因为Java内部使用了Unicode字符集。
  • 标识符不能是Java关键字和保留字(Java预留的关键字,以后的Java升级版本中可能作为关键字),但可以包含关键字和保留字。例如:不可以使用 for 作为标识符,但是 myfor 是可以的。
  • 标识符是严格区分大小写的,同时也没有长度的限制。例如:Myfor 和 myfor 是两个不同的标识符。
  • 标识符的命名也不能随意而为,最好是能反映其作用的,做到看其名知其意。

Java语言中具有特殊用途的词,被称为关键字。Java中常用的关键字,如下所示:

abstractextendsbreakbytecasecatch
charclasscontinuedefaultdodouble
elseifbooleanfalsetruepublic
interfacelongintfloatshortvoid
finalfinallytryforstaticthis
nullreturnnewimportthrowthrows
switchsuperwhiledoprivateprotected
packageinstanceofnativeimplementssynchronizedvolatile

下面这个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        因为他们的值相同
    }

}

图解如下:

《基础篇-1.2Java世界的规章制度(上)》

 

字符串的常用方法

返回类型方法说明
Stringconcat(String str) 字符串的连接,将str字符串拼接到原来字符串的后面,并返回。
intlength() 返回字符串的长度,这里的长度是指字符串中Unicode字符的数目。
charcharAt(int index) 索引特定位置的字符,并返回该字符。
booleanequals(Object anObject) 字符串的比较,比较两个字符串的值是否相等,若相等则返回true,否则返回false。
intcompareTo(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字符串,一种特殊的包装类数据。

 

点赞