一、Java概述
Java是由Sun(stanfod university network)公司于1995年5月23日正式推出的一套计算机高级编程语言。
Java语言的特点
1、简洁高效
Java语言非常简洁,相比于C++中头文件、指针等各种抽象的概念,Java更好理解,便于上手,同时还提供了功能强大的系统类库,使开发变得更加简洁高效。
2、跨平台
程序在不同平台的兼容性问题一直困扰着开发者,如果我们开发的程序能够无障碍地同时运行在Windows、Mac OS和Linux系统中,那将非常完美。而Java就可以一套代码运行在多个平台。
3、面向对象
面向对象是一种编程思想,这种思想地诞生,对于软件工程有着划时代地意义,开发者告别了面向过程开发地繁琐步骤,从一个新地维度重新读编程这件事,极大地提升了软件开发效率和能力,Java就是这样一种面向对象的高级编程语言。
4、分布式计算
Java提供了一套网络操作类库,很适合开发分布式计算的程序,开发者可以通过调用类库进行网络程序开发,实现分布式特性。
5、健壮性
Java提供了非常强大的排错机制,在程序编译阶段就可以检测出程序中的错误,无需等到运行时才暴露出存在的问题。同时在运行阶段会再一次进行相应的检查,多种手段保证了程序的稳定性和健壮性。
6、可处理多线程
线程是进程的基本单位,是程序开发中必不可少的一种基础资料,Java提供了良好的多线程处理机制,使程序具备更为优秀的交互性。
Java的运行机制
Java开发分为三步:
- 在后缀.java地文件中编写Java程序,此文件称之为Java源文件
- 通过编译器将源文件编译为后缀为.class地字节码文件
- 计算机读取字节码文件运行程序
编译器可以理解为翻译,它可以将开发者写地程序翻译成计算机能识别地二进制数据
Java拥有自己的虚拟计算机,这个虚拟的计算机有自己的内存,有自己的磁盘,被称为Java虚拟机(Java virtual machine,JVM)所有的Java程序都运行在JVM上。
Java程序能够做到跨平台运行,也是因为JVM,不同的操作系统上只要安装上了JVM,就可以运行Java程序,JVM可以将不同操作系统的底层运行机制进行屏蔽。而编译好的字节码文件只需要识别JVM,而不需要关心更底层的操作系统,由JVM去适应识别操作系统。
Java三大体系
Java语言衍生了三个体系分支,分别是J2SE、J2ME、J2EE
J2SE(Java2 platform standard edition)定义了Java的核心类库,包含了各种常用组件,是Java开发的基础
J2ME(Java2 paltform micro edition)是基于J2SE衍生出的专用于移动设备的开发组件,如手机、机顶盒、车载导航等
J2EE(Java2 platform enterprise edition)是基于J2SE扩展出的企业级开发组件,提供了Java Web相关的开发组件,如Servlet、JSP等,是Java开发的主流技术。
2005年之后,J2SE更名为Java SE、J2ME更名为Java ME、J2EE更名为Java EE。在三大体系中,Java SE是核心,Java ME和Java EE是在Java SE的基础上发展起来的
Java环境
Java环境主要分为:JRE和JDK
JRE(Java runtime environment)是Java的运行环境,包括JVM和Java基础类库,一台计算机要运行Java程序,就必须有JRE。
JDK(Java development kit)是Java开发包,它包含JRE和编译Java源文件的编译器,想要在一台计算机上进行Java程序开发,就必须安装JDK
JRE是Java程序运行环境,JDK是Java程序开发环境,而JDK包含了JRE,因此只需要安装JDK即可。
二、Java语法
1、关键字
Java关键字是指Java语言预先定义好的,有指定意义的标识符,是程序的核心组成。
关键字来构建程序的核心骨架,Java类库提供程序要调用的方法,开发者自定义的标识符来指定程序完成相关工作。
Java关键字可以表示一个基本数据类型,可以表示流程控制,可以作为类和方法的修饰符等,但是不能作为包名、类名、方法名、参数名、变量名。Java关键字全部为小写。
2、变量
变量是计算机语言中的一个概念,可以表示某个具体数值,并且这个值可以改变,所以叫变量。与之对应的是常量,常量也是用来表示某个数值的,但值是固定的,不能改变。
计算机存储数据的地方叫作内存,内存会为不同的数据开辟不同的空间来存储,所以数据和数据之间是相互独立的,互不影响。
每一个内存空间都有自己独一无二的地址,程序就是通过内存地址找到具体的内存空间,从中取出数据。内存地址是十六进制的数据
变量是一个概念,存储在内存中,方便存取内存中的数据,是程序中存储数据的基本单元。变量有三要素:数据类型、变量名、变量值
int a = 10;
数据类型 变量名 变量值
- 数据类型是变量中保存的值的数据类型,不同的数据需要用不同的类型来保存,整数、小数、文本信息、日期等都需要用不同的数据类型来表示。
- 变量名由开发者自己定义,给存储数据的内存地址取别名
- 变量值就是内存中存储的数据。
使用变量
1、声明变量的数据类型和变量名,计算机根据数据类型在内存中开辟相应大小的空间,同时变量名的定义要符合规则,可以包含数字、字母、下划线、$,但不能包含空格、运算符,不能用纯关键字命名,不能以数字开头,大小写字母可混用,首字母应小写,后续单词的首字母应大写,如myName
2、给内存空间赋值,该值就是变量值
public class TestCode(){
public static void main(String[] args){
// 开辟内存空间,数据类型是int
int num;
// 赋值
num = 10;
}
}
3、基本数据类型
Java共有8种基本数据类型,程序种常用的数据类型有整数、小数、字母、单词和汉字。这些数据类型分为两类,数值类型和非数值类型。
| 分类 | 基本数据类型 | 所占空间 |
|---|---|---|
| 数值类型 | byte | 1字节(8位) |
| 数值类型 | int | 4字节 |
| 数值类型 | short | 2字节 |
| 数值类型 | long | 8字节 |
| 数值类型 | float | 4字节 |
| 数值类型 | double | 8字节 |
| 非数值类型 | char | 2字节 |
| 非数值类型 | boolean | 1/8字节 |
4、数据类型转换
4.1 自动转换
public class Test{
public static void main(String []args){
int num1 = 10;
double num2 = num1;
System.out.println(num1);
System.out.println(num2);
//输出 10 10.0
}
}
上面的程序虽然从结果来看数值并没有改变,但在计算机底层是两种完全不同的数据类型。由原来的int类型变为double类型,这一过程叫作自动类型转换,程序会自动去识别数据类型并完成转换
反之则不行。double类型的存储空间为8字节,int类型的存储空间为4字节,所以 int类型可以自动转为double类型,double类型不能自动转为int类型(自动转换成立,解释见下节)。
浮动型(double、float)描述数值的精度比整型(short、int、long)高,所以整型数据类型也可以自动转换为浮点型,即使long为8字节,float为4字节,不满足只能由低字节向高字节进行转换的原则,也同样可以完成自动转换。我们说的自动类型转换只包括所有数值类型,不包括char 和 boolean。
基本数据类型自动转换的关系:byte -> short -> int -> long -> float -> double
4.2 强制转换
上一节提到int类型可以自动转为double类型,而double类型不能自动转为int类型。这句话严格意义上来讲是错的。即double类型是可以转为int类型的只不过程序不会自动完成,需要我们手动干预进行强制转换。
public class Test{
public static void main(String []args){
double num1 = 10.5;
int num2 = (int) num1;
System.out.println(num1);
System.out.println(num2);
// 输出 10.5 10
}
}
通过程序结果可以看到double在转为int时会造成精度损失,由10.5变成了10,小数点后全部丢弃,将浮点型数值强转为整型时,只保留小数点左边的数值,不会按照四舍五入的方式来完成整数位的进位。
5、运算符
5.1 赋值运算符
赋值运算符顾名思义就是用来做赋值操作的,更准确地来讲就是将数值赋给某个变量,或者将一个变量的值赋给另外一个变量。语法 “ 数据类型变量名=数值/变量; ” 表示将等号右边的值赋给等号左边。
public class Test{
public static void main(String []agrs){
int num = 10;
int num1 = num;
}
}
5.2 基本算术运算符
使用基本算术运算符可以完成Java程序的基本数学运算,这只适用于数值类型的变量(+除外,它可以用作字符串拼接),包括 +、-、*、/、%、++、–。
其中 +、-、*、/、%会自动完成操作数的数据类型转换,由低字节转为高字节,比如“ 10.1 + 5”,会转换为“ 10.1 + 5.0 ”进行计算。
注意:a++ 与 ++a是有区别的,a++表示当前操作先取出变量a的值,在进行运算(a进行加一);++a表示当前操作先进行运算(对a进行加一),再取出变量a的值
5.3 复合算术运算符
复合算术运算符可以在基本算术运算符的基础上进一步简化代码,包括 +=、-=、*=、/=、%=。
代码a += b表示先计算变量a与变量b的之和,再把计算之和赋值给变量a,等同于a = a + b,其他的类似。
5.4 关系运算符
关系运算符用来计算一个表达式是否成立,只有两种结果,即成立或者不成立。关系运算符有:==、!=、>、<、>=、<=。其中>、<、>=、<=只能用作数值类型的比较,==、!=除了可以比较数值类型,也可以比较两个对象是否相等。
对象是存储再内存中的,比较两个对象是否相等,实际上就是比较两个对象的内存地址是否相等。如果两个对象的内存地址相等,那就表明它们是同一个对象。
5.5 逻辑运算符
逻辑运算符只能用于boolean类型的数据运算,判断boolean数据之间的逻辑关系,包括与(&)、或(|)、非(!)三种关系,其中与、或还有短路与(&&)、短路或(||)。
| 类型 | 描述 |
|---|---|
| a & b | 当a和b都为true时,结果为true,否则为false |
| a && b | 当a和b都为true时,结果为true,否则为false |
| a | b | 当a或者b有一个为true,结果都为true,否则为false |
| a || b | 当a或者b有一个为true,结果都为true,否则为false |
| a ! b | 若a为true,结果为false;若变量为false,则结果为true |
&和&&,|和||的区别:&操作只有两个操作数都为true,结果才为true,否则为false,如果在a & b中,a为false,还需要计算判断b,再给出结果。如果使用 a && b,如果a为false,则不要进行判断b,直接给出结果-false。从效率的角度考虑,&&会少执行一次判断,所以&&比&更加高效。|与||同理。
5.6 条件运算符
条件运算符也叫三元运算符。可以完成给变量赋值的操作,根据不同的条件完成不同的操作。基本语法变量a = 条件 ? 值1 :值2
public class Test{
public static void main(String []args){
int a = 10;
String result = a > 5 ? "a大于5" : "a小于5";
System.out.println(result);
// 输出 a大于5
}
}
5.7 位运算符
位运算符是指对表达式以二进制为单位进行运算。位运算符按位与(&)、按位或(|)、按位与或(^)、左移(<<)、右移(>>)
| 类型 | 描述 |
|---|---|
| a & b | a、b变量转换为二进制数,每一位的数字一一对应,若都为1,则记作1,否则为0 |
| a | b | a、b变量转换为二进制数,每一位的数字一一对应,只要有一个为1,则该位记作1,否则记作0 |
| a^b | a、b变量转换为二进制数,每一位的数字一一对应,相同记作0,不同记作1 |
| a << b | a乘以2的b次方,a * (2^b) |
| a >> b | a除以2的b次方,a / (2^b) |
计算 10 & 5
1 0 1 0
0 1 0 1
-———
0 0 0 0
所以,计算后 10&5 的结果是0000
如何区分逻辑运算符和位运算符?通过操作数来判断,如果操作是boolean类型,则为逻辑运算符;如果操作数为数值类型,则为位运算符
三、流程控制
1、if-else
if-else是一个基本的流程控制语法,用于判断某个条件是否成立,然后执行不同的逻辑,基本语法如下:
if( 判断条件 ){
// 条件成立的语句
}else{
// 条件不成立的语句
}
2、多重if
public class Test{
public static void main(String []args){
int num = 100;
if(num > 90){
System.out.println("成绩不错!");
}else if(num > 60){
System.out.println("你及格了");
}else{
System.out.println("你没有及格");
}
}
}
if-else的使用是比较灵活的,可以根据不同情况选择不同的组合方式,需要注意的是:
- if 后面必须跟(条件);
- else 后面不能跟(条件);
- else 后面可直接跟{},也可跟if语句。
3、if嵌套
如果遇到条件中包含子条件,那么使用单一的if-else或者多重if已经不能满足需求了。因为单一的if-else和多重if只能在一个维度处理逻辑,如果再增加一个维度,就需要使用if嵌套来完成。
// 成绩大于90分且年龄等于10岁的学生
public class Test{
public static void main(String []args){
int num = 100;
int age = 9;
if(num > 90){
System.out.println("成绩不错!");
if(age == 10){
System.out.println("你是10岁的学生");
}else{
System.out.println("你不是10岁的学生");
}
}else if(num > 60){
System.out.println("你及格了");
}else{
System.out.println("你没有及格");
}
}
}
4、switch-case
switch-case也可以完成流程控制,与if不同的是,switch-case只能完成等值判断,即条件如果是判断两个值是否相等,可以使用switch-case,如果是比较两个值的大小关系,则不能使用switch-case。switch支持 int、short、byte、char、枚举、String 数据类型的判断,不支持boolean类型。
// 参加比赛,第一名奖励2000,第二名奖励1000,第三名奖励500,否则没有奖励
public class Test{
public static void main(String []args){
int placing = 1;
switch(placing){
case 1:
System.out.println("奖励2000");
break;
case 2:
System.out.println("奖励1000");
break;
case 3:
System.out.println("奖励500");
break;
default:
System.out.println("没有奖励");
break;
}
}
}
需要注意的是,每一个case语句必须要跟break,表示结束当前的代码块,如果不跟break,则从当前的case语句起,后面所有的case判断都失效,都会直接执行对应的代码块。
四、循环
循环在程序开发中非常重要,也是使用频率很高的语法,使用循环语句可以非常有效的缩减代码,使得代码编写简洁高效。
循环存在四个要素,分别是(1)初始化变量(2)循环条件(3)循环体(4)更新循环变量
循环分为三种,分别是while循环,for循环,do-while循环。
1、while循环
// 基本语法
while(循环条件){
// 循环体
}
当循环条件成立时,会重复执行循环体中的代码,直到条件不成立。并且应该在循环体中动态控制循环条件是否成立,否则就成了死循环。以打印五次hello world来说明while循环的四要素。
public class Test{
public static void main(String []args){
int i = 0; // 初始化循环变量
while(i < 5){ // 循环条件
System.out.println("Hello World"); // 循环体
i++; // 更新循环变量
}
}
}
2、 do-while循环
do-while循环和while循环很类似,区别在于do-while循环会先执行一次循环体,再做判断,而while循环是必须先判断,在决定是否执行循环体。如果循环条件不成立,while循环一次都不会执行,do-while循环会执行一次循环体。
// 基本语法
do{
// 循环体
}while(循环条件)
/*
* 打印5次hello world
*/
public class Test{
public static void main(String []args){
int i = 0;
do{
System.out.println("Hello World");
i++;
}while(i < 5)
}
}
3、for循环
for循环也是很常用的一种循环语法,它与while循环的最大区别在于while循环适用于循环次数不确定的场景,如张三参加体能测试,成绩合格就停止循环,否则循环一直进行,这时循环次数是不确定的。for循环适用于循环次数确定的场景,如输出10次“HelloWorld”,很明确要执行10次循环。
// 基本语法
for(初始化循环遍历; 循环条件; 更新循环变量){
// 循环体
}
/*
* 打印5次hello world
*/
public class Test{
public static void main(String []args){
for(int i = 0; i < 5; i++){
System.out.println("Hello World");
}
}
}
while、do-while、for三种循环的区别:
- 相同点: 都遵循循环四要素,即初始化循环变量、循环条件、循环体、更新循环变量。
- 不同点: while 和 do-while 适用于循环次数不确定的场景,for适用于循环次数确定的场景;while 和 for 是先判断循环条件,再执行循环体;do-while是先执行循环体,再判断循环条件。
4、嵌套循环
上面都是在介绍一维结构的循环,如果想要完成更多复杂的功能,则需要进行循环嵌套。
例如:如何使用循环结构,打印如下图形
*
* * *
* * * * *
public class Test{
public static void main(String []args){
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3-i; j++){
System.out.print(" ");
}
for(int z = 0; z < (i+1)*2-1; z++){
System.out.print("*");
}
System.out.println("");
}
}
}
手动终止循环有两种方式:break和continue。两者的区别是,break表示跳出整个循环体;continue表示跳出本次循环,进入下一次循环
五、数组
数组就是一种可以存放大量数据类型相同的变量的数据结构,是一个具有相同数据类型的数据集合。数组中的数据必须是同一种数据类型,可以类比现实生活中学校的所有学生、机房里的所有计算机等。我们使用变量来保存数据,需要在内存中开辟一块空间,而数组就是在内存中开辟一串连续的空间来保存数据。
一个数组由四种基本元素构成,(1)数组名称(2)数组元素(3)元素下标(4)数据类型。数组本身也是一个变量,也需要定义变量名,也就是数组名称。数组中保存的每一个数据都会有一个下标(从0开始),相当于编号,通过编号可以快速检索到对应的元素。
1、数组
数组也是一个变量,创建数字的步骤和创建普通变量基本一致,分为如下步骤。
- 声明数组:数据类型[] 数组名;如 “ int[] array; ” 表示声明了一个int类型的数组,该数组中只能存放int类型的数据,“ String[] array; ” 表示声明了一个 String类型的数组,该数组中只能存放 String 类型的数据。
- 分配内存空间:创建数组必须要指定数组的长度,根据指定长度在内存中开辟一串连续的空间,并且长度不能修改。语法:“ 数组名 = new 数据类型[数组长度] ”。例如 “ array=new int[6]; ”表示array的长度为6。
- 给数组赋值:分配完内存空间就可以向数组中存值,通过下标找到数组中对应的内存空间,完成赋值。如 “ array[0] = 1; array[2] = 3;”。
public class Test{
public static void main(String []args){
int[] array;
array = new int[5];
array[0] = 1;
array[1] = 2;
array[2] = 3;
array[3] = 4;
array[4] = 5;
System.out.println(array[3]);
}
}
// 声明数组和开辟空间可以使用一行代码编写
// int[] array = new int[4];
声明数组时,[]可以放在数据类型的后面,也可以放在数组名后面,即 int[] array 和 int array[] 都可以。
边声明边赋值有两种方式,如下所示:
int[] array = {1,2,3};
int[] array = new int[]{1,2,3};
数组与之前介绍的变量在内存中的保存方式是不同的。内存可以简单分为栈内存和堆内存。基本数据类型的变量和值都保存在栈内存中,在栈内存开辟的空间中直接放入数据。
引用数据类型的变量保存在栈内存中。而变量的值,也就是引用实际指向的对象,保存在堆内存中,即栈内存保存的是堆内存的地址。什么是引用数据类型?这里可以简单记为只要是通过new关键字创建的变量都是引用类型。
Java提供了一个工具类,通过调用该工具类的方法可以完成对数组的操作。这个类是 Arrays,它保存在java.util包中,提供了多种操作数组的方法,比如对数组的元素进行排序,求出数组的最大最小值等。
2、二维数组
如果一维数组中保存的值是其他数组的内存地址,那这种结构的数组就是二维数组。二维数组的使用与一维数组类似:(1)声明(2)开辟内存空间(3)赋值
public class Test{
public static void main(String []args){
int[][] array = new int[2][2];
array[0][0] = 1;
array[0][1] = 11;
array[1][0] = 2;
array[1][1] = 22;
System.out.println(array[0][1]);
}
}
// 边声明边赋值
// int[][] array = {{1,2,3},{4,5,6}};
// int[][] array = new int[][]{{1,2,3},{4,5,6}};