java各版本含义
- JavaSE:标准版,定位在个人计算机上的应用
- JavaEE:企业版,定位在服务器端的应用
- JavaME:微型版,定位在消费性电子产品应用上
java核心优势
java核心优势:跨平台/可移植性
如:java 的int永远都是32位,不像c++可能是16,可能是32位(根据编译器厂商规定而变化)
- 跨平台/可移植
- 安全性
- 面向对象
- 简单
- 高性能
- 分布式
- 多线程
- 健壮性
java应用程序运行机制
计算机高级语言类型主要有编译型和解释型。而java语言是两种类型的结合。
Java首先利用文本编辑器编写 Java源程序,源文件的后缀名为**.java**;再利用编译器(javac)将源程序编译成字节码文件,字节码文件的后缀名为**.class**; 最后利用虚拟机JVM(解释器,java)解释执行。
JVM、JRE和JDK
-
JVM(Java Virtual Machine)就是一个虚拟的用于执行bytecode字节码的”虚拟计算机”。Java 虚拟机机制屏蔽了底层运行平台的差别,实现了“一次编译,随处运行”。 Java虚拟机是实现跨平台的核心机制。
-
JRE( Java Runtime Environment )包含:Java虚拟机、库函数、运行Java应用程序所必须的文件。
-
JDK(Java Development Kit )包含:包含JRE,以及增加编译器和调试器等用于程序开发的文件。
**·**如果只是要运行Java程序,只需要JRE就可以。JRE通常非常小,其中包含了JVM。
**·**如果要开发Java程序,就需要安装JDK。
环境变量Path
环境变量是在操作系统中一个具有特定名字的对象, 它包含了一个或者多个应用程序所将使用到的信息。
Path是一个常见的环境变量,它告诉操作系统,当要求系统运行一个程序而没有告诉它程序所在的完整路径时,系统除了在当前目录下寻找此程序外,还应到哪些目录下寻找。
测试JDK安装成功
进入命令行窗口,开始菜单搜索框输入“cmd”即可,如图1-18所示。在窗口中输入命令“java -version ”,回车。显示版本信息,则说明JDK安装成功。
使用记事本运行程序
-
编译(编译器创建class字节码文件)
打开命令行窗口,进入Java文件所在目录;执行命令:javac Welcome.java,生成class文件。
-
解释并运行阶段
执行:”java Welcome”(就是运行编译生成的Welcome.class文件),输出执行结果。
第一个程序总结
- Java对大小写敏感
- 关键字public被称作访问修饰符(access modifier),用于控制程序的其它部分对这段代码的访问级别。
- 关键字class 的意思是类。Java是面向对象的语言,所有代码必须位于类里面。
- 个源文件中至多只能声明一个public的类,其它类的个数不限,如果源文件中包含一个public 类,源文件名必须和其中定义的public的类名相同,且以“.java”为扩展名。
- 一个源文件可以包含多个类class。
常用DOS命令
操作 | 说明 |
---|---|
cd 目录路径 | 进入一个目录 |
cd … | 进入父目录 |
dir | 查看本目录下的文件和字目录列表 |
cls | 清除屏幕命令 |
上下键 | 查找敲过的命令 |
Tab键 | 自动补齐命令 |
数据类型和运算符
注释
-
单行注释: 使用“//”开头,“//”后面的单行内容均为注释。
-
多行注释: 以“/”开头以“/”结尾,在“/”和“/”之间的内容为注释(行内注释)
-
文档注释:以“/**”开头以“*/”结尾。注释中包含一些说明性的文字及一些JavaDoc标签(后期写项目时,可以生成项目的API)
/** * Welcome类(我是文档注释) * @author * @version 1.0 */ public class Welcome { //我是单行注释 public static void main(String[] args/*我是行内注释 */) { System.out.println("Hello World!"); } /* 我是多行注释! 我是多行注释! */ }
标识符
标识符是用来给变量、类、方法以及包进行命名的
规则:
- 标识符必须以字母、下划线_、美元符号$开头。
- 标识符其它部分可以是字母、下划线“_”、美元符“$”和数字的任意组合。
- Java 标识符大小写敏感,且长度无限制。
- 标识符不可以是Java的关键字。
标识符使用规范
-
表示类名的标识符:每个单词的首字母大写,如Man, GoodMan
-
表示方法和变量的标识符:第一个单词小写,从第二个单词开始首字母大写,我们称之为“驼峰原则”,如eat(), eatFood()
Java不采用通常语言使用的ASCII字符集,而是采用Unicode这样标准的国际字符集。因此,这里字母的含义不仅仅是英文,还包括汉字等等。但是不建议大家使用汉字来定义标识符!
变量本质
变量本质上就是代表一个”可操作的存储空间”,空间位置是确定的,但是里面放置什么值不确定。我们可通过变量名来访问“对应的存储空间”,从而操纵这个“存储空间”存储的值。
Java是一种强类型语言,每个变量都必须声明其数据类型。变量的数据类型决定了变量占据存储空间的大小。 比如,int a=3; 表示a变量的空间大小为4个字节。
-
变量声明
语法:
type varName [=value][,varName[=value]···];
double salary; long earthPopulation; int age;
-
注意
- 不同数据类型的常量会在内存中分配不同的空间
- 每个变量都有类型,类型可以是基本类型,也可以是引用类型。
变量分类
从整体上可将变量划分为局部变量、成员变量(也称为实例变量)和静态变量。
类型 | 声明位置 | 从属于 | 声明周期 |
---|---|---|---|
局部变量 | 方法或语句块内部 | 方法/语句块 | 从声明位置开始,直到方法或语句块执行完毕,局部变量消失 |
成员变量(实例变量) | 类内部,方法外部 | 对象 | 对象创建,成员变量也跟着创建。对象消失,成员变量也跟着消失; |
静态变量 | 类内部,static修饰 | 类 | 类被加载,静态变量就有效;类被卸载,静态变量消失。 |
public class TestVariable {
int a; //成员变量, 从属于对象; 成员变量会自动被初始化
static int size; //静态变量,从属于类
public static void main(String[] args) {
{
int age; //局部变量,从属于语句块;
age = 18;
}
int salary = 3000; //局部变量,从属于方法
int gao = 13;
System.out.println(gao);
int i;
// int j = i + 5; // 编译出错,变量i还未被初始化
}
}
常量
常量通常指的是一个固定的值,例如:1、2、3、’a’、’b’、true、false、”helloWorld”等。
在Java语言中,主要是利用关键字final来定义一个常量。 常量一旦被初始化后不能再更改其值。
声明格式
final type varName = value;
实例
public class TestConstants {
public static void main(String[] args) {
final double PI = 3.14;
// PI = 3.15; //编译错误,不能再被赋值!
double r = 4;
double area = PI * r * r;
double circle = 2 * PI * r;
System.out.println("area = " + area);
System.out.println("circle = " + circle);
}
}
为了更好的区分和表述,一般将1、2、3、’a’、’b’、true、false、”helloWorld”等称为字面常量,而使用final修饰的PI等称为符号常量。
变量和常量命名规范
- 类成员变量、局部变量 首字母小写和驼峰原则
- 常量: 大写字母和下划线: MAX_VALUE
- 类名: 首字母大写和驼峰原则
- 方法名:首字母小写和驼峰原则
基本数据类型
Java是一种强类型语言,每个变量都必须声明其数据类型。 Java的数据类型可分为两大类:基本数据类型(primitive data type)和引用数据类型(reference data type)。
Java中定义了3类8种基本数据类型
- 数值型- byte、 short、int、 long、float、 double
- 字符型- char
- 布尔型-boolean
引用数据类型: 类(calss)、接口(interface)、数组
- 引用数据类型的大小统一为4个字节,记录的是其引用对象的地址!
整型常量/变量
整型用于表示没有小数部分的数值,允许负数。整型的范围与允许java代码的机器无关。
类型 | 占用存储空间 |
---|---|
byte | 1字节 |
short | 2字节 |
int | 4字节 |
long | 8字节 |
Java整型常量的四种表示形式
- 十进制
- 八进制:以0开头,如015
- 十六进制:以0x开头,如0x15
- 二进制数,要求0b或0B开头,如0b0110011
java整型常量默认为int类型,声明long类型后面加’l’或’L’。
long a = 55555555//编译成功,在int表示范围内
long b = 55555555555555//不加L编译失败,已经超过int表示范围
修改为long类型常量即可
long b = 555555555555L
浮点型常量/变量
带有小数的数据在Java中称为浮点型。浮点型分为float和double类型
类型 | 占有存储空间 |
---|---|
float | 4字节 |
double | 8字节 |
float称为单精度类型,尾数可以精确到7位有效数字。
double双精度,精度为float类型的两倍。
浮点型常量默认类型为double
java浮点类型常量表示形式
- 十进制形式: 3.14 314.0 0.314
- 科学计数法,314e2 314E2 314E-2
使用科学计数法给浮点型变量赋值
double f = 314e2;
double f2 = 314e-2;-->3.14
flaot类型的数值后有一个后缀F/f,没有F/f的浮点数值默认为double类型,也可以在浮点数值添加后缀D/d,以明确为double类型
float = 3.14F;
double d1 = 3.14;
doble d2 = 3.14D;
BigDecimal
浮点类型,float,double的数据不适合在不容许舍入误差的金融计算领域,如果需要精确数字计算,需要使用BigDecimal类
浮点数的比较
float = 0.1f;
double = 1.0/10;
System.out.println(f==d);//结果为false,因为不精确
float d1 = 423432423f;
float d2 = d1+1;
if(d1==d2){
System.out.println("d1==d2");//输出结果为d1==d2(因为不精确)
}else{
System.out.println("d1!=d2");
}
java.math包下面的两个有用的类:BigInteger和BigDecimal,这两个类可以处理任意长度的数值。BigInteger实现了任意精度的整数运算。BigDecimal实现了任意精度的浮点运算。
使用BigDecimal进行浮点数的比较
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
BigDecimal bd = BigDecimal.valueOf(1.0);
bd = bd.subtract(BigDecimal.valueOf(0.1));
bd = bd.subtract(BigDecimal.valueOf(0.1));
bd = bd.subtract(BigDecimal.valueOf(0.1));
bd = bd.subtract(BigDecimal.valueOf(0.1));
bd = bd.subtract(BigDecimal.valueOf(0.1));
System.out.println(bd);//0.5
System.out.println(1.0 - 0.1 - 0.1 - 0.1 - 0.1 - 0.1);//0.5000000000000001
}
}
字符型常量/变量
字符型在内存中占2个字节,在Java中使用单引号表示字符串了。例如’A’是一个字符,它与”A”是不同的,”A”表示含有一个字符的字符串。
char 类型用来表示在Unicode编码表中的字符。Unicode编码被设计用来处理各种语言的文字,它占2个字节,可允许有65536个字符。
字符型举例
char eChar = 'a';
char cChar ='中';
Unicode具有从0到65535之间的编码,他们通常用从’\u0000’到’\uFFFF’之间的十六进制值来表示(前缀为u表示Unicode)
字符型的十六进制表示
char c = '\u0061';
Java 语言中还允许使用转义字符 ‘\’ 来将其后的字符转变为其它的含义。常用的转义字符及其含义和Unicode值如表2-6所示。
转义字符
char c2 = '\n'; //代表换行符
转移符 | 含义 |
---|---|
\b | 退格 backspace |
\n | 换行 |
\r | 回车 |
\t | 制表符 |
\ " | 双引号 |
\ ’ | 单引号 |
\ \ | 反斜杠 |
注意事项
- 以后我们学的String类,其实是字符序列(char sequence)。
/**
* 测试字符类型
*
*/
public class TestPrimitiveDataType3 {
public static void main(String[] args) {
char a = 'T';
char b = '尚';
char c = '\u0061';
System.out.println(c);
//转义字符
System.out.println(""+'a'+'\n'+'b');
System.out.println(""+'a'+'\t'+'b');
System.out.println(""+'a'+'\''+'b'); //a'b
//String就是字符序列
String d = "abc";
}
}
boolean类型变量/常量
boolean类型有两个常量值,true和flase,在内存中占一位。不可以使用 0 或非 0 的整数替代 true 和 false
boolean类型
` boolean flag ;
flag = true; //或者flag=false;
if(flag) {
// true分支
} else {
// false分支
}
运算符
运算符 | 符号 | |
---|---|---|
算数运算符 | 二元运算 | +,-,*,/ ,% |
一元运算符 | ++,– | |
赋值运算符 | = | |
扩展运算符 | +=,-=,*=,/= | |
关系运算符 | > ,<, >=,<=,==,!=,instanceof | |
逻辑运算符 | &&,||,!,^ | |
位运算符 | &,|,^,~,>>,<<,>>> | |
条件运算符 | ?: | |
字符串连接符 | + |
算数运算符
二元运算符规则:
整数运算:
- 如果两个操作数一个为long,则结果为long
- 没有long时,结果为int。即使操作数全为short,byte,结果也是int
浮点运算:
- 如果两个操作数有一个为double,则结果为double
- 只有两个数都是float,则结果才是float
取模运算:
- 其操作数可以为浮点数,一般使用整数
- 结果是余数,余数符号和左边操作数相同,如7%3=1,-7%3=-1,7%-3=1.
一元运算符
++,–
int a = 3;
int b = a++; //执行完后,b=3。先给b赋值,再自增。
System.out.println("a="+a+"\nb="+b);
a = 3;
b = ++a; //执行完后,c=5。a先自增,再给c赋值
System.out.println("a="+a+"\nb="+b);
赋值运算符及其扩展运算符
运算符 | 用法举例 | 等效的表达式 |
---|---|---|
+= | a += b | a = a+b |
-= | a -= b | a = a-b |
*= | a *= b | a = a*b |
/= | a *= b | a = a/b |
%= | a *= b | a = a%b |
扩展运算符
int a=3;
int b=4;
a+=b;//相当于a=a+b;
System.out.println("a="+a+"\nb="+b);
a=3;
a*=b+3;//相当于a=a*(b+3)
System.out.println("a="+a+"\nb="+b);
关系运算符
关系运算符用来进行比较运算,如表2-9所示。关系运算的结果是布尔值:true/false;
关系运算符
运算符 | 含义 | 示例 |
---|---|---|
== | 等于 | a==b |
!= | 不等于 | a!=b |
> | 大于 | a>b |
< | 小于 | a<b |
>= | 大于或等于 | a>=b |
<= | 小于或等于 | a<=b |
注意事项
- =是赋值运算符,而真正的判断两个操作数是否相等的运算符是==。
- ==、!= 是所有(基本和引用)数据类型都可以使用
- > 、>=、 <、 <= 仅针对数值类型(byte/short/int/long, float/double。以及char)
逻辑运算符
逻辑运算的操作数和运算结果都是boolean值。
运算符 | 说明 | |
---|---|---|
逻辑与 | &( 与) | 两个操作数为true,结果才是true,否则是false |
逻辑或 | |(或) | 两个操作数有一个是true,结果就是true |
短路与 | &&( 与) | 只要有一个为false,则直接返回false |
短路或 | ||(或) | 只要有一个为true, 则直接返回true |
逻辑非 | !(非) | 取反:!false为true,!true为false |
逻辑异或 | ^(异或) | 相同为false,不同为true |
位运算符
位运算指的是进行二进制位的运算
位运算符 | 说明 |
---|---|
~ | 取反 |
& | 按位与 |
| | 按位或 |
^ | 按位异或 |
<< | 左移运算符,左移1位相当于乘2 |
>> | 右移运算符,右移1位相当于除2取商 |
左移运算和右移运算
int a = 3*2*2;
int b = 3<<2; //相当于3*2*2
int c = 12/2/2;
int d = 12>>2;
雷区
1. &和|既是逻辑运算符,也是位运算符。如果两侧操作数都是boolean类型,就作为逻辑运算符。如果两侧的操作数是整数类型,就是位运算符。
2. 不要把“^”当做数学运算“乘方”,是“位的异或”操作。
字符串连接符
“+”运算符两侧的操作数中只要有一个是字符串(String)类型,系统会自动将另一个操作数转换为字符串然后再进行连接。
int a=12;
System.out.println("a="+a);//输出结果: a=12
条件运算符
语法
x ? y :z
其中 x 为 boolean 类型表达式,先计算 x 的值,若为true,则整个运算的结果为表达式 y 的值,否则整个运算结果为表达式 z 的值。
三目条件运算符
int score = 80;
int x = -100;
String type =score<60?"不及格":"及格";
int flag = x > 0 ? 1 : (x == 0 ? 0 : -1);
System.out.println("type= " + type);
System.out.println("flag= "+ flag);
运算符优先级
优先级 | 运算符 | 类 | 结合性 |
---|---|---|---|
1 | () | 括号运算符 | 由左至右 |
2 | !、+(正号)、-(负号) | 一元运算符 | 由左至右 |
2 | ~ | 位逻辑运算符 | 由右至左 |
2 | ++、– | 递增与递减运算符 | 由右至左 |
3 | *、/、% | 算术运算符 | 由左至右 |
4 | +、- | 算术运算符 | 由左至右 |
5 | <<、>> | 位左移、右移运算符 | 由左至右 |
6 | >、>=、<、<= | 关系运算符 | 由左至右 |
7 | ==、!= | 关系运算符 | 由左至右 |
8 | & | 位运算符、逻辑运算符 | 由左至右 |
9 | ^ | 位运算符、逻辑运算符 | 由左至右 |
10 | | | 位运算符、逻辑运算符 | 由左至右 |
11 | && | 逻辑运算符 | 由左至右 |
12 | || | 逻辑运算符 | 由左至右 |
13 | ? : | 条件运算符 | 由右至左 |
14 | =、+=、-=、*=、/=、%= | 赋值运算符、扩展运算符 | 由右至左 |
自动类型转换
自动类型转换指的是容量小的数据类型可以自动转换为容量大的数据类型。
byte–>short–>int–>long
char–>int
int–>long
int–>float(可能数据丢失)
int–>double
long–>float(可能数据丢失)
long–>double(可能数据丢失)
float–>double
可以将整型常量直接赋值给byte、 short、 char等类型变量,而不需要进行强制类型转换,只要不超出其表数范围即可。
自动转换特例
short b = 12; //合法
short b = 1234567;//非法,1234567超出了short的表数范围
强制类型转换
强制类型转换,又被称为造型,用于显式的转换一个数值的类型。在有可能丢失信息的情况下进行的转换是通过造型来完成的,但可能造成精度降低或溢出。
语法格式:
(type)var
强制类型转换
double x = 3.14;
int nx = (int)x; //值为3
char c = 'a';
int d = c+1;
System.out.println(nx); //3
System.out.println(d); //98
System.out.println((char)d); //b
当将一种类型强制转换成另一种类型,而又超出了目标类型的表数范围,就会被截断成为一个完全不同的值。
强制类型转换特例
int x = 300;
byte bx = (byte)x; //值为44
- 不能在布尔类型和任何数值类型之间做强制类型转换
基本类型转化常见错误和问题
操作比较大的数时,要留意是否溢出,尤其是整数操作时。
int money = 1000000000; //10亿
int years = 20;
//返回的total是负数,超过了int的范围
int total = money*years;
System.out.println("total="+total); //-1474836480
//返回的total仍然是负数。默认是int,因此结果会转成int值,再转成long。但是已经发生了数据丢失
long total1 = money*years;
System.out.println("total1="+total1);//-1474836480
//返回的total2正确:先将一个因子变成long,整个表达式发生提升。全部用long来计算。
long total2 = money*((long)years);
System.out.println("total2="+total2); //20000000000
简单的键盘输入和输出(Scanner)
使用Scanner获取键盘输入
import java.util.Scanner;
/**
* 测试获得键盘输入
*/
public class TestScanner {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入名字:");
String name = scanner.nextLine();
System.out.println("请输入你的爱好:");
String favor = scanner.nextLine();
System.out.println("请输入你的年龄:");
int age = scanner.nextInt();
System.out.println("###############");
System.out.println(name);
System.out.println(favor);
System.out.println("来到地球的天数:"+age*365);
System.out.println("离开地球的天数:"+(72-age)*365);
}
}
控制语句
选择结构
- if单选择结构
- if-else双选择结构
- if-else if-else多选择结构
- switch结构
if单选择结构
语法
if(布尔表达式){
语句块
}
public class Test1 {
public static void main(String[] args) {
//通过掷三个骰子看看今天的手气如何?
int i = (int)(6 * Math.random()) + 1;//通过Math.random()产生随机数
int j = (int)(6 * Math.random()) + 1;
int k = (int)(6 * Math.random()) + 1;
int count = i + j + k;
//如果三个骰子之和大于15,则手气不错
if(count > 15) {
System.out.println("今天手气不错");
}
//如果三个骰子之和在10到15之间,则手气一般
if(count >= 10 && count <= 15) { //错误写法:10<=count<=15
System.out.println("今天手气很一般");
}
//如果三个骰子之和小于10,则手气不怎么样
if(count < 10) {
System.out.println("今天手气不怎么样");
}
System.out.println("得了" + count + "分");
}
}
Math类的使用
1**.**java.lang包中的Math类提供了一些用于数学计算的方法。
2.Math.random()该方法用于产生一个0到1区间的double类型的随机数,但是不包括1。
int i = (int) (6 * Math.random()); //产生:[0,6)之间的随机整数
注意
1.如果if语句不写{},则只能作用于后面的第一条语句
if-else双选择结构
语法
if(布尔表达式){
语句块1
}else{
语句块2
}
当布尔表达式为真时,执行语句块1,否则,执行语句块2。也就是else部分。
案例
public class Test2 {
public static void main(String[] args) {
//随机产生一个[0.0, 4.0)区间的半径,并根据半径求圆的面积和周长
double r = 4 * Math.random();
//Math.pow(r, 2)求半径r的平方
double area = Math.PI * Math.pow(r, 2);
double circle = 2 * Math.PI * r;
System.out.println("半径为: " + r);
System.out.println("面积为: " + area);
System.out.println("周长为: " + circle);
//如果面积>=周长,则输出"面积大于等于周长",否则,输出周长大于面积
if(area >= circle) {
System.out.println("面积大于等于周长");
} else {
System.out.println("周长大于面积");
}
}
}
if-else if -else多选择结构
语法
if(布尔表达式1) {
语句块1;
} else if(布尔表达式2) {
语句块2;
}……
else if(布尔表达式n){
语句块n;
} else {
语句块n+1;
}
switch
语法
switch (表达式) {
case 值1:
语句序列1;
[break];
case 值2:
语句序列2;
[break];
… … … … …
[default:
默认语句;]
}
switch语句会根据表达式的值从相匹配的case标签处开始执行,一直执行到break语句处或者是switch语句的末尾。如果表达式的值与任一case值不匹配,则进入default语句(如果存在default语句的情况)。
根据表达式值的不同可以执行许多不同的操作。switch语句中case标签在JDK1.5之前必须是整数(long类型除外)或者枚举,不能是字符串,在JDK1.7之后允许使用字符串(String)。
案例
public class Test6 {
public static void main(String[] args) {
char c = 'a';
int rand = (int) (26 * Math.random());
char c2 = (char) (c + rand);
System.out.print(c2 + ": ");
switch (c2) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
System.out.println("元音");
break;
case 'y':
case 'w':
System.out.println("半元音");
break;
default:
System.out.println("辅音");
}
}
}
循环结构
循环结构分两大类,一类是当型,一类是直到型。
当型:
当布尔表达式条件为true时,反复执行某语句,当布尔表达式的值为false时才停止循环,比如:while与for循环。
直到型:
先执行某语句, 再判断布尔表达式,如果为true,再执行某语句,如此反复,直到布尔表达式条件为false时才停止循环,比如do-while循环。
while循环
语法
while (布尔表达式) {
循环体;
}
求1到100之间的累加和
public class Test7 {
public static void main(String[] args) {
int i = 0;
int sum = 0;
// 1+2+3+…+100=?
while (i <= 100) {
sum += i;//相当于sum = sum+i;
i++;
}
System.out.println("Sum= " + sum);
}
}
do-while
语法
do {
循环体;
} while(布尔表达式) ;
do-while循环结构会先执行循环体,然后再判断布尔表达式的值,若条件为真,执行循环体,当条件为假时结束循环。do-while循环的循环体至少执行一次。
1-100之间的累加和
public class Test8 {
public static void main(String[] args) {
int i = 0;
int sum = 0;
do {
sum += i; // sum = sum + i
i++;
} while (i <= 100);//此处的;不能省略
System.out.println("Sum= " + sum);
}
}
for循环
语法
for (初始表达式; 布尔表达式; 迭代因子) {
循环体;
}
for循环在第一次反复之前要进行初始化,即执行初始表达式;随后,对布尔表达式进行判定,若判定结果为true,则执行循环体,否则,终止循环;最后在每一次反复的时候,进行某种形式的“步进”,即执行迭代因子。
A. 初始化部分设置循环变量的初值
B. 条件判断部分为任意布尔表达式
C. 迭代因子控制循环变量的增减
for循环在执行条件判定后,先执行的循环体部分,再执行步进。
public class Test10 {
public static void main(String args[]) {
int sum = 0;
//1.求1-100之间的累加和
for (int i = 0; i <= 100; i++) {
sum += i;
}
System.out.println("Sum= " + sum);
//2.循环输出9-1之间的数
for(int i=9;i>0;i--){
System.out.print(i+"、");
}
System.out.println();
//3.输出90-1之间能被3整除的数
for(int i=90;i>0;i-=3){
System.out.print(i+"、");
}
System.out.println();
}
}
嵌套循环
在一个循环语句内部再嵌套一个或多个循环,称为嵌套循环。while、do-while与for循环可以任意嵌套多层。
public class Test14 {
public static void main(String args[]) {
for (int i=1; i <=5; i++) {
for(int j=1; j<=5; j++){
System.out.print(i+" ");
}
System.out.println();
}
}
}
使用嵌套循环实现九九乘法表
for (int i=1;i<=9;i++){
for(j=1;j<=i;j++){
System.out.print(j+"*"+i+"="+i*j)
}
}
public class Test15 {
public static void main(String args[]) {
for (int i = 1; i < 10; i++) { // i是一个乘数
for (int j = 1; j <= i; j++) { // j是另一个乘数
System.out.print(j + "*" + i + "=" + (i * j < 10 ? (" " + i * j) : i * j) + " ");
}
System.out.println();
}
}
}
break语句和continue语句
在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。
break语句
public class Test16 {
public static void main(String[] args) {
int total = 0;//定义计数器
System.out.println("Begin");
while (true) {
total++;//每循环一次计数器加1
int i = (int) Math.round(100 * Math.random());
//当i等于88时,退出循环
if (i == 88) {
break;
}
}
//输出循环的次数
System.out.println("Game over, used " + total + " times.");
}
}
- round(double a) 返回最接近参数的 long。
continue
-
continue用在while,do-while中,continue 语句立刻跳到循环首部,越过了当前循环的其余部分。
-
continue用在for循环中,跳到for循环的迭代因子部分。
把100~150之间不能被3整除的数输出,并且每行输出5个
public class Test17 {
public static void main(String[] args) {
int count = 0;//定义计数器
for (int i = 100; i < 150; i++) {
//如果是3的倍数,则跳过本次循环,继续进行下一次循环
if (i % 3 == 0){
continue;
}
//否则(不是3的倍数),输出该数
System.out.print(i + "、");
count++;//没输出一个数,计数器加1
//根据计数器判断每行是否已经输出了5个数
if (count % 5 == 0) {
System.out.println();
}
}
}
}
带标签的break和continue
“标签”是指后面跟一个冒号的标识符,例如:“label:”。对Java来说唯一用到标签的地方是在循环语句之前。而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方。
带标签break和continue:控制嵌套循环跳转(打印101-150之间所有的质数)
public class Test18 {
public static void main(String args[]) {
outer: for (int i = 101; i < 150; i++) {
for (int j = 2; j < i / 2; j++) {
if (i % j == 0){
continue outer;
}
}
System.out.print(i + " ");
}
}
}
语句块
语句块(有时叫做复合语句),是用花括号扩起的任意数量的简单Java语句。块确定了局部变量的作用域。块中的程序代码,作为一个整体,是要被一起执行的。**块可以被嵌套在另一个块中,但是不能在两个嵌套的块内声明同名的变量。**语句块可以使用外部的变量,而外部不能使用语句块中定义的变量,因为语句块中定义的变量作用域只限于语句块。
public class Test19 {
public static void main(String[] args) {
int n;
int a;
{
int k;
int n; //编译错误:不能重复定义变量n
} //变量k的作用域到此为止
}
}
方法
方法就是一段用来完成特定功能的代码片段,类似于其它语言的函数。
整个程序的基本单位是类,方法是从属于类和对象的。
方法声明
[修饰符1 修饰符2 …] 返回值类型 方法名(形式参数列表){
Java语句;… … …
}
方法的调用方式:
对象名.方法名(实参列表)
方法的详细说明
-
形式参数:在方法声明时用于接收外界传入的数据。
-
实参:调用方法时实际传给方法的数据。
-
返回值:方法在执行完毕后返还给调用它的环境的数据。
-
-
返回值类型:事先约定的返回值的数据类型,如无返回值,必须显示指定为为void。
方法的声明及调用
public class Test20 {
/** main方法:程序的入口 */
public static void main(String[] args) {
int num1 = 10;
int num2 = 20;
//调用求和的方法:将num1与num2的值传给add方法中的n1与n2
// 求完和后将结果返回,用sum接收结果
int sum = add(num1, num2);
System.out.println("sum = " + sum);//输出:sum = 30
//调用打印的方法:该方法没有返回值
print();
}
/** 求和的方法 */
public static int add(int n1, int n2) {
int sum = n1 + n2;
return sum;//使用return返回计算的结果
}
/** 打印的方法 */
public static void print() {
System.out.println("北京尚学堂...");
}
}
方法的重载
方法的重载是指一个类中可以定义多个方法名相同,但参数不同的方法。 调用时,会根据不同的参数自动匹配对应的方法。
雷区
重载的方法,实际是完全不同的方法,只是名称相同而已!
构成方法重载的条件:
1.不同的含义:形参类型、形参个数、形参顺序不同
2.只有返回值不同不构成方法的重载
方法重载
public class Test21 {
public static void main(String[] args) {
System.out.println(add(3, 5));// 8
System.out.println(add(3, 5, 10));// 18
System.out.println(add(3.0, 5));// 8.0
System.out.println(add(3, 5.0));// 8.0
// 我们已经见过的方法的重载
System.out.println();// 0个参数
System.out.println(1);// 参数是1个int
System.out.println(3.0);// 参数是1个double
}
/** 求和的方法 */
public static int add(int n1, int n2) {
int sum = n1 + n2;
return sum;
}
// 方法名相同,参数个数不同,构成重载
public static int add(int n1, int n2, int n3) {
int sum = n1 + n2 + n3;
return sum;
}
// 方法名相同,参数类型不同,构成重载
public static double add(double n1, int n2) {
double sum = n1 + n2;
return sum;
}
// 方法名相同,参数顺序不同,构成重载
public static double add(int n1, double n2) {
double sum = n1 + n2;
return sum;
}
//编译错误:只有返回值不同,不构成方法的重载
public static double add(int n1, int n2) {
double sum = n1 + n2;
return sum;
}
//编译错误:只有参数名称不同,不构成方法的重载
public static int add(int n2, int n1) {
double sum = n1 + n2;
return sum;
}
}
递归
递归是一种常见的解决问题的方法,即把问题逐渐简单化。递归的基本思想就是“自己调用自己”,一个使用递归技术的方法将会直接或者间接的调用自己。
递归结构包括两个部分:
1.定义递归头。解答:什么时候不调用自身方法。如果没有头,将陷入死循环,也就是递归的结束条件。
2.递归体。解答:什么时候需要调用自身方法。
递归:计算n!
public class Test22 {
public static void main(String[] args) {
long d1 = System.currentTimeMillis();
System.out.printf("%d阶乘的结果:%s%n", 10, factorial(10));
long d2 = System.currentTimeMillis();
System.out.printf("递归费时:%s%n", d2-d1); //耗时:32ms
}
/** 求阶乘的方法*/
static long factorial(int n){
if(n==1){//递归头
return 1;
}else{//递归体
return n*factorial(n-1);//n! = n * (n-1)!
}
}
}
使用循环求n!
public class Test23 {
public static void main(String[] args) {
long d3 = System.currentTimeMillis();
int a = 10;
int result = 1;
while (a > 1) {
result *= a * (a - 1);
a -= 2;
}
long d4 = System.currentTimeMillis();
System.out.println(result);
System.out.printf("普通循环费时:%s%n", d4 - d3);
}
}