简介
Java关键字是Java程序语言结构的一部分,它对于编译器有特殊的含义及作用,我们不能用将它们用变量名称(编译会报错)。Java中一共有50个关键字,包含2个保留字const
和goto
,所有的关键字都是小写,全部的关键字如下表所示:
char | byte | short | int | long |
---|---|---|---|---|
float | double | boolean | if | else |
switch | case | break | default | do |
while | continue | for | try | catch |
throw | throws | finally | return | private |
protected | public | class | interface | extends |
implements | this | super | new | import |
package | instanceof | enum | abstract | void |
final | static | volatile | transient | synchronized |
native | strictfp | assert | const | goto |
另外还有3个标志符true、false、null 一共53个,这些标志符在Java语法中都有特殊的含义,不能当作变量名使用,掌握这些关键字的作用以及熟练的使用它们是学好Java的必备技能。
上面的表格中列出了所有的关键字,它们主要分为几大类:8中基本数据类型、程序逻辑控制、异常处理、类方法和变量修饰符、类和接口的相关修饰。下面就以各个分类来简单说一下每一个关键字的作用。
基本数据类型
java是一门强类型语言,Java的数据类型分为基本数据类型和引用数据类型.
Java一共有8种基本数据类型。分为:整型、浮点型、布尔型、字符型,每种类型占用的字节长度以及取值范围如下表所示。
名称 | 类型 | 长度 | 默认值 | 取值范围 | 示例 |
---|---|---|---|---|---|
byte | 字节型 | 占1个字节 | 0 | -128 ~ 127 | 21 |
short | 短整型 | 占2个字节 | 0 | -32768 ~ 32767 | 123 |
int | 整型 | 占4个字节 | 0 | -2^31 ~ 2^31 - 1 | 433 |
long | 长整型 | 占8个字节 | 0L | -2^63 ~ 2^63 - 1 | 34L |
float | 浮点型 | 占4个字节 | 0.0F | -2^128 ~ 2^128 | 32.2f |
double | 双精度浮点型 | 占8个字节 | 0.0D | -2^1024 ~ 2^1024 | 55D |
boolean | 布尔型 | 占1或4个字节 | false | true or false | true |
char | 字符型 | 占2个字节 | 空 | ‘\u0000’ ~ ‘\uffff’ | ‘a’ |
- boolean类型被编译为int类型,等于是说JVM里占用字节和int完全一样,int是4个字节,于是boolean也是4字节
- boolean数组在Oracle的JVM中,编码为byte数组,每个boolean元素占用8位=1字节
程序逻辑控制
Java逻辑控制包含条件控制和循环控制,条件控制可以使用if、else,循环控制可以使用for、while。具体包含下面这些关键字。
关键字 | 含义 | 作用 |
---|---|---|
if | 如果… | if(…){},如果小括号中的条件成立返回true,则执行大括号中的内容 |
else | 否则… | else 必须与if连用,不能单独使用,else后面可以接if语句 |
switch | 开关 | switch(表达式) { case 常量表达式1: 语句1; break; case 常量表达式2: 语句2; default: 默认语句 } case后面的常量表达式的数据类型要和switch后面的表达式的数据类型一致,且只能是基本数据类型或String类型(Java 1.7及以上支持) |
case | 案例 | 用于switch语法中,表示switch的一个条件分支,如上面的常量表达式1等于switch表达式的值时,则执行语句1,否则继续判断下面的case |
break | 打破、中断 | 用于提前退出 for、while 或 do 循环,或者在 switch 语句中用来结束 case 块。 break 总是退出最深层的 while、for、do 或 switch 语句。 |
default | 默认 | 用来标记 switch 语句中的默认分支,如果switch中没有break语句或者任何一个break语句没有执行到,则都会执行default语句;default语句一般写在switch的最后,如果写在最上面或中间,则default下面的所有case永远不会被执行。 |
for | 为… | for 语句的形式为 for(initialize; condition; increment) 。每次执行循环体之前将计算 condition 的结果。如果 condition 为 true,则执行循环体。 每次执行循环体之后,在计算下一个迭代的 condition 之前,将执行 increment 语句。 |
do | 执行 | do { } while(condition); do 循环体至少执行一次。循环体执行结束后判断condition是否成立,成立则再次执行循环体,直到condition返回false |
while | 当… | while(condition) { } 当condition为true时则会执行循环体内容 |
continue | 继续 | for(int i = 0; i < 5; i++) { if (i == 3) continue; Log.i(“index”, i); } 出现在循环体中,当执行到continue语句时,其后面的循环体内容将不再执行,直接进行下一次循环操作,如上面的例子中将不会打印3 |
###异常处理
异常是程序运行中出现的错误。会打断程序正常执行。是java中提供的一种错误提示和处理的机制。
异常分为2类:
- 错误(ERROR):通常指不是由程序造成并且在程序中不能处理或避免的错误。比如:内存溢出,Java虚拟机出错等
- 异常(Exception):通常指由于程序代码不严谨造成的可以避免的错误或在程序中可以预先处理的错误。
抛出一个异常使用throw关键字,通过throws关键字在方法上标注有可能会发生的异常。
void printAge(int age) throws NumberFormatException {
if (age < 0) {
throw new NumberFormatException("年龄不能小于0");
}
}
程序抛出的异常可以使用try-catch进行捕获处理,
try {
// 尝试执行可能会发生异常的代码块
} catch(...) {
// 捕捉try块中发生的异常并处理
} catch(...) {
// 多重catch时父类异常必须写到子类之后,同级的异常没有先后顺序。
} finally {
// 必须执行块,无论try中是否发生异常,该块都会被执行,即使try中有return也会在return之前被执行,但是如果try中有System.exit(),则Java虚拟机会退出,则不会执行finally。
}
###类方法和变量修饰符
在Java中一共有4中访问修饰符。用于控制类和数据的访问权限。
按权限范围由小到大依次为:private、空(default)、protected、public.
控制的范围如下所示:
访问范围 | public | protected | default | private |
---|---|---|---|---|
同类 | ok | ok | ok | ok |
同包 | ok | ok | ok | |
子类(不同包) | ok | ok | ||
不同包无继承的类 | ok |
- 抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public。
- 接口中的方法必须是public abstract的
类和接口的相关修饰符
class:用来声明新的 Java类,该类是相关变量和/或方法的集合。类是面向对象的程序设计方法的基本构造单位。类通常代表某种实际实体,如几何形状或人。类是对象的模板。每个对象都是类的一个实例。要使用类,通常使用 new 操作符将类的对象实例化,然后调用类的方法来访问类的功能。
interface :用来声明新的Java接口,接口是方法和常量的集合。接口是 Java 语言的一项强大功能。任何类都可声明它实现一个或多个接口,这意味着它实现了在这些接口中所定义的所有方法。任何非抽象类如果实现了接口则必须提供在该接口中的所有方法的实现,若是抽象类实现了接口则抽象类或其子类要实现接口中的全部方法。
abstract:可以修改类或方法。abstract类可以扩展(增加子类),但不能直接实例化。abstract方法不在声明它的类中实现,但必须在某个子类中重写。采用abstract方法的类一定是抽象类,并且必须声明为abstract类。
extends:用在 class 或 interface 声明中,用于标识所声明的类或接口是 extends 关键字后的类或接口的子类或子接口。子类继承父类的所有 public 和 protected 变量和方法。 子类可以重写父类的任何非 final 方法。
class ContextImpl extends Context {}
public interface Closeable extends AutoCloseable {
public void close() throws IOException;
}
implements:在 class 声明中使用,表示所声明的类提供了在 implements 关键字后面的名称所指定的接口中所声明的所有方法的实现。类必须提供在接口中所声明的所有方法的实现。一个类可以实现多个接口。
this :用于引用当前实例。 当引用可能不明确时,可以使用 this 关键字来引用当前的实例。
super :用于引用使用该关键字的类的超类。 作为独立语句出现的 super 表示调用超类的构造方法。 super.methodName() 表示调用超类的方法。
new:用于创建类的新实例。 new 关键字后面的参数必须是类名,并且类名的后面必须是一组构造方法参数(必须带括号)。
static
static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念。
被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。
只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。
用public修饰的static成员变量和成员方法本质是全局变量和全局方法,当声明它类的对象时,不生成static变量的副本,而是类的所有实例共享同一个static变量。static表示不要实例化就可以使用,这样就容易理解多了。
static变量
被static修饰的变量,叫静态变量或类变量;没有被static修饰的变量,叫实例变量。
对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。
对于实例变量,每创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。
static方法
静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用this和super关键字,不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法。
static代码块
static代码块也叫静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次,利用静态代码块可以对一些static变量进行赋值。
final:final可以修饰类、方法和变量。
修饰类: 最终类,不能被继承。
修饰方法:最终方法,不能被重写。
修饰变量:最终变量,常量,一旦赋值不能被改变。
enum:枚举是Java中一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,Java 枚举类使用 enum 关键字来定义,各个常量使用逗号 , 来分割。
enum Color {
RED, GREEN, BLUE;
}
枚举可以用来创建单例模式,枚举类中也可以定义变量和方法。
public enum Singleton {
INSTANCE;
public void method() {
}
}
native :修饰方法,表示该方法是用 Java 以外的语言实现的。Java的不足除了体现在运行速度上要比传统的C++慢许多之外,Java无法直接访问到
操作系统底层(如系统硬件等),为此Java使用native方法来扩展Java程序的功能。
可以将native方法比作Java程序同C程序的接口,其实现步骤:
1. 在Java中声明native()方法,然后编译;
2. 用javah产生一个.h文件;
3. 写一个.cpp文件实现native导出方法,其中需要包含第二步产生的.h文件(注意其中又包含了JDK带的jni.h文件);
4. 将第三步的.cpp文件编译成动态链接库文件;
5. 在Java中用System.loadLibrary()方法加载第四步产生的动态链接库文件,这个native()方法就可以在Java中被访问了。
strictfp:strictfp的意思是FP-strict,也就是精确浮点的意思。在Java虚拟机进行浮点运算时,如果没有指定strictfp关键字时,Java的编译器以及运行环境在对浮点运算的表达式是采取一种近似于我行我素的行为来完成这些操作,以致于得到的结果往往无法令人满意。而一旦使用了strictfp来声明一个类、接口或者方法时,那么所声明的范围内Java的编译器以及运行环境会完全依照浮点规范IEEE-754来执行。因此如果想让浮点运算更加精确,而且不会因为不同的硬件平台所执行的结果不一致的话,那就用关键字strictfp。可以将一个类、接口以及方法声明为strictfp,但是不允许对接口中的方法以及构造函数声明strictfp关键字。
transient :修饰类的成员变量,表示该类对象在序列化时,这个变量不被序列化。
我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。
然而在实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。
synchronized:可以应用于方法或语句块,并为一次只应由一个线程执行的关键代码段提供保护。 可防止代码的关键代码段一次被多个线程执行。 如果应用于静态方法,那么,当该方法一次由一个线程执行时,整个类将被锁定。 如果应用于实例方法,那么,当该方法一次由一个线程访问时,该实例将被锁定。 如果应用于对象或数组,当关联的代码块一次由一个线程执行时,对象或数组将被锁定。
volatile :用于表示可以被多个线程异步修改的成员变量。 volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,所有线程所看到的指定变量的值都是相同的。Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”;与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少,但是它所能实现的功能也仅是 synchronized 的一部分。
instanceof :instanceof 是 Java 的一个二元操作符,类似于 ==,>,< 等操作符。它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。
import:使一个包中的一个或所有类在当前 Java 源文件中可见。可以不使用完全限定的类名来引用导入的类,使用*来引入包下面所有的类。
package:指定在 Java 源文件中声明的类所驻留的 Java 包。
goto :但无任何作用。结构化程序设计完全不需要 goto 语句即可完成各种流程,而 goto 语句的使用往往会使程序的可读性降低,所以 Java 不允许 goto 跳转。
const:是一个类型修饰符,使用const声明的对象不能更新。与final某些类似。
null :表示无值。 将 null 赋给非原始变量相当于释放该变量先前所引用的对象。 不能将 null 赋给原始类型(byte、short、int、long、char、float、double、boolean)变量。
true/false :表示 boolean 变量的两个合法值中的一个。