老面:Java中有哪些关键字
笑小枫:
- 用于数据类型
用于数据类型的关键字有 boolean、byte、char、 double、 float、int、long、new、short、void、instanceof。 - 用于语句
用于语句的关键字有break、case、 catch、 continue、 default 、do、 else、 for、 if、return、switch、try、 while、 finally、 throw、this、 super。 - 用于润饰
用于润饰的关键字有 abstract、final、native、private、 protected、public、static、synchronized、
transient、 volatile。 - 用于办法、类、接口、包和异样
用于办法、类、接口、包和异样的关键字有 class、 extends、 implements、interface、 package、import、throws。 - 其余
还有些关键字,如 future、 generic、 operator、 outer、rest、var等都是Java保留的没有意义的关键字。另外,Java还有3个保留字:goto、const、null。它们不是关键字,而是文字。蕴含Java定义的值。和关键字一样,它们也不能够作为标识符应用。
老面:简略介绍一下 final 关键字
笑小枫:final关键字能够用来润饰援用、办法和类。
- 润饰援用
- 如果援用为根本数据类型,则该援用为常量,该值无奈批改;
- 如果援用为援用数据类型,比方对象、数组,则该对象、数组自身能够批改,但指向该对象或数组的地址的援用不能批改。
- 如果援用时类的成员变量,则必须当场赋值,否则编译会报错。
- 润饰办法
当应用final润饰办法时,这个办法无奈被子类重写。然而,该办法依然能够被继承。 - 润饰类
当用final批改类时,该类成为最终类,无奈被继承。
老面:简略介绍一下 this、super 关键字
笑小枫:this:代表以后对象的援用,谁来调用我我就代表谁。super:代表以后对象对父类的援用。
- 调用成员变量不同;
this:成员变量 调用本类的成员变量,也能够调用父类的成员变量。
super:成员变量 调用父类的成员变量。 - 调用构造方法不同。
this:调用本类的构造方法。
super:调用父类的构造方法。 - 调用成员办法。
this:成员办法 调用本类的成员办法,也能够调用父类的办法。
super:成员办法 调用父类的成员办法。
老面:简略介绍一下 static 关键字
笑小枫:
- static是一个修饰符,用于润饰成员。(成员变量,成员函数)static润饰的成员变量 称之为动态变量或类变量。
- static润饰的成员被所有的对象共享。
- static优先于对象存在,因为static的成员随着类的加载就曾经存在。
- static润饰的成员多了一种调用形式,能够间接被类名所调用,(类名.动态成员)。
- static润饰的数据是共享数据,对象中的存储的是特有的数据。
老面:简略介绍一下 volatile 关键字
笑小枫:volatile是java虚拟机提供的轻量级同步机制,用于示意能够被多个线程异步批改的成员变量,其特点有: 1.保障可见性 2.禁止指令重排 3.不保障原子性
1、volatile可见性实现原理:
变量被volatile关键字润饰后,底层汇编指令中会呈现一个lock前缀指令。会导致以下两种事件的产生:
- 批改volatile变量时,会强制将批改后的值刷新到主内存中。
- 批改volatile变量后,会导致其余线程工作内存中对应的变量值生效。因而,再读取该变量值的时候就须要从新从读取主内存中的值。
2、volatile有序性实现原理:
指令重排序:编译器在不扭转单线程程序语义的前提下,重新安排语句的执行程序,指令重排序在单线程下不会有问题,然而在多线程下,可能会呈现问题。
volatile有序性的保障就是通过禁止指令重排序来实现的。指令重排序包含编译器和处理器重排序,JMM会别离限度这两种指令重排序。禁止指令重排序又是通过加内存屏障实现的。
JMM:JMM(java 内存模型 Java Memory Model 简称JMM) 自身是一个形象的概念,并不在内存中实在存在的,它形容的是一组标准或者规定,通过这组标准定义了程序中各个变量(实例字段,动态字段和形成数组对象的元素)的拜访形式.JMM的同步规定: 1.线程解锁之前,必须把共享变量刷新回主存 2.线程加锁锁之前,必须读取主存的最新值到本人的工作空间 3.加锁解锁必须是 同一把锁内存屏障(memory barriers):一组处理器指令,用于实现对内存操作的程序限度。
3、 volatile为什么不保障原子性?
java中只有对变量的赋值和读取是原子性的,其余的操作都不是原子性的。所以即便volatile即便能保障被润饰的变量具备可见性,然而不能保障原子性。
老面:简略介绍一下 synchronized 关键字
笑小枫:可用来给对象和办法或者代码块加锁,当它锁定一个办法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。
在晚期的java版本,synchronized 关键字属于重量级锁,效率低下。jdk1.6之后有了优化。
synchronized在java内存模型中次要有3种作用,别离是:
- 原子性:通过monitorenter和monitorexit指令,保障被synchronized润饰的代码在同一时间只能被一个线程拜访,在锁未开释之前,无奈被其余线程拜访到
- 可见性:保障共享变量的批改可能及时可见,对一个变量的unlock操作之前,必须把此变量同步回主内存中(store和write操作)
- 有序性:一个变量在同一时刻只容许一条线程对其执行lock操作,这条规定决定了持有同一个锁的两个同步块只能串行执行
synchronized的底层实现原理
- 原子性实现原理
synchronized实现原子性底层是通过JVM来实现的,同一时间只能有一个线程去执行synchronized中的代码块;
每一个对象都有一个监视器monitor来关联,监视器被占用时会被锁住,其余线程无奈获取该monitor,当JVM执行某个线程的的外部办法的monitorenter,它会尝试去获取该对象的monitor的所有权,过程如下: - 若monitor的进入数为0,线程能够进入monitor,并将该monitor的进入数置为1,那么该线程就成为monitor的所有者
- 若线程已领有monitor的所有权,容许它重入monitor,则进入monitor的进入数加1(recursions:记录线程领有锁的次数)
若其余线程曾经占有monitor的所有权,那么以后尝试获取monitor的所有权的线程会被阻塞,直到monitor的进入数变为0,能力从新尝试获取monitor的所有权。
monitorexit指令
- 能执行monitorexit指令的线程肯定是领有以后对象的monitor的所有权的线程。
- 当执行monitorexit时会将monitor的进入数减1。当monitor的进入数减为0时,以后线程退出monitor,不再领有monitor的所有权,此时这个monitor阻塞的线程能够尝试去获取这个monitor的所有权。
- 可见性实现原理
synchronized通过内存屏障保障可见性,同样的咱们晓得volatile是通过内存屏障来保障可见性的, - monitorenter指令之后,synchronized外部的共享变量,每次读取数据的时候被强制从主内存读取最新的数据。
- monitorexit指令也具备Store屏障的作用,也就是让synchronized代码块内的共享变量,如果数据有变更的,强制刷新回主内存。
数据批改之后立刻刷新回主内存,其余线程进入synchronized代码块后,应用共享变量的时候强制读取主内存的数据。 - 有序性实现原理
同样的,synchronized也是通过monitorenter、monitorexit指令嵌入下面的内存屏障,既具备加锁、开释锁的性能,同时也具备内存屏障的性能
老面:简略介绍一下 break、continue 关键字
笑小枫:
break用于齐全完结一个循环,跳出循环体,执行循环前面的语句。
continue是跳过当次循环中剩下的语句,执行下一次循环。
老面:简略介绍一下 trabsient 关键字
笑小枫:被transient润饰的变量不参加序列化和反序列化。当一个对象被序列化的时候,transient型变量的值不包含在序列化的示意中,然而非transient型的变量是被包含进去的。
老面:简略介绍一下 instanceof 关键字
笑小枫:在 Java 中能够应用 instanceof 关键字判断一个对象是否为一个类(或接口、抽象类、父类)的实例
老面:简略介绍一下 extends、implements 关键字
笑小枫:
extends 是继承某个类, 继承之后能够应用父类的办法, 也能够重写父类的办法
implements 是实现多个接口, 接口的办法个别为空的, 必须实现能力应用
老面:简略介绍一下 native 关键字
笑小枫:native次要用于办法上,native办法是指该办法的实现由非Java语言实现,比方用C或C++实现。
次要是因为JAVA无奈对操作系统底层进行操作,然而能够通过jni(java native interface)调用其余语言来实现底层的拜访。
PS:JNI是Java本机接口(Java Native Interface),是一个本机编程接口,它是Java软件开发工具箱(java Software Development Kit,SDK)的一部分。JNI容许Java代码应用以其余语言编写的代码和代码库。Invocation API(JNI的一部分)能够用来将Java虚拟机(JVM)嵌入到本机应用程序中,从而容许程序员从本机代码外部调用Java代码。