Java程序运行机制
- 编译型
- 解释型
-
Java既是编译型又是解释型
(1) 首先采用通用的java编译器将java源程序编译为与平台无关的字节码文件(.class文件)
(2) 然后由java虚拟机(JVM)对字节码文件解释执行
注意:java字节码具有平台无关性,可以在各种不同系统平台中运行,但是需要有不同版本的java虚拟机,不同平台的java环境其Java虚拟机是不一样的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HuLRJq4r-1629637480070)(C:\Users\chmod\AppData\Roaming\Typora\typora-user-images\image-20210822155531260.png)]
-
JVM(Java Virtual Machine Java虚拟机)
(1)JVM是java字节码执行的引擎,为java程序的执行提供必要的支持,还能优化java字节码文件,使之转化成效率更高的机器指令。程序员编写的程序最终都要在JVM上执行,JVM中的类的装载是由类加载器(ClassLoader)和它的子类来实现的。
(2)ClassLoader是java运行时一个重要的系统组件,负责在运行时查找和装入类文件的类。
(3)JVM屏蔽了与具体操作系统平台相关的信息,从而实现了java程序只需要生成在JVM上运行的字节码文件(class文件),就可以在多种平台上不加修饰的运行。不同平台对应着不同的JVM,在执行字节码时,JVM负责将每一条要执行的字节码发送给解释器,解释器再将其翻译成特定平台环境的机器指令并执行。java语言最重要的特点是跨平台运行,使用JVM就是为了支持与操作系统无关,实现跨平台运行。
-
ClassLoader
(1)是JVM实现的一部分,包括bootstrapclassloader(启动类加载器)
(2)ClassLoader在JVM运行的时候加载java核心的API,通过java程序实现两个ClassLoader:
- ExtClassLoader:它的作用是用来加载java扩展的API。也就是lib\ext类
- APPClassLoader:用来加载用户机器上CLASSATH设置目录的Class
(3)ClassLoader加载流程:当运行一个程序的时候,JVM启动,运行bootstrapclassloader,该Class.java核心API,然后调用ExtClassLoader加载扩展API,最后APPClassLoader加载CLASSATH目录下定义的Class.
-
JRE
JRE是JavaRuntimeEnvironment,java运行时环境,它是java程序运行所必须的环境集合,主要由java虚拟机、java平台核心类和若干支持文件组成。其不包含开发工具、编译器、调试器以及其他工具。
在执行java程序的时候,操作系统会按照下面顺序寻找JRE环境:
-
先查找当前目录下有没有jre
-
再查找父目录下有没有jre
-
接着在环境变量PATH指定的路径中查找jre
-
注册表查看CurrentVersion的键值指向哪个jre
JRE自带的基础类库主要在JRE\LIB\rt.jar文件中。在程序运行时,JRE由ClassLoader(类加载器)负责查找和加载程序引用到的基类库和其他类库。基础类库,ClassLoader会自动到rt.jar的位置,其他的类库,ClassLoader在环境变量CLASSPATH指定的路径中搜索。
- JDK
- DK是Java Development Kit,简称java开发工具包。
- JDK是java的核心。它包括java运行环境、一堆java工具盒java基础的类库(rt.jar)。
- JDK包含JRE的全部内容外,还包含开发者用以编译、调试和运行java程序的工具。
-
JDK、JRE、JVM之间的关系:
- JDK、JRE、JVM之间是包含关系。范围由大到小依次为JDK、JRE、JVM。
-
学习链接:java语言运行机制
注释
注释:就是对代码的解释和说明,其目的就是其他开发者能够轻松的了解代码。注释不影响代码程序的编译和运行的
单行注释 //
多行注释 /* */
文档注释 /** **/
标识符和关键字
标识符
Java 中标识符是为方法、变量或其他用户定义项所定义的名称。标识符可以有一个或多个字符。在 Java 语言中,标识符的构成规则如下。
- 标识符由数字(09)和字母(AZ 和 a~z)、美元符号($)、下划线(_)以及 Unicode 字符集中符号大于 0xC0 的所有符号组合构成(各符号之间没有空格)。
- 标识符的第一个符号为字母、下划线和美元符号,后面可以是任何字母、数字、美元符号或下划线。
另外,Java 区分大小写,因此 myvar 和 MyVar 是两个不同的标识符。
提示:标识符命名时,切记不能以数字开头,也不能使用任何 Java 关键字作为标识符,而且不能赋予标识符任何标准的方法名。
标识符分为两类,分别为关键字和用户自定义标识符。
- 关键字是有特殊含义的标识符,如 true、false 表示逻辑的真假。
- 用户自定义标识符是由用户按标识符构成规则生成的非保留字的标识符,如 abc 就是一个标识符。
提示:使用标识符时一定要注意,或者使用关键字,或者使用自定义的非关键字标识符。此外,标识符可以包含关键字,但不能与关键字重名。
例如以下合法与不合法标识符。
- 合法标识符:date、KaTeX parse error: Expected group after '_' at position 13: 2011、_date、D_̲date 等。
- 不合法的标识符:123.com、2com、for、if 等。
标识符用来命名常量、变量、类和类的对象等。因此,一个良好的编程习惯要求命名标识符时,应赋予它一个有意义或有用途的名字。
关键字
- abstract
- 修饰类:
abstract修饰类,这个类就是抽象类,抽象类中可以有非抽象变量和成员变量,也可以有普通方法、构造方法。但是不能实例化,只能被子类继承。
如果子类不是抽象类,则必须重写父类的抽象方法。
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
...
}
- 修饰方法:
abstract修饰方法,这个方法就是抽象方法。抽象方法必须存在于抽象类中。抽象方法不能有具体实现。
abstract public E get(int index);
-
asser
assert表示“断言”,有两种使用方法:
assert 表达式;
若表达式为真,程序继续执行;若表达式为假,则抛出一个AssertionError异常。
assert 表达式:错误信息;
与第一种方法相同,只是异常中带有错误信息。
使用assert时不能在表达式中完成任何程序实际所需的行为(只能做判断)。因为正常发布的代码都是断言无效的,即正常发布的代码中断言语句都不不执行的。
- boolean
boolean是Java的基本类型之一(默认值false)。只有两个值:true和false。区别C的判断句,Java不能直接使用1和0来表示真假,且boolean类型也不能强转到其他基本类型。
boolean a = true;
boolean b = false;
- break
-
break在switch中用于跳出switch块,停止switch向下穿透的现象。
case value:expression; break;
-
break在循环中用于跳出循环。
while(...){ ... break; }
-
break也可以在后面接标签,用来跳出一些嵌套比较复杂的循环中。
``` flag: for(...){ for(...){ break flag; } } ```
- byte
byte是Java的基本类型之一(默认值0)。表示8位有符号整数。
范围:-128~127
byte a = 100;
- case
case用于switch中,用于判断和执行语句。用法:
case 变量值:语句;
若变量值和switch(变量值)
中的变量值相等,就执行后面的语句。执行完后继续执行下一个case语句。
- catch
catch用于捕获异常。
用法:
catch(异常类型 异常){...}
在try/catch语句块中,catch捕获发生的异常,并应对错误做一些处理。
当catch捕获到异常后,try中执行的语句终止,并跳到catch后的语句中。
- char
char是Java的基本类型之一(默认值\u000)。表示16位、在Unicode编码表中的字符。使用单引号来表示字符常量,例如’A’。
范围:0-65535
char a = 'A';
- class
class表示类。用于声明一个类。
[访问控制] (abstract) class 类名 (implements){...}
-
const
const是Java的一个保留关键字,没有实际意义,但是不能用于做变量名(因为被保留作为关键字了)。在C语言中表示常量,类似Java的final。 -
continue
-
continue用于在循环中跳过本次循环。
while(...){ ... continue; }
-
continue也可以在后面接标签,在一些嵌套比较复杂的循环中跳过一次循环。
``` flag: for(...){ for(...){ continue flag; } } ```
- default
-
default关键字:
-
用于switch做默认分支:
default:语句;
-
-
用于接口,让接口实现具体的方法:
``` public interface a{ default void b(){ 具体方法; } } ``` default用于接口时,必须要有具体实现。 (API>=24)
- do
do用于和while组成循环,do/while循环不同于while循环,属于先执行循环体再判断。
do{
循环体;
}while(...)
- double
double是Java的基本类型之一(默认值0.0d),表示双精度、64位的浮点数。
double a = 0.1d;
- else
else用于分支结构中的判断。例如:
if(判断1){
语句1;
}else if(判断2){
语句2;
}else{
语句3;
}
- enum
enum表示枚举,用于限制变量值的类型,例如:
public enum Alpha (implements 接口){
(public static final)a,b,c,d
}
规定Color的实例只能为a,b,c,d其中之一。
枚举类中可以有成员变量和方法。
17.extends
extends表示继承。例如:
class 子类 extends父类{}
Java中的继承是单继承,即子类只能有一个直接父类。
除了private,子类可以访问父类的方法和成员变量。
- final
- 修饰变量:
将变量变为常量,在初始化变量后不能再改变值。 - 修饰方法:
被final修饰的方法不能被子类重写。 - 修饰类:
被final修饰的类不能被继承。
- 修饰变量:
- finally
finally在try/catch语句块中处理一些后续的工作。例如关闭网络连接和输入输出流等。
如果在try/catch中使用return,则finally会撤销这个return,无论如何都会执行finally中的语句。
- float
float是Java的基本类型之一(默认值0.0f)。表示单精度、32位的浮点数。
float a = 0.1f;
- for
for用于循环:
for(初始化循环变量; 判断执行条件;更新循环变量){
语句
}
for(变量:数组){
语句
}
- goto
Java中的保留关键字,没有实际意义,但是不能用做变量名。在C中表示无条件跳转语句。
23.if
if用于分支结构中的判断。常与else和else if使用。
if(表达式){语句}
若表达式为真,则执行后面的语句。
- implements
implements用于接入接口。接上接口的类必须实现接口的抽象方法(可以不实现默认方法和静态方法)。
class A implements B{
@Override
do(){
...
}
}
- import
用于导入包。
import android.content.Intent;
- instanceof
instanceof用于判断类与对象的关系。例如:
a instanceof b
若a是b的一个实例(或子类对象),则整个表达式的结果是true,否则结果为false。
- int
int是Java的基本类型之一(默认值为0)。表示32位、有符号的整数。
范围:[-231,231-1)
int a = 1;
- interface
interface用于声明一个接口,例如:
public interface A{
void b();
}
声明a为一个接口,若接上该接口,则必须实现其中的抽象方法b。
接口中的成员变量是static、final、public的。接口中的方法为静态方法或默认方法和静态方法(API>=24)。
- long
long是Java的基本类型之一(默认值为0L),表示64位、有符号的整数。
范围:[-263,263)
long a = 3216846849646L;
- native
native可以让Java运行非Java实现的方法。例如c语言,要编译后用javah产生一个.h文件。导入该.h文件并且实现native方法,编译成动态链接库文件。在Java加载动态链接库文件,这个native方法就可以在Java中使用了。
public native void aVoid();
- new
new用于生成类的实例。
Object a = new Object();
- package
package用于规定当前文件的包。
package com.example.zhangyijun.testdefactivity;
- private
访问控制的一种。
私有的方法和变量只能在本类中访问。类和接口不能为私有。
private int a = 1;
private void b(){
...
}
- protected
访问控制的一种。
受保护的方法和变量只能给子类和基类访问。
protected int a = 1;
protected void b(){
...
}
-
public
访问控制的一种。
公有的方法、类、变量、接口能够被任何其他类访问。 -
return
方法中返回数据,并结束方法。 -
strictfp
使用strictfp关键字来声明一个类、接口或者方法时,那么该类、接口或者方法会遵循IEEE-754标准来执行,提高浮点运算的精度,并且减少不同硬件平台之间由于浮点运算带来的差异。
public strictfp double aDouble(){
return 0d;
}
- short
short是Java的基本类型之一(默认值0),表示16位、有符号的整数。
范围:[-215,215)
short a = 0;
- static
static修饰的语句块存放在堆的方法区中。
静态变量:依附在类中的变量,可以被类的所有的实例共用。
static int a = 0;
静态方法:依附在类中的方法。静态方法只能访问类中的静态变量和静态方法。
publlic static void b(){
...
}
静态块:在类加载的时候执行块中的语句,块中不能访问非静态变量。
static{
...
}
静态内部类:用static修饰内部类。
- super
super即超类
引用父类的的成员:
super.xxx
变量或方法重名时用super调用父类的成员或方法。
调用父类的构造方法:
super(xxx);
- switch
switch用于分支结构,判断某个变量与一系列值是否相等。switch 语句中的变量类型可以是: byte、short、int 、char、String、enum。
switch(变量){
case value1:语句1;
break;
case value2:语句2;
break;
...
default:语句;
}
若变量和case后的值相等则执行语句。
当语句执行到break时跳到switch块后,如果没有break会产生穿透现象。
default分支必须为最后一个分支,在没有值和case变量相等时执行该语句。
- synchronized
synchronized关键字用于保证线程安全。由这个关键字修饰的方法或者代码块保证了同一时刻只有一个线程执行该代码。
synchronized(obj){...}
当一个线程访问同步代码块时,检查obj是否有锁,如果有就挂起。如果没有就获得这个obj的锁,也就是把其他线程锁在了外面。当代码执行完毕时释放该锁,其他线程获得锁继续执行代码。
- this
指向当前对象:this.xxx
形参和成员名字重名时时用this区分。
引用构造函数。 - throw
用于抛出一个异常。
throw (Exception);
- throws
在方法中将发生的异常抛出。
[控制访问](返回类型)(方法名)([参数列表])[throws(异常类)]{...}
- transient
类接上序列化接口后,可以通过transient关键字将某些变量变得无法序列化。
transient int a = 1;
- try
在try/catch中,将可能出现异常的语句放在try{}块中,出现异常之后代码将会终止并跳到catch中继续执行。
try{
...
}catch(Exception e){
...
}finally{
...
}
-
void
修饰方法,表示方法没有返回值。 -
volatile
volatile关键字修饰的变量在多线程中保持同步。相比synchronized效率要高,不会阻塞线程。但只能保证数据的可见性,不能保证数据的原子性。例如在处理i++的时候另外一个线程修改i的值,那么i的值将会发生错误,这是原子性导致的。
volatile int a;
- while
while用于两种循环结构:
while(判读语句){
循环体...
}
do{
循环体...
}while(判读语句)