JVM,JRE与JDK
java语言有一个非常显著的特征就是跨平台性,无论在什么操作系统上,java程序都能够运行,这就得益于java的JVM。
- JVM
java虚拟机,简称JVM(java virtual machine),是运行java程序的假想计算机,是java程序的运行环境,我们编写的java代码,都运行在JVM上。
JVM为什么能使java具有跨平台性呢?原因就在于每个操作系统都具有一个不同的JVM,这些JVM充当了java程序与操作系统之间的中介,java程序直接运行在JVM中,形成的字节码在转运到操作系统,使得java程序在不同平台不需要重新编译,具有跨平台性。 - JRE与JDK
JRE(Java Runtime Environment),是java程序运行时所需的环境,包括JVM和运行时所需要的核心类库,如果只需要运行java程序的话,那么只需要JRE即可。
JDK(Java Development Kit),是java程序开发的工具包,包括JRE和开发人员使用的工具,如果需要开发java程序,那么就需要安装JDK了。
这三者的关系是JDK>JRE>JVM,如下图所示
用cmd运行java程序
首先将cmd定位在java程序所在的文件夹中,然后依次使用javac命令和java命令,javac是对java程序进行编译成class字节码,java命令则是运行编译好的class文件,具体操作如下图所示,其中Test.java是我已经编写好的程序
java程序的注释
java程序的注释与c++类似,有2种注释方法:单行注释和多行注释
单行注释://注释内容,//之后的内容将被计算机忽略
多行注释:/* 注释内容,/* */之间的内容将被计算机忽略,可以跨行 */
java关键字和标识符的命名规范
和c++语言类似,java也有预先定义的关键字,这些关键字都是全小写,都有特定含义,变量名和类名等都不能与关键字相同。java区分大小写,所以,命名时可以使用标识符的大写,但不建议。
标识符就是我们自己定义的内容的名称,标识符可以包含英文字母,数字,美元符号$和下划线_,但标识符不能以数字开头
建议标识符的命名规范:
- 类名规范:首字母大写,后面每个单词的首字母大写(大驼峰式)
- 变量名规范:首字母小写,后面每个单词首字母大写(小驼峰式)
- 方法名规范:同变量名
常量与变量
- 1.常量分为字符串常量,整数常量,浮点数常量,字符常量,布尔常量,空常量,用const修饰
字符串常量:String,以’\0’结束,如”abc”,”123”,占n+1个字节,其中n为组成字符串的字符个数。
整数常量:short(2字节),int(4字节),long(8字节)
浮点数常量:float(4字节),double(8字节)
字符常量:char(1字节)
布尔常量:bool(1字节)
空常量:null(0字节) - 2.变量,即可以改变的常量,没有const修饰的常量,其类型与常量相同
变量的使用注意事项: - 如果创建多个变量,变量名不可以重复
- 对于float和long类型,字母后缀的F和L不要去掉
- 如果使用byte和short类型的变量,右侧的数据值不要超过左侧类型的范围
- 一定要对变量赋值后才能使用
- 变量使用不能超过作用域
数据类型转换
- 自动类型转换,数据类型从小到大,将会自动发生类型转换。
- 强制类型转换,当数据类型从大到小,则需要强制转换,不能自动完成,可能会发生精度损失
1
2
3
4
5
6
7
8
9
10//自动转换
int a=100;
long b=a; //从int到long,自动转换
float c=0.1;
double d=c; //从float到double,自动转换
//强制转换
int num = 100L; //会报错,int无法自动转换为long
int num = (int)100L; //正确,实现了强制转换
char s='a';
a=(int)s; //正确,将字符串强制转化成int整数,将会输出a的ASCII码
ASCII码表
ASCII是使用7位二进制数(剩下的1位二进制为0)来表示所有的大写和小写字母,数字0 到9、标点符号,基本上所有的计算机语言都会用到ASCII码进行编码,JAVA也是如此,只不过java也是使用了Unicode编码,把ASCII码表放在这里便于查看
java编译器的一些优化
- 对于byte,short,char三种类型,如果右侧赋值的数据大小没有超过范围,那么java编译器会自动加上(byte),(short),(char),例如:
byte a = 30 <==> byte a = (byte) 30 - 但是,当右侧赋值的数据大小超过范围后,java编译器则会直接报错
- java中的加法默认将加数当作int数据类型,所以使用2个short类型的变量相加赋予另一个short类型时,编译器会报错,但是当short类型的右边赋予的是两个常量相加,那么编译器不会报错,而是会直接先将常量相加直接赋予short:报错原因:
1
2
3
4short a=10;
short b=20;
short c=a+b; //会报错
short c=10+20; //正确
jshell的使用
jshell是java的交互式运行环境,类似于python的命令行的交互式运行环境,直接在命令提示符中输入jshell进入Java交互环境,之后直接输入一条java语句,便能直接输出语句结果,注意jshell中的语句不用以分号结尾。
选择结构
1.if语句
在Java程序中,如果要根据条件来决定是否执行某一段代码,就需要if语句。根据if的计算结果(true还是false),JVM决定是否执行if语句块(即花括号{}包含的所有语句)。
2.除了if语句外,还有一种条件判断,是根据某个表达式的结果,分别去执行不同的分支。switch语句根据switch (表达式)计算的结果,跳转到匹配的case结果,然后继续执行后续语句,直到遇到break结束执行。switch语句的基本语法是:
1 | switch (option) { |
循环结构
循环语句就是让计算机根据条件做循环计算,在条件满足时继续循环,条件不满足时退出循环。
除了for,while外,Java还提供了一种for each循环,它可以更简单地遍历数组,和for循环相比,for each循环的变量n不再是计数器,而是直接对应到数组的每个元素。但是,for each循环无法指定遍历顺序,也无法获取数组的索引。它的用法如下所示:
1 | int[] ns = { 1, 4, 9, 16, 25 }; |
break和continue
break
在循环过程中,可以使用break语句跳出当前循环,break会跳出当前循环,当有多个嵌套的循环时,break只能跳出最内层的循环,然后剩下的循环都不会执行了。
continue
continue是提前结束本次循环,直接继续执行下次循环,在多层嵌套的循环中,continue语句同样是结束本次自己所在的循环。比如算从1-100的奇数的和时用continue就会很方便:
1 | int sum=0; |
方法
方法的注意事项
- 方法必须定义在类中,且不能在方法中再定义方法
- 方法定义的前后顺序无所谓
- 如果方法有返回值,那么必须加上return返回值,不能没有
- 对于void方法,不能return加返回值,只能直接return;
- 一个方法可以有多个return语句,但是必须保证能执行的只有一个
方法重载
在一个类中,我们可以定义多个方法。如果有一系列方法,它们的功能都是类似的,只有参数有所不同,那么,可以把这一组方法名做成同名方法,这种方法名相同,但各自的参数不同,称为方法重载(Overload),方法重载的目的是,功能类似的方法使用同一名字,更容易记住,因此,调用起来更简单。
例如,String类提供了多个重载方法indexOf(),可以查找子串:
- int indexOf(int ch):根据字符的Unicode码查找;
- int indexOf(String str):根据字符串查找;
- int indexOf(int ch, int fromIndex):根据字符查找,但指定起始位置;
- int indexOf(String str, int fromIndex)根据字符串查找,但指定起始位置。
重载的注意事项
1.方法的重载与下列因素相关:
- 参数的个数不同
- 参数的类型不同
- 参数的多类型顺序不同
1 | public static int sum(int x,int y); |
2.方法的重载与下列因素无关:
- 与参数的名称无关
- 与方法的返回值类型无关
1 | public static int sum(int x,int y); |
数组
定义一个数组类型的变量,使用数组类型“类型[]”,有以下几种创建方法:
- int[] a={1,2,3,4,5}; //根据{}之间的元素个数自动创建
- int[] a=new int{1,2,3,4,5} //同上
- int[] a=new int[5];a={1,2,3,4,5}; //先创建容量为5的数组,再赋值
数组的内存
1.当动态创建一个数组时,系统将会在栈区先写入数组名称,然后在堆区开辟空间存放数组元素,其中数组的索引也是存放在栈区的,当你要修改数组元素的值时,你首先将访问栈区的索引,然后这个索引再指向堆区对应的内存,如下图所示:
2.当一个数组赋值给另一个数组时:int[] arrayB = arrayA;这时候是将arrayA的地址直接赋值给arrayB了,此时arrayA和arrayB共用一个内存,本质上时同一个数组,其内存分配如下所示:
数组注意事项:
- 数组所有元素初始化为默认值,整型都是0,浮点型是0.0,布尔型是false;
- 要访问数组中的某一个元素,需要使用索引。数组索引从0开始
- 可以修改数组中的某一个元素,使用赋值语句
- 可以用数组变量.length获取数组大小
- 数组是引用类型,在使用索引访问数组元素时,如果索引超出范围,运行时将报错
- 直接输出数组名称将会得到数组的首地址
- 数组的2个异常:超出数组索引(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException):创建一个空数组时访问数组元素将会出现空指针异常
数组的使用
1.简单遍历输出
由于java提供了获取数组长度的方法(array.length),所以对于数组的遍历非常方便:
1 | int[] array={1,2,3,4,5}; |
2.查找数组最大值
以最大值为例,只需要用一个变量记录首元素,在遍历数组时,每次比较得出最大值更新这个变量即可
1 | int[] array={6,5,4,3,2,1}; |
3.数组的排序
对数组的排序中,常用的排序算法有冒泡排序、插入排序和快速排序等。以冒泡排序为例:
1 | for (int i = 0; i < ns.length - 1; i++) { |
在java中,其标准库内已经内置了排序功能,我们也可以对它直接进行调用:
1 | import java.util.Arrays; |
二维数组
二维数组可以理解为在一个数组中再定义数组,例如:
int[][] ns = {
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 }
};
因为ns包含3个数组,所以ns的长度为3
二维数组的内存
二维数组在系统中的内存占用如下:
打印二维数组
打印二维数组可以用两层嵌套循环:
1 | for (int[] arr : ns) { |
也可以直接使用Java标准库的Arrays.deepToString()直接打印二维数组。