第一节 Java基本概念介绍
计算机语言发展历史
任何一个产品的发展规律都是:向着人更加容易使用、功能越来越强大的方向发展。
第一代语言:机器语言
第二代语言:汇编语言
第三代语言:高级语言
Java的发展历史
- Java能做什么?
- 发展前景如何?
- 需要学习哪些内容?
- 学完可以做哪些工作?
- 怎样才能学会?
Java是一门面向对象的语言,从1995年发布至今已有将近30年的历史,但是发展前景依然看好,在历年的世界编程语言排行榜Java常年位居首位,在国内外的综合就业排名当中也是常年第一。
Java为什么这么火?
因为Java应用非常广泛,全球已经有超过30亿的设备正在运行Java,Java在软件界的霸主地位无需多谈。
因为他的安全性和稳定性大部分电商、保险、金融类的网站都由Java开发。国内知名的淘宝、京东也都是采用Java开发的。其次的大数据领域,Java也是首选的开发语言。在大家使用的Android手机和嵌入式设备当中也绝大多采用Java开发。
Java进阶规划
零基础入门
Web基础
数据库
主流框架、分布式与微服务
学习建议
要多练习,学练结合,多写代码。
Java初识
- Java简介
- 开发第一个Java程序
- 使用IntelliJ Idea进行Java开发
Java简介
- Java是一门面向对象的程序设计语言
- 1995年由sun公司发布
- 2010年sun公司被Oracle公司收购
- JDK版本是18
Java可以分为三个体系
- Java SE(Java Platform Standard Edition,Java 平台标准版)以前称为 J2SE,主要开发桌面程序,比如QQ,Office等都属于桌面程序,可以开发这一类程序。JavaSE为后面的JavaEE提供基础
- Java EE(Java Platform Enterprise Edition,Java 平台企业版)以前称为 J2EE。网页Web程序是由JavaEE来实现的,JavaEE除了JavaSE中的内容外还包括jsp、servlet等等web开发需要的技术,主要应用于电商网站、门户网站这样网站产品的开发。
- Java ME(Java Platform Micro Edition,Java 平台微型版)以前称为 J2ME。主要用于移动设备的开发,Android和ios火起来之前还是占有很大市场份额的。现在用的非常少了。
相当于我们买车分低配版、标准版、高配版
Java特点
Java的核心优势
跨平台
JDK
- JDK(Java Development Kit),Java语言的软件开发工具包。
- 两个主要组件:
- javac -编译器,将源程序转成字节码
- java -运行编译后的java程序(.class后缀的)
在我们的开发阶段Java程序的编译和执行都靠它来完成,这里提供了很多相关命令,我们在编译和运行Java程序的时候都需要这里的命令,这些命令作为JDK中的组件
JRE
- JRE(Java Runtime Environment)
- 包括Java虚拟机(JVM)、Java核心类库和支持文件
- 如果只需要运行Java程序,下载并安装JRE即可
- 如果要开发Java软件,需要下载JDK
- JDK中附带有JRE
JDK、JRE和JVM三者的关系
JRE = JVM + JavaSE标准类库
JDK = JRE + 开发工具集(例如Javac编译工具等)
一个java程序需要跑起来的话需要有Java运行环境JRE,但是如果要开发Java程序就必须要有JDK,JDK里提供了很多开发工具和API,帮助我们写程序和调试程序。
JVM
- JVM(Java Virtal Machie),Java虚拟机
- JVM是实现Java跨平台的关键
一般其他高级语言要在不同的平台上运行,需要编译成不同的目标代码。不同的平台比如:Windows/Linux IOS Android.这些系统本身是有差别的
而引入Java虚拟机JVM以后,Java在不同的平台上运行是不需要重新编译的,系统的差异。
Java代码经过Java虚拟机解释成针对不同操作系统的代码。系统差异的问题由不同的虚拟机来解决,我们开发写代码不需要关注系统差异。
**JVM是一种规范。**就是一个虚拟的用于执行bytecodes字节码的计算机。
Java程序执行过程
xxx.java的源文件通过编译器编译,生成xxx.class的字节码文件,字节码文件会交由解释器执行,这时候我们就可以看到我们的程序了。这个解释执行的过程是由Java虚拟机来完成的。
Java虚拟机解释执行编译过程中生成的字节码文件,把字节码文件解释成具体平台上的机器指令执行。因为计算机只能识别0101这样的二进制指令。所以把字节码解释成具体平台上的机器指令就可以实现一次编译,到处运行了。
第二节 Windows下开发环境搭建
- 下载JDK
https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html - 安装
跟普通软件安装一样,点击下一步就OK! - 环境变量配置
没配置环境变量前执行javac找不到命令,因为系统找不到bin目录下的javac.exe,现在没有找到。需要把bin目录配置到环境变量里javac和java命令才能正确执行
配置环境变量
- 搜索 环境变量,或者 旧版本操作系统 控制面板->系统和安全->系统
- 系统属性 -> 高级 -> 环境变量
- 配置JAVA_HOME
环境变量中包括用户变量和系统变量,系统变量是全局生肖的,而用户变量是只针对当前用户生效的,一个操作系统可能有多个账户进行访问。
- 编辑Path
注意:之前的内容一定不能去掉
把命令行窗口关掉再打开,输入命令javac
测试安装环境是否安装成功
运行cmd输入命令: java -version
输入javac出现如下结果则通过测试
第一个JAVA程序的编写和运行
- 使用记事本编辑
public class Welcome{
public static void main(String[] args) {
System.out.println("Hello 小学喊你吃饭啦!");
}
}
2. 保存为 F:\java\Welcome.java
3. 命令行进入F:\java\ 目录
4. 执行javac命令
Java程序的结构
定义类 里面包含一个主方法 class-定义类的关键字
主方法是程序的入口,程序的代码是从主方法开始运行
注意:语句结尾一定要写分号
IntelliJ IDEA
开发工具推荐用 Jetbrain的IntelliJ IDEA,是 java 编程语言开发的集成环境,被公认为最好的 java 开 发工具之一。
IDEA 目前市场占有率越来越高,流行度也越来越高。但是,对于电脑的配置要求相对 eclipse 要高一些。大家根据自身情况自由选择。IDE(开发环境)之间的切换很容易,不 用过度纠结使用哪一个。“初学者用哪一个都可以!
创建项目
src文件夹中存放java文件,下面可以自己创建包 创建java类,在不同包下可以创建同名的类。
注释
//单行注释
/**多行注释*/
第三节 数据类型、变量和常量的使用
常量与变量课件
主要内容
- 标识符
- 关键字
- 变量
- 数据类型
- 类型转换
- 常量
标识符
用于给变量、类和方法命名。
注意:表示类名的标识符用大写字母开始。如:Man, GoodMan
表示方法和变量的标识符用小写字母开始,后面的描述性词以大写开始。
JAVA中的关键字/保留字
JAVA关键字是Java语言保留供内部使用的,如class用于定义类。关键字也可以称为保留字。不能使用关键字作为变量名或方法名。
两个保留字现在没用,以后可能会使用
变量(variable)
变量的本质
- 变量本质上就是代表一个”可操作的存储空间”,空间位置是确定的,但是里面放 置什么值不确定。
- 可通过变量名来访问“对应的存储空间”,从而操纵这个“存储空间”存储的值。
- Java 是一种强类型语言,每个变量都必须声明其数据类型。变量的数据类型决定了 变量占据存储空间的大小。 比如,int a=3; 表示 a 变量的空间大小为 4 个字节。
在开发过程中我们经常需要对一些数据进行处理。比如做一些数学运算,对一些复杂的运算我们希望把中间的运行结果存储下来,这样可以更好的参与下一次运算。
这样一个数学问题如果想使用计算机来处理就涉及到数据存储,而变量就是数据的临时存放场所,可以为我们解决数据存储的问题,变量是存储到内存当中的。
变量的三个元素:变量类型、变量名和变量值
double salary;
long earthPopulation;
int age;
不同数据类型的常量会在内存中分配不同的空间,
变量名的命名规则
- 满足标识符的命名规则
- 符合驼峰法命名 规范
- 尽量简单,做到见名知意
- 变量名的长度没有限制
类的命名规则
- 满足Pascal命名法规范
组成类名的每一个单词首字母要大写
有了这些命名规则以后,当我们看到一个标识符的时候就能区分这个标识符是类的名字、方法的名字还是常量的名字,这样有利于代码的阅读。
变量的分类和作用域
变量有三种类型:局部变量、成员变量(也称为实例变量)和静态变量。
-
局部变量(local variable)
方法或语句块内部定义的变量。生命周期是从声明位置开始到到方法或语句块执行完毕 为止。局部变量在使用前必须先声明、初始化(赋初值)再使用。 -
成员变量(也叫实例变量 member variable)【暂不用掌握,讲面向对象再说】
方法外部、类的内部定义的变量。从属于对象,生命周期伴随对象始终。如果不自行初 始化,它会自动初始化成该类型的默认初始值。 -
静态变量(类变量 static variable)【暂不用掌握,讲面向对象再说】
使用 static 定义。 从属于类,生命周期伴随类始终,从类加载到卸载。 (注:讲完内存 分析后我们再深入!先放一放这个概念!) 如果不自行初始化,与成员变量相同会自动初始化成该类型的默认初始值,如表 2-3 所示。
局部变量、成员变量、静态变量的核心区别
public class TestVariable1 {
int a; //成员变量,从属于对象;成员变量会自动被初始化
static int size; //静态变量,从属于类
public static void main(String[] args) {
{
int age; //局部变量,从属于语句块
age = 18;
}
double salary = 7000;
int xue = 0;
System.out.println(xue);
}
}
常量
在 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 等称为符号常量。
变量和常量命名规范
- 所有变量、方法、类名:见名知义
- 类成员变量:首字母小写和驼峰原则: monthSalary
- 局部变量:首字母小写和驼峰原则
- 常量:大写字母和下划线:MAX_VALUE
- 类名:首字母大写和驼峰原则: Man, GoodMan
数据类型
在Java中,数据类型分为两大类:
- 基本数据类型:4类8种基本数据类型
- 引用数据类型
基本数据类型
整数类型
byte、short、int、long
Java中整型的三种表示形式
- 十进制整数:0 ~ 9,注:第一位不能是0
- 十六进制数:0 ~ 9 A ~ F, 注:必须以0x或0X开头
例如: 0X8A 0x12AF - 八进制整数:0 ~ 7,注:必须以0开头
例如: 0123 012
Java各整数类型有固定的表数范围和字段长度,其不受操作系统的影响,以保证Java程序的可移植性。
Java语言的整形常量默认为int型,声明long型后面需加上l或者L,否则会出错
变量声明
- 格式:数据类型 变量名;
例如:int n; //声明整型变量n
long count; //声明长整型变量count
赋值
使用"="运算符进行赋值
- "="叫作赋值运算符,将运算符右边的值赋给左边的变量。
例如:int n; //定义int型变量
n = 3; //将3赋值给n - 可以在定义变量的同时给变量赋值,即变量的初始化
例如:int n=3;
变量定义
int local = 037; //定义int类型变量存放进八进制数据
long longNumber = 0xa2cdf3ffL; //定义变量存放进十六进制长整型数据
short shortNumber = 123; //定义变量存放短整型数据
byte b=10; //定义变量存放byte类型数据
浮点型
与整数类型相似,Java浮点数类型有固定的表数范围和字段长度,不受平台影响
- 浮点型字面值默认情况下为double类型,也可以在值后加d或D。
例如:123.43d 或 123.43D
表示float类型,则需要在字面值后面加f或F
例如:23.4f或23.4F
由于字长有限,浮点数能够精确表示的数是有限的,因而也是离散的。 浮点数一 般都存在舍入误差,很多数字无法精确表示(例如0.1),其结果只能是接近, 但不等于。二 进制浮点数不能精确的表示0.1、0.01、0.001这样10的负次幂。并不是所有的小数都能可 以精确的用二进制浮点数表示。
java.math 包下面的两个有用的类:BigInteger 和 BigDecimal,这两个类可以处理任 意长度的数值。BigInteger 实现了任意精度的整数运算。BigDecimal 实现了任意精度的浮点运算。
对于小数的约束可能模式有4种:向上/向下取整、四舍五入、银行家模式
银行家算法 是IEEE里规定的小数取整的基本方案
四舍六入五考虑,五后非空就进一,五后为空看奇偶,五前为偶应舍去,五前为奇要进一。
js中的toFix()在有些浏览器实现的是银行家算法,有些浏览器实现的是四舍五入。
BigDecimal.ROUND_UP //始终进一
BigDecimal.ROUND_DOWN //始终舍去
RoundingMode.HALF_UP => BigDecimal.ROUND_HALF_UP //四舍五入
RoundingMode.HALF_DOWN => BigDecimal.ROUND_HALF_DOWN //五舍六入
RoundingMode.HALF_EVEN => BigDecimal.ROUND_HALF_EVEN //银行家算法
银行家算法要解决什么问题 Java全站课 18周 6-9
练习:
BigDecimal计算
基本数据类型变量的存储
字符型
字符型在内存中占 2 个字节,在 Java 中使用单引号来表示字符常量。例如’A’是一 个字符,它与”A”是不同的,”A”表示含有一个字符的字符串。
char 类型用来表示在 Unicode 编码表中的字符。Unicode 编码被设计用来处理各种 语言的文字,它占 2 个字节,可允许有 65536 个字符。
Unicode编码表可以表示世界所有的语言相关字符,包含汉字。是目前主流的字符集。
public class TestBasicDataType3 {
public static void main(String[] args) {
char a = 'Z';
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');
//String就是字符序列,本质是char字符组成的数组
String d = "abc";
}
}
转义字符
布尔型(boolean)
- boolean 类型有两个常量值,true 和 false。
- 在内存中占一个字节或 4 个字节,不可以使用 0 或非 0 的整数替代 true 和 false , 这点和 C 语言不同。
【注意点】 JVM 规范指出 boolean 当做 int 处理,也就是 4 字节,boolean 数组当做 byte 数组处理,这样我 们可以得出 boolean 类型占了单独使用是 4 个字节,在数组中是确定的 1 个字节。
演示:
boolean flag;
flag = true;
if(flag){
// true 分支
System.out.println("开启");
}else{
// false 分支
System.out.println("关闭");
}
第四节 Java中多种运算符的应用
运算符(operator)
算术运算符
- +,-,*,/,%属于二元运算符。%是取模运算符,就是我们常说的求余数操作。
- 算术运算符中++(自增),–(自减)属于一元运算符。
二元运算符的运算规则:
整数运算
- 如果两个操作数有一个为 long, 则结果也为 long。
- 没有 long 时,结果为 int。即使操作数全为 short,byte,结果也是 int。
浮点运算
- 如果两个操作数有一个为 double,则结果为 double。
- 只有两个操作数都是 float,则结果才为 float。
取模运算
- 其操作数可以为浮点数,一般使用整数,结果是“余数”,“余数”符号和左 边操作数相同,如:7%3=1,-7%3=-1,7%-3=1。
//测试自增和自减
int a1 = 3;
int a2 = 3;
int b1 = a1++; //执行完成,b1=3。先给b1赋值,再自增。
System.out.println("a1="+a1+"\nb1="+b1);
b2 = ++a2;
System.out.println("a2="+a2+"\nb2="+b2); //执行完成,b1=4。a1先自增,再b2赋值。
赋值及其扩展赋值运算符
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);
关系运算符
关系运算符用来进行比较运算。关系运算的结果是布尔值:true/false;
注意事项
=是赋值运算符,而真正的判断两个操作数是否相等的运算符是==。
==、!= 是所有(基本和引用)数据类型都可以使用。
> 、>=、 <、 <= 仅针对数值类型(byte/short/int/long,float/double 以及 char)
逻辑运算符
逻辑运算的操作数和运算结果都是 boolean 值。
短路与和短路或采用短路的方式。从左到右计算,如果只通过运算符左边的操作数就能 够确定该逻辑表达式的值,则不会继续计算运算符右边的操作数,提高效率。
public class TestOperator03 {
public static void main(String[] args) {
boolean b1 = true;
boolean b2 = false;
System.out.println(b1&b2);
System.out.println(b1|b2);
System.out.println(b1^b2);
System.out.println(!b1);
/**短路*/
//1>2 的结果为 false,那么整个表达式的结果即为 false,将不再计算 2>(3/0)
boolean c = 2>4 && 2>(3/0);
System.out.println(c);
//2>4 的结果为 false,那么整个表达式的结果即为 false,还要计算 2>(3/0),0 不能做除 数,//会输出异常信息
boolean d = 2>4 & 2>(3/0);
System.out.println(d);
}
}
位运算符
位运算指的是进行二进制位的运算。
3 --> 0 0 1 1
4 --> 0 1 0 0
----------------------------------
& 0 0 0 0 0
| 0 1 1 1 7
^ 0 1 1 1 7
3 * 4 怎样做最快?
public class TestOperator04 {
public static void main(String[] args) {
int a = 3;
int b = 4;
System.out.println(a&b);
System.out.println(a|b);
System.out.println(a^b);
System.out.println(~a);
//移位
int c = 3 << 2;
System.out.println(c);
System.out.println(12 >> 1);
}
}
注意:
&和|既是逻辑运算符,也是位运算符。如果两侧操作数都是 boolean 类型,就作为逻 辑运算符。如果两侧的操作数是整数类型,就是位运算符。
字符串连接符
“+”运算符两侧的操作数中只要有一个是字符串(String)类型,系统会自动将另一个操作 数转换为字符串然后再进行连接。
public class TestOperator05 {
public static void main(String[] args) {
String a = "3";
int b = 4;
int c = 5;
char d = 'a';
System.out.println(a+b+c);
System.out.println(b+c+a);
System.out.println(d+4);
}
}
条件运算符
String type = score<60?"不及格":"及格";
x 为 boolean 类型表达式,先计算 x 的值,若为 true,则整个运算的结果为表达式 y 的 值,否则整个运算结果为表达式 z 的值。
public class TestOperator06 {
public static void main(String[] args) {
int score = 80;
int x = -100;
String type = score < 60 ? "不及格":"及格";
System.out.println(type);
if(score < 60){
System.out.println("不及格");
}else{
System.out.println("及格");
}
System.out.println(x > 0 ? 1 :(x == 0?0:-1));
}
}
运算符优先级的问题
建议
- 大家不需要去刻意的记这些优先级,表达式里面优先使用小括号来组织!!
- 逻辑与、逻辑或、逻辑非的优先级一定要熟悉!(逻辑非>逻辑与>逻辑或)。如: a||b&&c 的运算结果是:a||(b&&c),而不是(a||b)&&c
第五节 数据类型的转换
自动类型转换
自动类型转换指的是容量小的数据类型可以自动转换为容量大的数据类型。如图所 示,黑色的实线表示无数据丢失的自动类型转换,而虚线表示在转换时可能会有精度的损失。
(容量小和容量大指的是表数范围)
可以将整型常量直接赋值给 byte、 short、 char 等类型变量,而不需要进行强制类 型转换,只要不超出其表数范围即可。
/**测试自动类型转化*/
public class TestTypeConvert {
public static void main(String[] args) {
int a = 324;
long b = a;
double d = b;
// a = b;
// long e = 3.23F;
float f = 234324L;
//特例
byte b2 = 123;
}
强制类型转换
强制类型转换,用于强制转换数值的类型,可能损失精度。
double x = 3.94;
int nx = (int)x; //值为 3
char c = 'a';
int d = c+1;
System.out.println(nx);
System.out.println(d);
System.out.println((char)d);
当将一种类型强制转换成另一种类型,而又超出了目标类型的表数范围,就会被截断成 为一个完全不同的值。
基本数据类型转化时常见错误和问题
1. 操作比较大的数时,要留意是否溢出,尤其是整数操作时。
2. L 和 l 的问题: (1) 不要命名名字为 l 的变量,字母 l 容易和数字 1 混淆。 (2) long 类型使用大写 L,不要用小写 l。
/**测试基本类型转换常见错误*/
public class TestTypeConvertError {
public static void main(String[] args) {
int money = 1000000000; //10亿
int years = 20;
//返回的total是负数,超过了int的范围
int total = money*years;
System.out.println("total="+total);
//返回的total仍然是负数。默认是int,因此结果会转成int值,再转成long。但是已经发 生了数据丢失
long total1 = money*years;
System.out.println("total1="+total1);
//返回的total2正确:先将一个因子变成long,整个表达式发生提升。全部用long来计算。
long total2 = money*((long)years);
System.out.println("total2="+total2);
long total3 = 34L*3223*years*223423;
System.out.println(total3);
//命名问题
int l = 2; //分不清是L还是1
long a = 23451l; //建议使用大写L
System.out.println(l+1);
}
}
第六节 控制语句
控制语句介绍
流程控制语句是用来控制程序中各语句执行顺序的语句。
控制语句:把语句组合成能完成一定功能的小逻辑模块。它分为三类:顺序、选择和循环。 学会控制语句,是真正跨入编程界的“门槛”,是成为“程序猿”的“门票”。
- “顺序结构”代表“先执行 a,再执行 b”的逻辑。
- **“条件判断结构”代表“如果…,则…”的逻辑。**比如,如果看到红灯,则停车;如果x > 80,则输出“优秀”
- **“循环结构”代表“如果…,则重复执行…”的逻辑。**比如,如果高考分数低于300分则再继续复读,直到高于300分上大学。
实际上,任何软件和程序,小到一个练习,大到一个操作系统,本质上都是由**“变 量、选择语句、循环语句”**组成。
选择结构(条件判断结构)
if结构
if 单分支结构
语法结构
if(布尔表达式){
语句块
}
/**测试If单分支结构*/
public class TestIf {
public static void main(String[] args) {
double d = Math.random(); //返回[0,1)之间的随机数
System.out.println(d);
int i = (int)(6*Math.random()+1);
System.out.println(i);
if (i<=3){
System.out.println("小");
}
//通过掷三个骰子看看今天的手气如何?
// 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 + "分");
}
}
tips
- 如果 if 语句不写{},则只能作用于后面的第一条语句。
- 强烈建议,任何时候都写上{},即使里面只有一句话!
if else双选择结构
语法结构
if(布尔表达式){
语句块 1
}else{
语句块 2
}
当布尔表达式为真时,执行语句块 1,否则,执行语句块 2。也就是 else 部分。
public class TestIfElse {
public static void main(String[] args) {
double d = Math.random(); //返回[0,1)之间的随机数
System.out.println(d);
int i = (int)(6*Math.random()+1);
System.out.println(i);
if (i<=3){
System.out.println("小");
}else{
System.out.println("大");
}
}
}
if-else 结构也可以转换为条件运算符
String result = i<=3 ? "小" : "大";
System.out.println(result);
if-else if-else多分支结构
语法结构
if(布尔表达式 1){
语句块 1;
}else if(布尔表达式 2){
语句块 2;
}……
else if(布尔表达式 n){
语句块 n;
}else{
语句块 n+1;
}
public class TestIfElseIfElse {
public static void main(String[] args) {
int age = (int) (100 * Math.random());
System.out.print("年龄是" + age + ", 属于");
//15 岁以下儿童;15-24 青年;25-44 中年;45-64 中老年;65-84 老年;85 以上老 寿星
if (age < 15) {
System.out.println("儿童, 喜欢玩!");
} else if (age < 25) {
System.out.println("青年, 要学习!");
} else if (age < 45) {
System.out.println("中年, 要工作!");
} else if (age < 65) {
System.out.println("中老年, 要补钙!");
} else if (age < 85) {
System.out.println("老年, 多运动!");
} else {
System.out.println("老寿星, 古来稀!");
}
}
}
switch结构
switch多分支结构(多值情况)
语法结构
switch (表达式) {
case 值 1:
语句块 1;
[break];
case 值 2:
语句块 2;
[break];
… … … … …
[default: 默认语句块;]
}
- switch 会根据表达式的值从相匹配的 case 标签处开始执行,一直执行到 break 处或者 是 switch 的末尾。如果表达式的值与任一 case 值不匹配,则进入 default 语句。
- switch 中表达式的值,是 int(byte、short、char 也可,long 不行)、枚举,字符串。
public class TestSwitch {
public static void main(String[] args) {
int month = (int)(1 + 12 * Math.random());
System.out.println("月份:"+month);
switch(month){
case 1:
System.out.println("一月份!过新年了!");
break;
case 2:
System.out.println("二月份!开春了");
break;
default:
System.out.println("我是其他月份");
}
}
}
switch 接收字符串(JDK7以上版本)
String str = "audi";
switch (str) {
case "audi":
System.out.println("我买了个奥迪车");
break;
case "benz":
System.out.println("我买了个奔驰车");
break;
default:
System.out.println("比亚迪,挺好!");
}
循环结构
循环结构分两大类,一类是当型,一类是直到型。
- 当型
当布尔表达式条件为 true 时,反复执行某语句,当布尔表达式的值为 false 时才停止循环,比如:while 与 for 循环。 - 直到型
先执行某语句, 再判断布尔表达式,如果为 true,再执行某语句,如此反复,直到布 尔表达式条件为 false 时才停止循环,比如 do-while 循环。
while循环
语法结构
while(布尔表达式){
循环体;
}
public class TestWhile {
public static void main(String[] args) {
//计算1+2+3+…+100=?
int i = 1;
int sum = 0;
while (i <= 100) {
sum = sum + i;
i++;
}
System.out.println(sum);
}
}
- 在循环刚开始时,会计算一次“布尔表达式”的值,若条件为真,执行循环体。而对于 后来每一次额外的循环,都会在开始前重新计算一次。
- 语句中应有使循环趋向于结束的语句,否则会出现无限循环–––"死"循环。
do-while 循环
语法结构:
do {
循环体;
} while(布尔表达式) ;
do-while 循环结构会先执行循环体,然后再判断布尔表达式的值,若条件为真,执行 循环体,当条件为假时结束循环。do-while 循环的循环体至少执行一次。
int i = 0;
int sum = 0;
do {
sum += i; // sum = sum + i
i++;
} while (i <= 100); //此处的;不能省略
System.out.println("Sum= " + sum);
for循环
语法结构
for (初始表达式; 布尔表达式; 迭代因子) {
循环体;
}
- 初始化部分设置:循环变量的初值
- 条件判断部分为:布尔表达式
- 迭代因子:控制循环变量的增减
for 循环在执行条件判定后,先执行的循环体部分,再执行步进
示例
for循环
public class TestFor {
public static void main(String[] args) {
int sum = 0;
for(int i=1;i<=100;i++){
sum = sum + i;
}
/**
* 1.执行初始化语句:i=1;
* 2.判断i<=100
* 3.执行循环体
* 4.步进迭代:i++
* 5.回到第二步继续判断
*/
System.out.println(sum);
}
}
逗号运算符
for(int i = 1, j = i + 10; i < 5; i++, j = i * 2) {
System.out.println("i= " + i + " j= " + j);
}
无限循环
for ( ; ; ) { // 无限循环: 相当于 while(true)
System.out.println("小雪喊你吃饭啦!");
}
嵌套循环
循环语句内部,再写一个或多个循环,称为嵌套循环。
示例
嵌套循环
执行结果如图所示
public static void main(String[] args) {
for(int i=1;i<=5;i++){
for(int j=1;j<=5;j++){
System.out.print(i+"\t");
}
System.out.println();
}
}
break语句和continue语句
- break 用于强行退出整个循环
- continue 用于结束本次循环,继续下一次
示例
break语句
public class TestBreak {
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());
System.out.println(i);
//当 i 等于 88 时,退出循环
if (i == 88) {
break;
}
}
//输出循环的次数
System.out.println("Game over, used " + total + " times.");
}
}
continue语句
//把 100~150 之间不能被 3 整除的数输出,并且每行输出 5 个
package com.zl.one.unit6;
public class TestContinue {
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();
}
}
}
}
带标签的continue语句
“标签”是指后面跟一个冒号的标识符,例如:“label:”。对 Java 来说唯一用到标 签的地方是在循环语句之前。
“goto 有害”论中,最有问题的就是标签,而非 goto,随着标签在一个程序里数量的增多,产生错误的机会也越来越多。但 Java 标签不会造成这方面的问题,因为它们的活动场所已被限死,不可通过特别的方式到处传递程序的控制权。
//控制嵌套循环跳转(打印 101-150 之间所有的质数)
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 + " ");
}
方法
语句块
语句块(也叫复合语句)。语句块中定义的变量只能用于自己,外部不能使用。 语句块可以使用外部的变量,而外部不能使用语句块的变量
示例
public static void main(String[ ] args) {
int n;
int a;
{
int k;
int n; //编译错误:不能重复定义变量 n
} //变量 k 的作用域到此为止
}
方法
- 方法(method):一段用来完成特定功能的代码片段,类似于其它语言的函数(function)。
- 方法用于定义该类或该类的实例的行为特征和功能实现。
- 面向过程中,函数是最基本单位,整个程序由一个个函数调用组成。
- 面向对象中,整个程序的基本单位是类,方法是从属于类和对象的。
方法声明格式
[修饰符 1 修饰符 2 …] 返回值类型 方法名(形式参数列表){
Java 语句;… … …
}
方法的调用方式
方法的详细说明
- 形式参数: 在方法声明时用于接收外界传入的数据。(方法定义时)
- 实参: 调用方法时实际传给方法的数据。 (方法调用时)
- 返回值: 执行完毕后,返还给调用它的环境的数据。
- 返回值类型: 事先约定的返回值的数据类型,如无返回值,则为 void。
示例
public class TestMethod {
public static void main(String[] args) {
TestMethod testMethod = new TestMethod();
int sum2 = testMethod.add(5,6,7);
System.out.println("sum="+sum2);
testMethod.print();
}
public void print(){
System.out.println("11111111111");
System.out.println("22222222222");
System.out.println("33333333333");
}
public int add(int x,int y,int z){
int sum = x+y+z;
return sum;
}
}
注意事项
- 实参必须和形参列表匹配。
- return:终止方法运行,并返回的数据。
- Java 中传递参数,遵循值传递的原则(传递的都是数据的副本):
- 基本类型传递的是该数据值的 copy 值。
- 引用类型传递的是该对象引用的 copy 值,但指向的是同一个对象。
方法的重载(overload)
重载:一个类中可以定义多个名称相同,但形式参数列表不同的方法。
构成方法重载的条件:
- 形参列表不同的含义:形参类型、形参个数、形参顺序不同
- 只有返回值不同不构成方法的重载 如:int a(String str){}与 void a(String str){}不构成方法重载
- 只有形参的名称不同,不构成方法的重载 如:int a(String str){}与 int a(String s){}不构成方法重载
递归结构
- 递归是一种常见的算法思路,在很多算法中都会用到。比如:深度优先搜索 (DFS:Depth First Search)等。
- 递归的基本思想就是“自己调用自己”
public static void main(String[] args) {
a();
}
static int count=0;
public static void a(){
System.out.println("a");
count++;
if(count < 10){
a();
}else{
return;
}
}
public static void b(){
System.out.println("b");
}
递归结构包括两个部分:
- 定义递归头。
解决:什么时候不调用自身方法。如果没有头,将陷入死循环,也就 是递归的结束条件。 - 递归体。
解决:什么时候需要调用自身方法
递归的缺陷
算法简单是递归的优点之一。但是递归调用会占用大量的系统堆栈,内存耗用多,在递归 调用层次多时速度要比循环慢的多,所以在使用递归时要慎重。
【示例】使用递归求 n!
public static void main(String[] args) {
long d1 = System.currentTimeMillis();
long result = factorial(10);
long d2 = System.currentTimeMillis();
System.out.println("result="+result);
System.out.printf("递归费时:"+(d2-d1)); //耗时:32ms
}
/** 求阶乘的方法*/
static long factorial(int n) {
if (n == 1) {//递归头
return 1;
} else {//递归体
System.out.println(n);
return n * factorial(n - 1);//n! = n * (n-1)!
}
}
【示例】使用循环求 n!
long d3 = System.currentTimeMillis();
int a = 10;
int result2 = 1;
while (a > 1) {
result2 *= a * (a - 1); a -= 2;
}
long d4 = System.currentTimeMillis();
System.out.println(result2);
System.out.printf("普通循环费时:"+(d4 - d3));