java关键字 = 51 + 2个保留字 = 53(java关键字都是小写)
java 保留字
cost
用于修改字段或局部变量的申明, 指定字段或局部变量的值是常熟,不能被修改
goto
指定跳转标签,找到标签后,程序将处理从下一行开始的命令
访问修饰符的关键字
public
公有的,可跨方法跨包
protected
受保护的,可跨方法跨类,但类仅限于本包下的类及子类
(default)
默认的,只能在本包中跨方法跨类
private
私有的,只能在本类中使用。
ps:反射调用某个类,是可以调用该类的私有方法的。
定义类、接口、抽象类和实现接口、继承类的关键字、实例化对象
class
类,定义类
interface
接口,定义接口
接口里属性的默认属性为public static final
成员里面不能有构造器、不能有初始化块
一个接口可以有多个直接父类,接口只能继承接口不能继承类(用extends方法)。
接口里面不能申明final方法、static方法,但可以申明abstract方法。
接口不能用private、protected修饰符修饰。
接口里方法默认的修饰符为public abstract
abstract
声明抽象
不能与该关键字共存的关键字:
- static :静态修饰抽象方法的话,那在类初始化的时候就需要运行这个静态修饰的抽象方法,但抽象方法是没有方法体的,所以没有意义。
- final : final是不能被继承的,但是abstract需要被继承之后重写方法,所以不能用abstract修饰final修饰的方法
- private : 是私有方法,不能被继承的,所以也不行。
new
创建一个新的对象。
包的关键字
import
引入包的关键字
package
定义包的关键字
数据类型的关键字
int
整型(32 bit) 范围 : 2 − 32 2^{-32} 2−32 - 2 31 2^{31} 231
byte
字节(8bit)范围:-128 - 127
short
短整型(16bit)
long
长整型(64bit)
float
浮点型(32bit)
double
双精度(64bit)
char
字符型(16bit)
boolean
布尔型(1bit)
条件循环(流程控制)
if
判断条件
else
否则
while
当什么的时候
for
满足三个条件时
for(int i = 0; i < n; i++)
这个语句里,进入的时候会初始化i = 0
然后每次循环对i< n会进行判断
在执行完循环语句后会执行i++
switch
开关,switch会接受int
,byte
,char
,short
,不能接受其他类型
case
返回开关里的结果
就是swith(xxx)中xxx的值对应的执行语句。
case后面执行语句如果没有加break,那么会按顺序执行到switch结束
default
默认,case中没有xxx值的话,会跳到默认位置执行。
do
运行【我见过do……while】
break
跳出循环。
continue
中断本次循环,调到下一次循环
return
返回
instanceof
(obj instanceof Class)
obj 必须是引用类型,不能是基本类型
obj为null的时候,会返回false
obj是class类的实例对象
obj为class接口的实现类
------借用别人的例子
Person p1 = new Person();
System.out.println(p1 instanceof String);//编译报错
System.out.println(p1 instanceof List);//false
System.out.println(p1 instanceof List<?>);//false
System.out.println(p1 instanceof List<Person>);//编译报错
里面instanceof的逻辑有点类似于对obj进行强制转型,如果转换错误就返回false
所以里面对Person转型成String,编译会直接不通过,所以是编译报错。
修饰方法、类、属性和变量
static
静态
可以修饰方法也可以修饰类,还能修饰代码块
在类初始化的时候,被static标记的类、变量、代码块也会随之初始化。
方便在没有创建对象的情况下来进行调用(方法/变量)。静态方法不属于任何对象。
static是不允许用来修饰局部变量
static不能出现在任何方法内部
static方法、代码块、变量执行顺序是按先后顺序的。
final
可以修饰类、修饰方法、修饰变量(包括成员变量和局部变量)
final修饰的东西被初始化之后,就不能被更改了。
super
相当于是指向当前对象的父类
super() 调用父类的构造函数
需要在构造方法第一行
super是一个Java关键字。
this
调用当前类中的对象。
this()调用本类中另一种构造函数
this用来指代当前对象名。
需要在构造方法第一行
this是一个指向本对象的指针
native
本地方法,一般对本地方法在static方法块统一编译
strictfp
就是硬性要求根据精确的浮点规范IEEE-754执行。
你可以将一个类、接口以及方法声明为strictfp,但是不允许对接口中的方法以及构造函数声明strictfp关键字
synchronized
无论synchronize关键字是加在方法上还是对象上,如果它的作用对象是非静态的,则它获得的锁是对象;如果作用对象是一个静态方法或一个类,则它获取的锁是类锁,该类所有的对象同一把锁。
每个对象都只有一把锁和它关联。谁拿到了锁就能运行那段代码。
实现同步需要耗费很多系统资源,甚至可能造成死锁,所以尽量避免无谓的同步控制。
transient
在implement Serializable的情况下禁止对标记了该关键字的字段序列化。
volatile关键字
用法
- 保证可见性
- 禁止指令重排序
原理
保证可见性
在多线程情况下,不同线程中有自己专属的高速缓存空间,在不同线程会首选读自己的缓存空间(如果要让不同CPU的缓存同步的话, 需要耗费的资源是很多的),如果缓存空间没有对应的数据,才会去从内存中读取自己想要的数据。
volatile的作用就是,当线程更新了自己的被volatile标记的字段的值后,会强制将修改后的值刷新到主内存中,让其他线程中的缓存对应的这个字段的值失效,线程如果想要读取这个值就必须去内存里获取。
禁止指令重排序
指令重排序
指令重排序其实是一种对指令执行效率的优化
但在有些情况下会导致输出错误的结果。
在单线程情况下,不管怎么重排序,单线程的程序执行结果是不会被改变的,编译器、runtime和处理器都必须遵守as-if-serial语义,不会对有依赖关系的操作做重排序。
public static void main(String[] args) {
int a = 0;
int b = 0;
a = 10;//1
b = 10;//2
int c = a+ b;//3
}
比如1、2、3三条语句,3对1、2对b有依赖关系,(就是3如果和1交换位置,那么会导致结果为0,而和2交换位置会导致结果为10,所以 称3与1、3与2有依赖关系,必须等1和2执行完成再执行3才能得到正确的结果。)
在单线程的情况下,遵循as-if-serial语义,不会出现什么问题
但在多线程情况下,单线程遵循as-if-serial语义,但不同的线程语句调换方式不一样,在并发的情况下会出现报错等问题。
比如:
// 线程A执行代码
int b = 0;
int a = 0;
int b = 1 + a;
boolean flag = True;
//线程B执行代码
if(flag){
return b;
}
在线程A和线程B并发的情况下,线程A对执行的指令进行优化,因为flag与上面的指令没有关联关系,所以很可能在线程A执行的过程中,可以把Boolean flag=true提前执行。这样就导致了在B执行代码的时候,返回的值是0,而不是1。导致了线程不安全的情况发生。
所以就需要使用volatile标记flag,防止flag提前执行。
这就是volatile禁止指令重排序的功能。
禁止方法
java是通过内存屏障对指令重排序进行禁止的。
LoadStore 读后才能写
LoadLoad 读后才能读
StoreLoad 写后才能读
StoreStore 写后才能写
当一个变量使用volatile修饰的时候,volatile关键字就是内存屏障。当编译器在生成指令顺序的时候,发现了volatile,就直接忽略掉。不再重排序了。
示意序列:
volatile读
LoadLoad
LoadStore
StoreStore
volatile写
StoreLoad
catch
处理异常
try
捕获异常
finally
有没有异常都必须执行
throws
声明一个异常可能会被抛出
enum
枚举
assert
断言,一般都在测试里面使用这个。