基础
关键字
Java关键字是事先定义的,有特别意义的标识符,有时又叫保留字,还有特别意义的变量。
Java的关键字对Java的编译器有特殊的意义,他们用来表示一种数据类型,或者表示程序的结构等,关键字不能用作变量名、方法名、类名、包名和参数。
abstract | assert | boolean | break | byte |
---|---|---|---|---|
case | catch | char | class | const |
continue | default | do | double | else |
enum | extends | final | finally | float |
for | goto | if | implements | import |
instanceof | int | interface | long | native |
new | package | private | protected | public |
return | strictfp | short | static | super |
switch | synchronized | this | throw | throws |
transient | try | void | volatile | while |
具体含义可详见下面的附录表。
标识符
标识符:就是用来标识变量名、函数名、数组名、文件名、类名等的有效字符序列。
标识符的几条规则:
- Java语言规定的标识符只能是大写字母、小写字母、下划线(_)、数字、美元符号($)的任意组合,且第一个字母不能为数字以免与数值字面值产生混淆。
- 不能是
Java
关键字和保留字,但可以包含关键字和保留字,如:void
不合法,但Myvoid
合法。 - Java是大小写敏感的,标识符也不例外。
- 标识符没有长度限制。
注:从JDK8开始,不建议单独使用下划线作为标识符。
'_' should not be used as an identifier, since it is a reserved keyword from source level 1.8
拓展:
- 类名&接口:每个单词首字母大写,其他小写。(驼峰式命名)
- 方法&变量:以小写字母开头,如果方法名由多个单词组成,则从第二个单词开始首字母大写。
- 常量:常量名全部大写,各单词间以
“_”
连接。- 包名:全部小写。
常量
常量就是在程序的执行过程中其值不能改变的一个标识符。
在Java中,利用关键字final
指示常量,关键字final
表示这个变量只能被赋值一次。一旦被赋值之后,就不能够再更改了。习惯上,常量名使用全大写。
示例:
final int SCORE = 100;
变量
变量与常量是相反的,在执行过程中其值是可以改变的一个标识符。程序通过一个变量名来代表该变量存储的数据。变量都有一个作用域来定义变量的可见范围和生存期。
在Java中所有变量必须先声明后使用。变量声明的方法:
类型 标识符 = 值
- 类型:Java中的任何一种数据类型,可以是下面的八种数据类型,对象等
- 标识符:就是变量的名字,也可以理解成C++中的指针。
变量作用域
Java语言里大括号括起来的部分是一个代码块。代码块中的变量只在本代码块中可以使用,其嵌套的子代码块也可以使用。
注释
在Java的编写过程中我们需要对一些程序进行注释,除了自己方便阅读,更为别人更好理解自己的程序,所以我们需要进行一些注释,可以是编程思路或者是程序的作用,总而言之就是方便自己他人更好的阅读。
Java提供了三种注释方式:
-
//
注释一行 -
/* ...... */
注释若干行 -
/**……*/
文档注释
JDK提供了为自己的代码自动生成API网页的工具javadoc
,其可以对文档注释中的内容进行解析,然后转换HTML格式的帮助文档。
字面值
在Java中,常量的值是通过使用表示常量的字面值(literal)创建的。例如,下面是一些字面值:
100 98.6 'X' "This is a test"
从左向右,第一个字面值标识了一个整数,下一个是浮点数值,第三个是字符常量,最后面一个是字符串。在可以使用某种类型的值得任何地方,都可以使用对应类型的字面值。
拓展:
从JDK7开始,可以使用二进制指定整型字面值。为此,使用0b或0B作为数值的前缀。例如使用二进制字面值指定十进制10:
int x = 0b1010;
从JDK7开始,在整型字面值中还可以嵌入一个或多个下划线。嵌入下划线可以使越多很大的整数变得更加容易,当编译字面值时,会丢弃下划线。例如:
int x = 1_2345_6789;
注意:下划线只能用于分隔数字,不能位于字面值的开头和结尾。然而,在两个数字之间使用多个下划线是允许的。
基本数据类型
Java语言定义了八种基本数据类型,而这八种数据类型又可以分为以下四组:
- 整型:short、int、long 和 byte
- 浮点型:float 和 double
- 字符型:char
- 布尔型:boolean
整型
Java语言包含字节型(byte)、短整型(short)、整型(int)、长整型(long)四种,整数类型可以使用十进制、八进制、十六进制来表示,默认是十进制,其它进制表示方式:
- 0B表示二进制【JKD1.7】,首位以0B开始
- 017表示八进制,首位以0开始
- 0xAB表示十六进制数据,首位以0x开始
Java中的整型常量默认为int
型。若要声明long
型常量,则可以在末尾添加 L
。
整数类型 | 位数 | 值得范围 |
---|---|---|
byte | 8 | -128 ~127 |
short | 16 | -3_2768 ~ 3_2767 |
int | 32 | -21_4748_3648 ~ 21_4748_3647 |
long | 64 | -2[^64-1] ~ 2[^64-1] - 1 |
注:从JDK1.7开始,数值型的字面值中的数字之间可以出现任何数量的下划线,例如1_123
。
在使用这些整型类型时,一定要注意不可以超过其取值范围;否则,就会产生溢出,从而取到其他不可预料的值。
int max = Integer.MAX_VALUE; //2147483647
int min = Integer.MIN_VALUE; //-2147483648
System.out.println(max+1); //输出:-2147483648
System.out.println(min-1); //输出:2147483647
注:Java中没有无符号整型类型。
浮点型
浮点型包括单精度浮点型(float)和双精度浮点型(double)两种类型。
浮点类型 | 位数 | 值得范围 |
---|---|---|
float | 32 | ±1.4E-45 ~ ±3.4E+38 |
double | 64 | ±4.9E-324 ~±1.7E+308 |
在数字后带有字母F或f(float)、D或d(double),或者一个数字包括小数点或指数部分则该数字为浮点类型。
注:如果浮点值没有使用float关键字定义为float类型,则系统默认其类型为double型。
Java浮点类型常量有两种表示形式:十进制和科学计数法形式。其中十进制形式必须含有小数点,例如 2.13、34.0;科学计数法形式,例如3.54e2、2.7E2。
定义单精度浮点数时,不能写成类似float a = 20.1
这种形式,需要在值后面加上 F或f
,因为小数常量默认为double
类型。
在实际的操作中,尤其是数学计算或需要经过多次计算才能得出结果,并且对结果的精度要求比较高的情况下,通常使用双精度型。
System.out.println(2.0-1.1);
上面的结果下意识会是输出为0.9,但实际输出为0.8999999999999999。其主要原因是浮点数值采用二进制系统表示,而在二进制系统中无法精确的表示分数 1/10 ,这就好像十进制无法精确地表示1/3一样。那如果需要精确计算该怎么办呢?如果需要在数值计算中不含有任何舍入误差,可以使用Java提供的BigDecimal类。
拓展:
Java中整型常量默认为int类型,为其分配4字节大小的空间。如果需要声明long类型的常量,可以在后面加L(小写也可以,但不建议):
int i = 3; long L =3L;
Java中浮点类型常量默认为double型,如要声明一个常量为float型,则需在数字后面加F或f:
double d = 3.14; float f = 3.14f;
float f = 3.4 语句是否错误?
“float f = 3.4”
语句的写法是不正确的,因为3.4默认为double类型,double类型必须使用强制类型转换才可以,如“float f = (float)3.4”
。
char类型
字符型(char
)可表示通常意义上的单个字符,占用两个字节可表示范围为0~65536
。char类型的字面量要用单引号括起来。例如 ‘A'
是编码值为65
所对应的字符常量。它与 “A”
不同,“A”
是包含一个字符A
的字符串。char类型的值可以表示为十六进制,其范围从\u0000
到 \Uffff
。
Java中char
型采用了Unicode
编码,而Unicode
只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储,Unicode
字符集有多个编码方式,分别是UTF-8
,UTF-16
和UTF-32
。而UTF-8
是使用最广的一种Unicode
的实现方式。
拓展:尽管char被设计成容纳Unicode字符,但它也可以用作整数类型,可以对char类型的变量执行算术运算。
注意:UTF-8是Unicode的实现方式之一。
UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。
UTF-8的编码规则很简单,只有二条:
- 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的
Unicode
码。因此对于英语字母,UTF-8
编码和ASCII
码是相同的。 - 对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的
Unicode
码。
拓展:
Unicode
最初设计是作为一种固定宽度的 16 位字符编码。在 Java 编程语言中,基本数据类型char
初衷是通过提供一种简单的、能够包含任何字符的数据类型来充分利用这种设计的优点。不过,现在看来,16 位编码的所有 65536 个字符并不能完全表示全世界所有正在使用或曾经使用的字符。于是,Unicode
标准已扩展到包含多达 1112064 个字符。那些超出原来的 16 位限制的字符被称作增补字符。Unicode
标准 2.0 版是第一个包含启用增补字符设计的版本,但是,直到 3.1 版才收入第一批增补字符集。由于 J2SE 的 5.0 版必须支持Unicode
标准 4.0 版,因此它必须支持增补字符。代码点(code point)是指与一个编码表中的某个字符对应的代码值。在
Unicode
标准中,代码点采用十六进制书写,并加上前缀U+
,例如U+0041就是字母A的代码点。
Unicode
代码点可以分为17个代码级别(code plane)。第一个代码级别称为基本的多语言级别,代码点从U+0000到U+FFFF。其余的16个级别,代码点从U+10000到U+10FFFF。在Java中,char类型用UTF-16编码描述一个代码单元。Java 平台如何支持增补字符的呢?
JSR-204
专家组使用了一种分层的方法:
- 使用基本类型
int
在低层 API 中表示代码点,例如Character
类的静态方法。- 将所有形式的
char
序列均解释为UTF-16
序列,并促进其在更高层级API
中的使用。- 提供 API,以方便在各种
char
和基于代码点的表示法之间的转换。在Java1.5之后,增补字符使用两个
char
型变量来表示。第一个char
型变量的范围称为“高代理部分”(high-surrogates range,从uD800到uDBFF,共1024个码位), 第二个char
型变量的范围称为“低代理部分”(low-surrogates range,从”uDC00到”uDFFF,共1024个码位)。这两个char
型变量就组成了所谓的surrogate pair
(在底层实际上是使用一个int进行表示的)。
boolean类型
boolean(布尔)类型只有两个值:false
和true
,用来判断逻辑条件。整型值和布尔值之间不能进行相互转换。
类型转换
在编程过程中,可能需要将一种数据类型转换为另一种数据类型。Java为我们提供了两种数据类型转换方式:自动类型转换和强制类型转换。
自动类型转换
在运算时不需要用户指定目标数据类型,系统自己进行类型转换,但前提需要满足以下两个条件:
- 两种类型互相兼容,例如int和long兼容,int和boolean不兼容。
- 目标数据类型的范围大于被转换数据类型值得范围,例如long类型分配内存大小8字节,int类型是4字节,因此long类型的范围比int类型大。
当满足这两个条件时,会发生扩宽转换(widening conversion)。
特例:可以将整型常量直接赋给byte,short,char
等类型变量,而不需要强制类型转换,只要不超出其表数范围。
简单类型除了boolean类型以外,其它的数据类型之间可以实现自动转换,但需要遵循一定规则,如下:
强制类型转换
场景:
- 两种类型互相兼容,但是目标数据类型的范围小于被转换数据类型值得范围。
- 不兼容的两种类型。
语法:(目标数据类型)value
示例:byte a=(byte) 256;
int
类型的值强制转换为byte
类型。如果整数的值超出了byte类型的范围,结果将以byte类型的范围为摸(用整数除以byte范围后的余数)减少。
int x = 257;
byte b = (byte)x;//结果为1,257/128=2余1
当将浮点值赋给整数类型时会发生另一种不同类型的转换:截尾(truncation)。整数没有小数部分,当然会直接舍去,当然如果整数部分的数值太大,以至于无法保存到目标整数类型中,那么数值将以目标类型的范围为模减少。
表达式中的自动类型提升
除了赋值外,还可能在表达式中发生类型抓换。
byte a = 40;
byte b = 50;
byte c = 100;
int d = a * b / c;
中间部分a*b
的结果很容易超出byte操作数的范围。为了解决这类问题,当对表达式求值时,Java自动将每个byte、short或char操作数提升为int类型。这意味着使用int类型而不是byte类型执行子表达式a*b
。因此,尽管a和b都被指定为byte类型,中间表达式(50*40)的结果2000是合法的。
尽管自动类型提升很有用,但是它们会导致难以理解的编译时错误。例如,下面的代码看起来是正确的,但是会导致问题:
byte a = 2;
byte b = 3;
byte c = a*b;// Type mismatch: cannot convert from int to byte
byte d = a*2;//Type mismatch: cannot convert from int to byte
上面的代码中在表达式过程中自动提升为int类型,所以结果也被提升为int类型。因此,现在表达式的结果是int类型,如果不适用强制类型转换,就不能将结果赋值给那个byte变量。如果能理解溢出产生的结果,就应当使用显式的强制类型转换。
类型提升规则:
如果对基本数据类型执行算术运算或按位运算时,只要类型比int小(即char、byte或short),在运行前都会自动转换为int。这样一来,最终生成的结果就是int类型。如果想把结果赋值给较小的类型,就必须使用强制类型转换。
通常,表达式中出现的最大的数据决定了表达式最终结果的数据类型。
拓展:
对象的向上/向下转型发生在多态的情况下,这在后期会着重说明!
基本数据类型的向上转型一般发生在自动类型转换,当然你可以将类型强制向上转型。而基本数据类型的向下转型(窄化)就必须通过强制类型来完成了,当然可能会伴随着溢出问题需要注意!
附录表
关键字 | 含义 |
---|---|
abstract | 表明类或者成员方法具有抽象属性 |
assert | 断言,用来进行程序调试 |
boolean | 基本数据类型之一,布尔类型 |
break | 提前跳出一个块 |
byte | 基本数据类型之一,字节类型 |
case | 用在switch语句之中,表示其中的一个分支 |
catch | 用在异常处理中,用来捕捉异常 |
char | 基本数据类型之一,字符类型 |
class | 声明一个类 |
const | 保留关键字,没有具体含义 |
continue | 回到一个块的开始处 |
default | 默认,例如,用在switch语句中,表明一个默认的分支 |
do | 用在do-while循环结构中 |
double | 基本数据类型之一,双精度浮点数类型 |
else | 用在条件语句中,表明当条件不成立时的分支 |
enum | 枚举 |
extends | 表明一个类型是另一个类型的子类型,这里常见的类型有类和接口 |
final | 用来说明最终属性,表明一个类不能派生出子类,或者成员方法不能被覆盖,或者成员域的值不能被改变,用来定义常量 |
finally | 用于处理异常情况,用来声明一个基本肯定会被执行到的语句块 |
float | 基本数据类型之一,单精度浮点数类型 |
for | 一种循环结构的引导词 |
goto | 保留关键字,没有具体含义 |
if | 条件语句的引导词 |
implements | 表明一个类实现了给定的接口 |
import | 表明要访问指定的类或包 |
instanceof | 用来测试一个对象是否是指定类型的实例对象 |
int | 基本数据类型之一,整数类型 |
interface | 接口 |
long | 基本数据类型之一,长整数类型 |
native | 用来声明一个方法是由与计算机相关的语言(如C/C++/FORTRAN语言)实现的 |
new | 用来创建新实例对象 |
package | 包 |
private | 一种访问控制方式:私用模式 |
protected | 一种访问控制方式:保护模式 |
public | 一种访问控制方式:共用模式 |
return | 从成员方法中返回数据 |
short | 基本数据类型之一,短整数类型 |
static | 表明具有静态属性 |
strictfp | 用来声明FP_strict(单精度或双精度浮点数)表达式遵循IEEE 754算术规范[1] |
super | 表明当前对象的父类型的引用或者父类型的构造方法 |
switch | 分支语句结构的引导词 |
synchronized | 表明一段代码需要同步执行 |
this | 指向当前实例对象的引用 |
throw | 抛出一个异常 |
throws | 声明在当前定义的成员方法中所有需要抛出的异常 |
transient | 声明不用序列化的成员域 |
try | 尝试一个可能抛出异常的程序块 |
void | 声明当前成员方法没有返回值 |
volatile | 表明两个或者多个变量必须同步地发生变化 |
while | 用在循环结构中 |
拓展:
除了8中简单数据类型之外的所有数据类型都被称为引用数据类型,引用数据类型的大小统一为4个字节,记录的时其引用对象的地址(类似于就是C++中的指针),例如类、接口和数组等。
Java属于强类型语言,在定义变量时必须严格指定变量类型。Java类型主要分为简单类型和引用类型,简单类型变量直接存储变量值,而引用类型变量存储的却是地址,这一点在赋值的时候至关重要。
参考资料:
在我写过的博客中有两篇博客是对资源的整理,可能对大家都有帮助,大家有兴趣的话可以看看!!
博文编号:20180315154750