第1章 内容介绍
1.1 Java就业方向
第2章 Java概述
2.1 什么是程序
程序:计算机执行某些操作或解决某个问题而编写的一系列有序指令的集合
2.2 Java重要特点
-
Java语言是面向对象的(oop)
-
Java语言是健壮的。(强类型机制、异常处理、垃圾的自动收集)
-
Java语言是跨平台性的。[即: 一个编译好的.class 文件可以在多个系统下运行]->因为有JVM :解释执行工作
-
Java语言是解释型的 解释性语言:javascript,PHP, java 编译性语言: c/c++
区别是:解释性语言,编译后的代码,不能直接被机器执行,需要解释器来执行,
编译性语言编译后的代码,可以直接被机器执行
2.3 Java运行机制及运行过程
2.3.1 Java 语言的特点:跨平台性
2.3.2 Java核心机制-Java虛拟机 [JVM java virtual machine]
基本介绍
1)JVM是一个虚拟的计算机,具有指令集并使用不同的存储区域。负责执行指令,管理数据、内存、寄存器,包含在JDK中.
2)对于不同的平台,有不同的虚拟机。
3)Java虚拟机机制屏蔽了底层运行平台的差别,实现了“一次编译,到处运行”[说明]
2.4 什么是JDK,JRE
2.4.1 JDK基本介绍
1)JDK的全称(Java Development Kit Java开发工具包)
JDK = JRE + java的开发工具 [java,javac,javadoc,javap等]
2)JDK 是提供给 Java开发人员使用的,其中包含了java 的开发工具,也包括了 JRE。所以安装了 JDK,就不用在单独安装 JRE 了
2.4.2 JRE基本介绍
1)JRE(Java Runtime Environment Java 运行环境) JRE = JVM + Java 的核心类库[类]
2)包括 Java 虛拟机(JVM Java Virtual Machine)和 Java 程序所需的核心类库等,如果想要运行一个开发好的 Java 程序,计算机中只需要安装 JRE 即可。
2.4.3 JDK、JRE和JVM的包含关系
1)JDK = JRE+ 开发工具集(例如 Javac,java 编译工具等
2)JRE = JVM + Java SE 标准类库(java 核心类库)
3)如果只想运行开发好的 .class 文件 只需要 JRE
2.5 配置环境变量path
2.5.1 为什么要配置path
2.5.2 配置环境变量path的步骤
2.6 Java快速入门
2.6.1 需求说明
要求开发一个 Hello.java 程序,可以输出"hello.world! "
2.6.2 开发步骤
将 Java 代码编写到扩展名为 Hello.java 的文件中。[代码说明通过 javac 命令对该 java 文件进行编译,生成 .class 文件。通过 java 命令对生成的 class 文件进行运行。
2.6.3 运行原理示意图
2.7 Java开发快速入门
//对代码的相关说明
//1.public class Hello 表示Hello是一个类,是一个public公有的类
//2.Hello{}表示一个类的开始和结束
//3.publiv static void main(String[] args)表示一个主方法,即我们程序的入口
//4.main(){}表示方法的开始和结束
//5.System.out.println("hello,world~");表示输出"hello,world~"到屏幕
//6.;表示语句结束
public class Hello{
public static void main(String[] args){
System.out.println("hello,world");
}
}
//一个源文件中最多只能有一个public类。其他类的个数不限。
//Dog是一个类
//编译后,每一个类,都对应一个.class
class Dog{
//一个源文件中最多只能有一个 public 类。其它类的个数不限,也可以将 main 方法写在非 public 类中,
//然后指定运行非 public 类,这样入口方法就是非 public 的 main 方法
public static void main(String[] args){
System.out.println("hello,小狗狗!");
}
}
class Tiger{
public static void main(String[] args){
System.out.println("hello,小老虎");
}
}
注意事项:对修改的Hello.java源文件需要重新编译,生成新的class文件后在进行执行,才能生效
2.8 Java开发注意事项和细节说明
-
Java源文件以 .java 为扩展名。源文件的基本组成部分是类(class),如本类中的Hello类。
-
Java应用程序的执行入口是main()方法。它有固定的书写格式:public static void main(String[] args) {...}
-
Java语言严格区分大小写。
-
Java方法由一条条语句构成,每个语句以“;”结束。
-
大括号都是成对出现的,缺一不可。[习惯,先写 {}再写代码]
-
一个源文件中最多只能有一个public类。其它类的个数不限。[演示]
-
如果源文件包含一个public类,则文件名必须按该类名命名![演示]
-
一个源文件中最多只能有一个public类。其它类的个数不限,也可以将main方法写在非public类中,然后指定运行非public类,这样入口方法就是非public的main方法
-
如果源文件中没有公共类(public class),文件名可自行拟定。
2.9 Java转义字符
2.9.1 Java常用的转义字符
在控制台,输入 tab 键,可以实现命令补全
\t : 一个制表位,实现对齐的功能
\n : 换行符
\\ : 一个\
\" : 一个"
\' : 一个'
\r : 一个回车 System.out.println("韩顺平教育\ 北京");
2.9.2 说明
应用实例
public class ChangeChar{
//编写一个main方法
public static void main(String[] args){
// \t : 一个制表位,实现对齐的功能
System.out.println("北京\t天津\t上海");
// \n : 换行符
System.out.println("jack\nsmith\nmary");
// \\ : 一个\
System.out.println("C:\\Windows\\System32\\cmd.exe");
// \" : 一个"
System.out.println("老韩说:\"要好好学习java,有前途\"");
// \' : 一个'
System.out.println("老韩说:\'要好好学习java,有前途\'");
// \r : 一个回车
System.out.println("韩顺平教育\r北京");//北京平教育
//解读:在文本文件中,回车通常与换行(Line Feed)一起使用来表示文本中的新行。具体而言,回车符表示将光标移动到当前行的开头位置,而换行符表示将光标移动到下一行的开头位置。这种组合被称为“回车换行”(CRLF)。
System.out.println("韩顺平教育\r\n北京");//韩顺平教育
//北京
}
}
2.9.3 课堂练习
public class ChangeCharExer01 {
//编写一个 main 方法
public static void main(String[] args) {
//完成代码
System.out.println("书名\t 作者\t 价格\t 销量\n 三国\t 罗贯中\t120\t1000");
//下面代码完成 两个数相加
//定义变量
int n1 = 10;
int n2 = 30;
//求和
int sum = n1 + n2;
//输出结果
System.out.println("结果=" + sum);
}
}
2.10 初学java易犯错误
1.找不到文件
解决方法:源文件名不存在或者写错,或者当前路径错误
2.主类名和文件名不一致
解决方法:声明为public的主类应与文件名一致,否则编译失败
3.缺少分号
解决方法:编译失败,注意错误出现的行数,再到源代码中指定位置改错
4.常见错误总结
学习编程最容易犯的错是语法错误(初学者)。Java要求你必须按照语法规则编写代码。如果你的程序违反了语法规则,例如:忘记了分号、大括号、引号,或者拼错了单词java编译器都会报语法错误。尝试着去看懂编译器会报告的错误信息。
举例:
-
1->1
-
2.0->o
-
英文符号写中文符号
-
void ->viod 拼写错误
-
不好修改的错误其实是 业务错误,环境错误
2.11 注释
2.11.1 介绍:
用于注解说明解释程序的文字就是注释,注释提高了代码的阅读性(可读性);注释是一个程序员必须要具有的良好编程习惯。将自己的思想通过注释先整理出来,再用代码去体现。
2.11.2 Java中的注释类型
1)单行注释 //
2)多行注释 /* */
3)文档注释 /** */
2.11.3 单行注释:
基本格式
格式: //注释文字
2.11.4 多行注释:
基本格式
格式: /* 注释文字 */
2.11.5 使用细节
1)被注释的文字,不会被JVM(java 虚拟机)解释执行
2)多行注释里面不允许有多行注释嵌套
2.11.6 文档注释
快捷键:1.//选中,然后输入 tab 整体右移
2.//选中,然后输入 shift+tab 整体左移
2.12 Java代码规范
1.类、方法的注释,要以javadoc的方式来写。
2.非Java Doc的注释,往往是给代码的维护者看的,着重告述读者为什么这样写,如何修改,注意什么问题等
3.使用tab操作,实现缩进,默认整体向右边移动,时候用shift+tab整体向左移
4.运算符和 = 两边习惯性各加一个空格。比如:2 + 4 * 5 + 345 - 89
5.源文件使用utf-8编码
6.行宽度不要超过80字符
7.代码编写次行风格和行尾风格(推荐)
2.13 DOS命令(了解)
2.13.1 DOS介绍
Dos: Disk Operating System 磁盘操作系统,简单说一下 windows 的目录结构。[原理图]
2.13.2 相关的知识补充:相对路径,绝对路径
2.13.3 常用的dos命令
1)查看当前目录是有什么内容 dir
dir dir d:\abc2\test200
2)切换到其他盘下 : 盘符号 cd : change directory
案例演示: 切换到c盘 cd /D c:
3)切换到当前盘的其他目录下(使用相对路径和绝对路径演示),..\表示上一级目录
案例演示: cd d:\abc2\test200 cd ..\..\abc2\test200
4)切换到上一级:
案例演示: cd ..
5)切换到根目录: cd \
案例演示: cd \
6)查看指定的目录下所有的子级目录 tree
7)清屏 cls
8)退出 DOS exit
9)说明:因为小伙伴后面使用DOS 非常少,所以对下面的几个指令,了解即可 (md[创建目录],rd[删除目录],copy[拷贝文件],del[删除文件],echo[输入内容到文件],type,move[剪切]) =>Linux
第3章 变量
3.1 为什么需要变量
3.1.1 变量是程序的基本组成单位
3.1.2 简单的原理示意图
3.2 变(变化)量(值)的介绍
3.2.1 概念
变量相当于内存中一个数据存储空间的表示,你可以把变量看做是一个房间的门牌号,通过门牌号我们可以找到房间,而通过变量名可以访问到变量(值)
3.2.2 变量使用的基本步骤
1)声明变量
int a;
2) 赋值
a = 60; //应该这么说: 把 60 赋给 a
使用 System.out.println(a);
//也可以一步到位[int a = 60; 通常我们是一步完成]
3.3 变量快速入门
public class Var02 {
//编写一个main方法
public static void main(String[] args) {
//记录人的信息
int age = 30;
double score = 88.9;
char gender = '男';
String name = "king";
//输出信息
System.out.println("人的信息如下:");
System.out.println(name);
System.out.println(age);
System.out.println(score);
System.out.println(gender);
}
}
3.4 变量使用注意事项
-
变量表示内存中的一个存储区域[不同的变量,类型不同,占用的空间大小不同,比如:int 4 个字节, double 就是 8个字节,先有基本印象,后面说字节]
-
该区域有自己的名称[变量名]和类型[数据类型]
-
变量必须先声明,后使用,即有顺序
-
该区域的数据/值可以在同一类型范围内不断变化
-
变量在同一个作用域内不能重名
-
变量=变量名+值+数据类型,这一点请大家注意。变量三要素
public class VarDetail{ //编写一个main方法 public static void main(String[] args){ //变量必须先声明,后使用,即有顺序 int a = 50;//int System.out.println(a);//50 //该区域的数据/值可以在同一类型范围内不断地变化 //a = "jack"; //错 a = 88; // 对 System.out.println(a); // 88 //变量在同一个作用域内不能重名 int a = 77; //错误 } } class Dog { public static void main(String[] args){ int a = 666;// 对 } }
3.5 程序中 + 号的使用
1.当左右两边都是数值型时,则做加法运算
2.当左右两边有一方为字符串,则做拼接运算
3.运算顺序,是从左到右
4.课堂测试题
System.out.printIn(100 + 98);//198
System.out.printIn("100"+ 98);//10098
System.out.printIn(100 + 3 + "hello")://103hello
System.out.printIn("hello"+ 100 +3);//hello1003
3.6 数据类型
每一种数据都定义了明确的数据类型,在内存中分配了不同大小的内存空间(字节)。
上图说明 [背下来]
1. java 数据类型分为两大类 基本数据类型, 引用类型
2. 基本数据类型有 8 种 数值型[byte , short , int , long , float ,double] char , boolean
3. 引用类型 [类,接口, 数组]
4. String属于引用数据类型
3.7 整数类型
3.7.1 基本介绍
Java 的整数类型就是用于存放整数值的,比如12,30,3456 等等
3.7.2 案例演示
byte n1 = 10;
short n2 = 10;
int n3 = 10;//4 个字节
long n4 = 10;//8个字节
3.7.3 整型的类型
3.7.4 整型的使用细节
-
Java各整数类型有固定的范围和字段长度,不受具体OS[操作系统]的影响,以保证java程序的可移植性。
-
Java的整型常量(具体值)默认为int型,声明long型常量须后加'l'或L
-
java程序中变量常声明为int型,除非不足以表示大数,才使用long
-
bit: 计算机中的最小存储单位。byte:计算机中基本存储单元,1byte =8 bit。[二进制再详细说]
-
思考题:long 类型,有几个 bit[8个字节*8bit= 64]
long n= 3;// 内存中存在形式
public class IntDetail{
public static void main(String[] args){
//Java 的整型常量(具体值)默认为 int 型,声明 long 型常量须后加‘l’或‘L’
int n1 = 1;//4个字节
//int n2 = 1l;//错
long n3 = 1L;//对
}
}
3.8 浮点类型
3.8.1 基本介绍
Java 的浮点类型可以表示一个小数,比如 123.4 ,7.8,0.12等等
3.8.2 浮点型的分类
3.8.3 说明
1)关于浮点数在机器中存放形式的简单说明,浮点数=符号位+指数位+尾数位
2)尾数部分可能丢失,造成精度损失(小数都是近似值)。
3.8.4 浮点型使用细节
-
与整数类型类似,Java 浮点类型也有固定的范围和字段长度,不受具体OS的影响。[float 4 个字节 double 是 8个字节]
-
Java 的浮点型常量(具体值)默认为double型,声明float型常量,须后加'f’或'F'
-
浮点型常量有两种表示形式
十进制数形式:如:5.12 512.0f .512(必须有小数点)
科学计数法形式:如:5.12e2[5.12*10的2次方]5.12E-2[5.12/10的2次方]
-
通常情况下,应该使用double型,因为它比float型更精确。[举例说明]
double num9 = 2.1234567851;
float num10 = 2.1234567851F;
5. 浮点数使用陷阱当我们对运算结果是小数的进行相等判断时要小心,例:2.7和8.1 / 3 比较
public class FloatDetail{
public static void main(String[] args){
//Java 的浮点型常量(具体值)默认为 double 型,声明 float 型常量,须后加‘f’或‘F'
//float num1 = 1.1;//错误
float num2 = 1.1F;//对
double num3 = 1.1;//对
double num4 = 1.1f;//对
//十进制数形式:如:5.12 512.0f .512 (必须有小数点)
double num5 = .123;//等价 0.123
System.out.println(num5);
//科学计数法形式:如:5.12e2 [5.12 * 10 的 2 次方] , 5.12E-2 [5.12 / 10 的 2 次方]
System.out.println(5.12e2);//512.0
System.out.println(5.12E-2);//0.0512
//通常情况下,应该使用 double 型,因为它比 float 型更精确。
//[举例说明]double num9 = 2.1234567851;float num10 = 2.1234567851F;
double num9 = 2.1234567851;
float num10 = 2.1234567851f;
System.out.println(num9);
System.out.println(num10);
//浮点数使用陷阱: 2.7 和 8.1 / 3 比较
double num11 = 2.7;
double num12 = 8.1 / 3;
System.out.println(num11);//2.7
System.out.println(num12);//接近 2.7 的一个小数,而不是 2.7
//得到一个重要的使用点: 当我们对运算结果是小数的进行相等判断是,要小心
//应该是以两个数的差值的绝对值,在某个精度范围类判断
if(num11 == num12){
System.out.println("num11 == num12 相等");
}
//正确的写法
if(Math.abs(num11 - num12) < 0.000001){
System.out.println("差值非常小,到我的规定精度,认为相等...");
}
//细节:如果是直接查询得的的小数或者直接赋值,是可以判断相等
}
}
3.9 JavaApi文档
-
APl(Application Programming Interface,应用程序编程接口)是 Java 提供的基本编程接口(java提供的类还有相关的方法)。中文在线文档:https://www.matools.com
-
Java语言提供了大量的基础类,因此 Oracle公司也为这些基础类提供了相应的API文档,用于告诉开发者如何使用这些类,以及这些类里包含的方法。
-
Java类的组织形式[!图]
3.10 字符类型(char)
3.10.1 基本介绍
字符类型可以表示单个字符,字符类型是 char,char是两个字节(可以存放汉字),多个字符我们用字符串 String(我们后面详细讲解 String)
3.10.2 案例演示
#代码
char c1 = 'a';
char c2 = '\t';
char c3 = '韩';
char c4 = 97;
3.10.3 字符类型使用细节
-
字符常量是用单引号( ' ' )括起来的单个字符。例如:char c1 ='a'; char c2 ='中';char c3 = '9';
-
Java中还允许使用转义字符 '\' 来将其后的字符转变为特殊字符型常量。例如:char c3= '\n' ;// '\n'表示换行符
-
在java中,char的本质是一个整数,在输出时,是unicode码对应的字符。
-
可以直接给char赋一个整数,然后输出时,会按照对应的unicode 字符输出[97 -> a]
-
char类型是可以进行运算的,相当于一个整数,因为它都对应有Unicode码
public class CharDetail{
public static void main(String[] args){
//在 java 中,char 的本质是一个整数,在默认输出时,是 unicode 码对应的字符
//要输出对应的数字,可以(int)字符
char c1 = 97;
System.out.println(c1);//a
char c2 = 'a';//输出'a'对应的数字
System.out.println((int)c2);
char c3 = '韩';
System.out.println((int)c3);
char c4 = 38889;
System.out.println(c4);//韩
//char 类型是可以进行运算的,相当于一个整数,因为它都对应有 Unicode 码.
System.out.println('a' + 10);//107
//课堂小测试
char c5 = 'b' + 1;//98+1=>99
System.out.println((int)c5);//99
System.out.println(c5);99->对应的字符->编码表 ASCII(规定好的)=>c
}
}
-
字符型 存储到 计算机中,需要将字符对应的码值(整数)找出来,比如'a'
存储:'a' ==> 码值 97 ==> 二进制(110 0001) ==> 存储:
读取:二进制(110 0001) => 97 ===> 'a' => 显示
-
字符和码值的对应关系是通过字符编码表决定的(是规定好)
-
介绍一下字符编码表[sublime测试]
ASCII (ASCII编码表 一个字节表示,一个128个字符,实际上一个字节可以表示256个字符,只用128个)
Unicode (Unicode 编码表 固定大小的编码 使用两个字节来表示字符,字母和汉字统一都是占用两个字节,这样浪费空间)
utf-8(编码表,大小可变的编码 字母使用1个字节,汉字使用3个字节)
gbk(可以表示汉字,而且范围广,字母使用1个字节,汉字2个字节)
gb2312(可以表示汉字,gb2312<gbk)
big5 码(繁体中文,台湾,香港)
3.11 ASCII码介绍(了解)
-
ASCII:上个世纪60年代,美国制定了一套字符编码(使用一个字节),对英语字符与二进制位之间的关系,做了统一的规定。这被称为ASCII码。ASCII码一共规定了128个字符的编码,只占用了一个字节的后面7位,最前面的1位同一规定为0。
特别提示:一个字节可以表示256个字符,ASCII码只用了 128个字符
-
着一个完整的ASCII码表[资料中]
-
缺点:不能表示所有字符
3.12 Unicode编码介绍(了解)
-
Unicode的好处:一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,使用 Unicode 没有乱码的问题。
-
Unicode 的缺点:一个英文字母和一个汉字都占用2个字节,这对于存储空间来说是浪费。
-
2的16次方是 65536,所以最多编码是65536个字符。
-
编码0-127的字符是与ASCI的编码一样.比如'a'在ASCII码是 0x61,在unicode码是ox0061,都对应97.因此 Unicode码兼容 ASCII码.
3.13 UTF-8编码介绍(了解)
-
UTF-8 是在互联网上使用最广的一种 Unicode 的实现方式(改进)
-
UTF-8 是一种变长的编码方式。它可以使用 1-6 个字节表示一个符号,根据不同的符号而变化字节长度。
-
使用 大小可变的编码 字母占1个字节,汉字占3个字节
3.14 布尔类型:boolean
3.14.1 基本介绍
-
布尔类型也叫boolean类型,booolean类型数据只允许取值true和false,无null
-
boolean类型占1个字节。
-
boolean 类型适于逻辑运算,一般用于程序流程控制[这个后面会详细介绍]:
if条件控制语句;
while循环控制语句;
do-while循环控制语句,
for循环控制语句
public class Boolean01{
//编写一个main方法
public static void main(String[] args){
//演示判断成绩是否通过的案例
//定义一个布尔变量
boolean isPass = false;//
if(isPass == true){
System.out.println("考试通过,恭喜");
}else{
System.out.println("考试没通过,下次努力");
}
}
}
3.14.2 使用细节说明
-
不可以用0或非0的整数替代false和true,这点和C语言不同
3.15 基本数据类型转换
3.15.1 自动类型转换
√ 介绍
当java程序在进行赋值或者运算时,精度小的类型自动转换为精度大的数据类型,这个就是自动类型转换。
√数据类型按精度(容量)大小排序为(背,规则)
3.15.2 自动类型转换注意和细节
-
有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。
-
当我们把精度(容量)大 的数据类型赋值给精度(容量)小 的数据类型时,就会报错,反之就会进行自动类型转换。
-
(byte,short)和 char之间不会相互自动转换。
-
byte,short,char 他们三者可以计算,在计算时首先转换为int类型。
-
boolean 不参与转换
-
自动提升原则: 表达式结果的类型自动提升为 操作数中最大的类型
public class AutoConvertDetail{
//编写一个main方法
public static void main(String[] args){
//细节 1: 有多种类型的数据混合运算时,
//系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算
int n1 = 10;//ok
//float d1 = n1 + 1.1;//错误 n1 + 1.1 => 结果类型是double
double d2 = n1 + 1.1;//对,n1 + 1.1 => 结果类型是double
float d1 = n1 + 1.1f;//对,n1 + 1.1f => 结果类型是float
//细节 2: 当我们把精度(容量)大 的数据类型赋值给精度(容量)小 的数据类型时,
//就会报错,反之就会进行自动类型转换。
//int n2 = 1.1;//错误,double => int
//细节 3: (byte, short) 和 char 之间不会相互自动转换
//当把具体数赋给 byte 时,(1)先判断该数是否在 byte 范围内,如果是就可以
byte b1 = 10;//对,-128 ~ 127
/**
* int n2 = 1;//n2是int
* byte b2 = n2;//错误;原因:如果是变量赋值,判断类型
**/
// char c1 = b1;//错误,原因:byte不能自动转换成char
// 细节 4: byte,short,char 他们三者可以计算,在计算时首先转换为 int 类型
byte b2 = 1;
byte b3 = 2;
short s1 = 1;
//short s2 = b2 + s1;//错误,b2 + s1 => int
int s2 = b2 + s1;//对,b2 + s1 => int
//byte b4 = b2 + b3;//错误: b2 + b3 => int
//细节5: boolean 不参与转换
boolean pass = true;
//int num100 = pass;//错误,boolean不参与类型的自动转换
//细节6:/自动提升原则: 表达式结果的类型自动提升为 操作数中最大的类型
byte b4 = 1;
short s3 = 100;
int num200 = 1;
float num300 = 1.1F;
double num500 = b4 + s3 + num200 + num300;//float -> double
}
}
3.15.3 强制类型转换
√介绍
自动类型转换的逆过程,将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转换符 ( ),但可能造成精度降低或溢出,格外要注意
√案例演示
public class ForceConvert{
public static void main(String[] args){
int i = (int)1.9;
System.out.println(i);// 1
int j = 2000;
byte b1 = (byte)j;
System.out.println(b1);//-48
//说明:2000 的二进制数为 0111 1101 0000
//byte只有8个字节,所以为1101 0000 即为-48
}
}
3.15.4 强制类型转换细节说明
-
当进行数据的大小从 大——>小,就需要使用到强制转换
-
强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级
-
char类型可以保存 int的常量值,但不能保存int的变量值,需要强转
-
byte和short,char类型在进行运算时,当做int类型处理。
public class ForceConvertDetail{
public static void main(String[] args){
//演示强制类型转换
//强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级
//int x = (int)10 * 3.5 + 6* 1.5;//编译错误: double -> int
int x = (int)(10 * 3.5 + 6 * 1.5);//(int)44.0 -> 44
System.out.println(x);//44
char c1 = 100;//ok
int m = 100;//ok
//char c2 = m;//错误
char c3 = (char)m;//ok
System.out.println(c3);//100 对应的字符,d字符
}
}
3.16 基本数据类型转换-练习题
3.17 基本数据类型和 String 类型的转换
3.17.1 介绍和使用
介绍
在程序开发中,我们经常需要将基本数据类型转成String 类型。或者将String类型转成基本数据类型。
基本数据类型
语法:将基本类型的值 + ""即可
String类型转基本数据类型[体验]
语法:通过基本类型的包装类调用parseXX方法即可
public class StringToBasic{
public static void main(String[] args){
//基本数据类型->String
int n1 = 100;
float f1 = 1.1F;
double d1 = 4.5;
boolean b1 =true;
String s1 = n1 + "";
String s2 = f1 + "";
String s3 = d1 + "";
String s4 = b1 + "";
System.out.println(s1 + " " + s2 + " " + s3 + " " + s4);
//String->对应的基本数据类型
String s5 = "123";
//会在 OOP 讲对象和方法的时候回详细
//解读 使用 基本数据类型对应的包装类,的相应方法,得到基本数据类型
int num1 = Integer.parseInt(s5);
double num2 = Double.parseDouble(s5);
float num3 = Float.parseFloat(s5);
long num4 = Long.parseLong(s5);
byte num5 = Byte.parseByte(s5);
boolean b = Boolean.parseBoolean("true");
short num6 = Short.parseShort(s5);
System.out.println("===================");
System.out.println(num1);//123
System.out.println(num2);//123.0
System.out.println(num3);//123.0
System.out.println(num4);//123
System.out.println(num5);//123
System.out.println(num6);//123
System.out.println(b);//true
//怎么把字符串转成字符 char -> 含义是指 把字符串的第一个字符得到
//解读 s5.charAt(0) 得到s5字符串的第一个字符'1'
System.out.println(s5.charAt(0));
}
}
3.17.2 注意事项
1)在将 String 类型转成 基本数据类型时,要确保String类型能够转成有效的数据,比如 我们可以把"123",转成一个整数,但是不能把"hello"转成一个整数
2)如果格式不正确,就会抛出异常,程序就会终止, 这个问题在异常处理章节中,会处理
/**
* 演示字符串转基本数据类型的细节
*/
public class StringToBasicDetail{
public static void main(String[] args){
String str = "hello";
//转成int
int n1 = Integer.parseInt(str);
System.out.println(n1);
}
}
3.18 本章作业
第4章 运算符
4.1 运算符介绍
4.1.1 运算符介绍
运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等。 1)算术运算符 2)赋值运算符 3)关系运算符[比较运算符] 4)逻辑运算符 5)位运算符[需要二进制基础] 6)三元运算符
4.2 算术运算符
4.2.1 介绍
算术运算符是对数值类型的变量进行运算的,在Java 程序中使用的非常多。
4.2.2 算术运算符一览
4.2.3 案例演示
-
+, -, *, /, %, ++, -- ,重点讲解 /、%、++
-
自增:++ 作为独立的语句使用:
前++和后++都完全等价于i=i+1;
作为表达式使用 前++:++i先自增后赋值
后++:i++先赋值后自增
-
--,+、-、*是一个道理,完全可以类推。
/**
* 演示算术运算符的使用
*/
public class ArithmeticOperator {
//编写一个main方法
public static void main(String[] args){
// /使用
System.out.println(10 / 4); //从数学来看是2.5,在java中是2
System.out.println(10.0 / 4); //java是2.5
double d = 10 / 4; //java中是10 / 4 = 2,double类型,2 => 2.0
System.out.println(d); //是2.0
// % 取模,取余
// 在 % 的本质 看一个公式 a % b = a - a / b * b
// -10 % 3 => -10 - (-10) / 3 * 3 = -1
// 10 % 3 => 10 - 10 / 3 * 3 = 10 - 9 = 1
// -10 % -3 => -10 - (-10) / (-3) * (-3) = -1
System.out.println(10 % 3); //1
System.out.println(-10 % 3); //-1
System.out.println(-10 % -3); //1
System.out.println(-10 % -3); //-1
//++的使用
//
int i = 10;
i++;// 自增 等价于 i = i + 1; => i = 11
++i;// 自增 等价于 i = i + 1; => i = 12
System.out.println("i=" + i); //12
/*
作为表达式使用
前++:++i先自增后赋值
后++:i++先赋值后自增
*/
int j = 8;
//int k = ++j; //等价 j = j + 1;k = j;
int k = j++; //等价k = j;j = j + 1;
System.out.println("k=" + k + "j=" + j);//8 9
}
}
4.2.4 细节说明
-
对于除号"/",它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。例如:int x= 10/3,结果是 3
-
当对一个数取模时,可以等价 a%b=a-a/b*b, (注意:a%b当a是小数时,公式=a - (int) a / b * b)这样我们可以看到 取模的一个本质运算。
-
当 自增 当做-一个独立语言使用时,不管是 ++i; 还是 i++; 都是一样的,等价
-
当自增 当做表达式使用时j = ++i 等价 i = i + 1,j = i
-
当自增 当做表达式使用时j = i++ 等价 j = i,i = i + 1
4.2.5 面试题
4.2.6 自增,自减课堂练习, 看看输出什么
// 练习
public class ArithmeticOperatorExercise01{
//编写一个main方法
public static void main(String[] args){
// int i = 1; //i->1
// i = i++; //规则使用临时变量:(1)temp=i;(2)i=i+1;(3)i=temp;
// System.out.println(i);//1
// int i = 1;
// i = ++i;//规则使用临时变量:(1)i = i + 1;(2)temp = i;(3)i = temp;
// System.out.println(i);//2
//
// 测试输出
int i1 = 10;
int i2 = 20;
int i = i1++;
System.out.println("i=" + i);//10;i = i1,i1 = i1 + 1
System.out.println("i1=" + i1);//11
i = --i2;
System.out.print("i=" + i);//19;i2 = i2 - 1,i = i2
System.out.println("i2=" + i2);//19
}
}
4.2.7 课堂练习2
1)假如还有 59 天放假,问:合 xx 个星期零 xx 天
2)定义一个变量保存华氏温度,华氏温度转换摄氏温度的公式为:5/9*(华氏温度-100),请求出华氏温度对应的摄氏温度。
3)代码
//课堂练习
public class ArithmeticOperatorExercise02{
public static void main(String[] args){
//1.需求:
//假如还有59天放假,问:合xx个星期需xx天
//2.思路分析
//(1) 使用int 变量 days 保存 天数
//(2) 一个星期是7天 days / 7 零xx天 days % 7
//(3) 输出
int days = 59;
int weeks = days / 7;
int leftDays = days % 7;
System.out.println(days + "天 合"
+ weeks + "星期零" + leftDays + "天");
//定义一个变量保存华氏温度,华氏温度转换摄氏温度的
//公式为:5/9*(华氏温度-100),请求出华氏温度对应的摄氏温度
double huaShi = 234.6;
double sheShi = 5.0 / 9 * (huaShi - 100);//注意这里要写5.0而不是5,因为5 / 9是int整型为0。
System.out.println("华氏温度" + huaShi + "对应的摄氏温度=" + sheShi);
}
}
4.3 关系运算符(比较运算符)
4.3.1 介绍
1)关系运算符的结果都是 boolean型,也就是要么是 true,要么是 false
2)关系表达式 经常用在 if 结构的条件中或循环结构的条件中
4.3.2 关系运算符一览
4.3.3 案例演示
//演示关系运算符的使用
public class RelationalOperator{
public static void main(String[] args) {
int a = 9;//提示:开发中,不可以使用a, b a1,bc n1 ,n2...!
int b = 8;
System.out.println(a > b); //T
System.out.println(a >= b); //T
System.out.println(a <= b); //F
System.out.println(a < b); //F
System.out.println(a == b); //F
System.out.println(a != b); //T
boolean flag = a > b; //T
System.out.println("flag=" + flag);
}
}
4.3.4 细节说明
1)关系运算符的结果都是 boolean 型,也就是要么是 true,要么是 false。
2)关系运算符组成的表达式,我们称为关系表达式。a>b
3)比较运算符"=="不能误写成"="
4.4 逻辑运算符
4.4.1 介绍
用于连接多个条件(多个关系表达式),最终的结果也是一个 boolean 值。
4.4.2 逻辑运算符一览
分为两组学习
1)短路与 && , 短路或 ||,取反 !
2)逻辑与 &,逻辑或 |,^ 逻辑异或
√说明逻辑运算规则:
1)a&b : & 叫逻辑与:规则:当 a 和 b 同时为 true ,则结果为 true, 否则为 false
2)a&&b : && 叫短路与:规则:当 a 和 b 同时为 true ,则结果为 true,否则为 false
3)a|b : | 叫逻辑或,规则:当 a 和 b ,有一个为 true ,则结果为 true,否则为 false
4)a||b : || 叫短路或,规则:当 a 和 b ,有一个为 true ,则结果为 true,否则为 false
5) !a : 叫取反,或者非运算。当 a 为 true, 则结果为 false, 当 a 为 false 是,结果为 true
6)a^b: 叫逻辑异或,当 a 和 b 不同时,则结果为 true, 否则为 false
4.4.3 && 和 & 基本规则
名称 | 语法 | 特点 |
---|---|---|
短路与&& | 条件 1&&条件 2 | 两个条件都为 true,结果为 true,否则 false |
逻辑与& | 条件 1&条件 2 | 两个条件都为 true,结果为 true,否则 false |
4.4.4 && 和 & 案例演示
/**
* 演示逻辑运算符的使用
*/
public class LogicOperator01{
public static void main(String[] args){
// && 短路与 和 & 逻辑与 案例演示
//
// &&短路与使用
int age = 50;
if(age > 20 && age < 90){
System.out.println("ok100");
}
// &逻辑与使用
if(age > 20 & age < 90){
System.out.println("ok200");
}
// 区别
int a = 4;
int b = 9;
// 对于&&短路与而言,如果第一个条件为false,后面的条件不再判断
// 对于&逻辑与而言,如果第一个条件为false,后面的条件仍然会判断
if(a < 1 & ++b < 50){
System.out.println("ok300");
}
System.out.println("a=" + a + "b=" + b);//4 10
}
}
4.4.5 && 和 & 使用区别
1)&&短路与:如果第一个条件为 false,则第二个条件不会判断,最终结果为 false,效率高
2)& 逻辑与:不管第一个条件是否为 false,第二个条件都要判断,效率低
3)开发中, 我们使用的基本是使用短路与&&, 效率高
4.4.6 || 和 | 基本规则
名称 | 语法 | 特点 |
---|---|---|
短路或|| | 条件1||条件2 | 两个条件中只要有一个成立,结果为 true,否则为 false |
|逻辑或 | 条件1|条件2 | 只要有一个条件成立,结果为 true,否则为 false |
4.4.7 || 和 | 案例演示
public class LogicOperator02{
public static void main(String[] args){
// || 短路与 和 | 逻辑与 案例演示
// ||规则:两个条件中只要有一个成立,结果为true,否则为false
// |规则:两个条件中只要有一个成立,结果为true,否则为false
// ||短路或使用
int age = 50;
if(age > 20 || age < 30){
System.out.println("ok100");
}
// |逻辑或使用
if(age > 20 | age < 30){
System.out.println("ok200");
}
// 区别
// (1)|| 短路或:如果第一个条件为true,则第二个条件不会判断,最终结果为true,效率高
// (2)| 逻辑或:不管第一个条件是否为true,第二个条件都要判断,效率低
int a = 4;
int b = 9;
if(a > 1 | ++b > 4){
System.out.println("ok300");
}
System.out.println("a=" + a + "b=" + b);//4 10
}
}
4.4.8 || 和 | 使用区别
1)||短路或:如果第一个条件为 true,则第二个条件不会判断,最终结果为 true,效率高
2)| 逻辑或:不管第一个条件是否为 true,第二个条件都要判断,效率低
3)开发中,我们基本使用 ||
4.4.9 ! 取反 基本规则
名称 | 语法 | 特点 |
---|---|---|
! 非(取反) | !条件 | 如果条件本身成立,结果为 false,否则为 true |
4.4.10 ! 案例演示
// ! 和 ^
public class InverseOperator{
public static void main(String[] args){
//! 操作是取反 T -> F,F -> T
System.out.println(60 > 20); //T
System.out.println(!(60 >20));//F
//a^b:叫逻辑异或,当 a 和 b 不同时,则结果为true,否则为false
boolean b = (10 > 1) ^ (3 > 5);
System.out.println("b=" + b);//T
}
}
4.4.11 ^ 案例演示
a^b: 叫逻辑异或,当 a 和 b 不同时,则结果为 true, 否则为 false
4.4.12 练习题 1 、2请写出每题的输出结果
//课堂练习
public class Text{
public static void main(String[] args){
// 题1
// int x = 5;int y = 5;
// if(x++ == 6 & ++y == 6){//逻辑与
// x = 11;
// }
// //x++ == 6,x先比较后自增;++y == 6,y先自增后比较
// System.out.println("x=" + x + "y=" + y);// x = 6,y = 6
// 题2
// int x = 5;int y = 5;
// if(x++ == 6 && ++y == 6){//短路与
// x = 11;
// }
// //x++ == 6,x先比较后自增;因为是短路与,所以第一个为假即为假
// System.out.println("x=" + x + "y=" + y);// x = 6,y = 5
// 题3
// int x = 5;int y = 5;
// if(x++ == 5 | ++y == 5){//逻辑或
// x = 11;
// }
// //x++ == 5,x先比较后自增;++y == 6,y先自增后比较,第一个为真第二个为假
// System.out.println("x=" + x + "y=" + y);// x = 11,y = 6
// 题4
// int x = 5;int y = 5;
// if(x++ == 5 || ++y == 5){//短路或
// x = 11;
// }
// //x++ == 5,x先比较后自增;因为是短路或,所以第一个为真即为真
// System.out.println("x=" + x + "y=" + y);// x = 11,y = 5
boolean x = true;
boolean y = false;
short z = 46;
if((z++ == 46) && (y = true)) z++;//z++先比较后自增,为真,z = 47; y = true 为真;z++,z = 48
if((x = false) || (++z == 49)) z++;//false赋值给x,为假;++z先自增后比较,z = 49,为真;z++,z = 50
System.out.println("z=" + z);//50
}
}
4.5 赋值运算符
4.5.1 介绍
赋值运算符就是将某个运算后的值,赋给指定的变量。
4.5.2 赋值运算符的分类
√基本赋值运算符 = int a = 10;
√复合赋值运算符
+= ,-= ,*= , /= ,%= 等 , 重点讲解一个 += ,其它的使用是一个道理
a += b; [等价 a = a + b; ]
a -= b; [等价 a = a - b; ]
4.5.3 赋值运算符特点
1)运算顺序从右往左 int num = a + b + c;
2)赋值运算符的左边 只能是变量,右边 可以是变量、表达式、常量值
int num = 20; int num2= 78 * 34 - 10; int num3 = a;
3)复合赋值运算符等价于下面的效果
比如:a+=3;等价于 a=a+3; 其他类推
4)复合赋值运算符会进行类型转换。
byte b = 2; b+=3; b++;
4.5.4 案例演示
案例演示赋值运算符的基本使用。
//演示赋值运算符的使用
public class AssignOperator{
public static void main(String[] args) {
int n1 = 10;
n1 += 4; // n1 = n1 + 4;
System.out.println(n1); // 14
n1 /= 3; // n1 = n1 / 3;
System.out.println(n1); // 4
//复合赋值运算符会进行类型转换
byte b = 3;
b += 2; // 等价 b = (byte)(b + 2);
b++; // b = (byte)(b + 1);
}
}
4.6 三元运算符
4.6.1 基本语法
条件表达式 ? 表达式 1: 表达式 2;
运算规则:
-
如果条件表达式为 true,运算后的结果是表达式 1;
-
.如果条件表达式为 false,运算后的结果是表达式 2;
4.6.2 案例演示
//三元运算符使用
public class TernaryOperator{
public static void main(String[] args) {
int a = 10;
int b = 99;
// 解读
// 1. a > b 为 false
// 2. 返回 b--, 先返回 b 的值,然后在 b-1
// 3. 返回的结果是 99
int result = a > b ? a++ : b--;
System.out.println("result=" + result);// 99
System.out.println("a=" + a);// 10
System.out.println("b=" + b);// 98
}
}
4.6.3 使用细节
1)表达式 1 和表达式 2 要为可以赋给接收变量的类型(或可以自动转换)
1)三元运算符可以转成 if--else 语句
int res = a > b ? a++ : --b;
if ( a > b) res = a++;
else res = --b;
//三元运算符细节
public class TernaryOperatorDetail {
//编写一个main方法
public static void main(String[] args){
//表达式1和表达式2要为可以赋给接收变量的类型
//(或可以自动转换/或者强制转换)
int a = 3;
int b = 8;
int c = a > b ? (int)1.1 : (int)3.4;//可以的
double d = a > b ? a : b + 3;//可以的,满足 int -> double
}
}
4.6.4 课堂练习
案例:实现三个数的最大值
public class TernaryOperatorExercise{
public static void main(String[] args) {
//案例:实现三个数的最大值
int n1 = 55;
int n2 = 33;
int n3 = 123;
//思路
//1.先得到 n1 和 n2 中最大数,保存到 max1
//2.然后再 求出 max1 和 n3中的最大数,保存到 max2
int max1 = n1 > n2 ? n1 : n2;
int max2 = max1 > n3 ? max1 : n3;
System.out.println("max2=" + max2);
//使用一条语句实现
int max = (n1 > n2 ? n1 : n2) > n3 ? (n1 > n2 ? n1 : n2) : n3;
System.out.println("max=" + max);
}
}
4.7 运算符优先级
1)运算符有不同的优先级,所谓优先级就是表达式运算中的运算顺序。如右表,上一行运算符总优先于下一行。
2)只有单目运算符、赋值运算符是从右向左运算的。
3)一览表, 不要背,使用多了,就熟悉了
4.8 标识符的命名规则和规范
4.8.1 标识符概念
-
Java 对各种变量、方法和类等命名时使用的字符序列称为标识符
-
凡是自己可以起名字的地方都叫标识符 int num1 =90;
4.8.2 标识符的命名规则(必须遵守)
-
由26个英文字母大小写,0-9,_或$组成
-
数字不可以开头。int 3ab = 1;//错误
-
不可以使用关键字和保留字,但能包含关键字和保留字。
-
Java中严格区分大小写,长度无限制。int totalNum = 10;int n=90
-
标识符不能包含空格。int a b=90;
4.8.3 判断下面变量名是否正确
hsp //ok
hsp12 //ok
1hsp //错误, 数字不能开头
h-s // 错误 , 不能有 - x h // 错误, 有空格
h$4 // ok
class //错误,class 关键字
int // 错误 ,int 是关键字
double //错误 ,double 是关键字
public //错误 ,public 是关键字
static //错误 ,static 是关键字
goto //错误, goto 是保留字
stu_name //ok
4.8.4 标识符命名规范[更加专业]
1)包名:多单词组成时所有字母都小写:aaa.bbb.ccc //比如 com.hsp.crm
2)类名、接口名:多单词组成时,所有单词的首字母大写:XxxYyyZzz [大驼峰] 比如: TankShotGame
3)变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写:xxxYyyZzz [小驼峰, 简称 驼峰法] 比如: tankShotGame
4)常量名:所有字母都大写。多单词时每个单词用下划线连接:XXX_YYY_ZZZ 比如 :定义一个所得税率 TAX_RATE
5)后面我们学习到 类,包,接口,等时,我们的命名规范要这样遵守,更加详细的看文档
4.9 关键字
关键字的定义和特点 (不用背)
定义:被 Java 语言赋予了特殊含义,用做专门用途的字符串(单词)
特点:关键字中所有字母都为小写
4.10 保留字
4.10.1 介绍
Java 保留字:现有 Java 版本尚未使用,但以后版本可能会作为关键字使用。自己命名标识符
时要避免使用这些保留字 byValue、cast、future、 generic、 inner、 operator、 outer 、
rest、 var 、 goto 、const
4.11 键盘输入语句
4.11.1 介绍
在编程中,需要接收用户输入的数据,就可以使用键盘输入语句来获取。需要一个 扫描器(对象), 就是Scanner
4.11.2 步骤 :
1) 导入该类的所在包, java.util.*
2) 创建该类对象(声明变量)
3) 调用里面的功能
4.11.3 案例演示:
要求:可以从控制台接收用户信息,【姓名,年龄,薪水】
import java.util.Scanner;//表示把java.util下的Scanner类导入
public class Input{
public static void main(String[] args){
//演示接受用户的输入
//步骤
//Scannner类 表示 简单文本扫描器,在java.util 包
//1. 引入/导入 Scanner类所在的包
//2. 创建 Scanner 对象 , new 创建一个对象
// myScanner 就是 Scanner类的对象
Scanner myScanner = new Scanner(System.in);
//3. 接受用户输入
System.out.println("请输入名字");
//当程序执行到 next 方法时,会等待用户输入
String name = myScanner.next(); //接受用户输入字符串
System.out.println("请输入年龄");
int age = myScanner.nextInt(); //接受用户输入int
System.out.println("请输入薪水");
double sal = myScanner.nextDouble(); //接受用户输入double
System.out.println("人的信息如下:");
System.out.println("名字=" + name + "年龄" + age + "薪水" + sal);
}
}
4.12 进制(程序员的基本功)
4.12.1 进制介绍
对于整数,有四种表示方式:
二进制:0,1 ,满 2 进 1.以 0b 或 0B 开头。
十进制:0-9 ,满 10 进 1。
八进制:0-7 ,满 8 进 1. 以数字 0 开头表示。
十六进制:0-9 及 A(10)-F(15),满 16 进 1. 以 0x 或 0X 开头表示。此处的 A-F 不区分大小写。
4.12.2 举例说明
//演示四种进制
//
public class BinaryTest {
public static void main(String[] args){
//n1 二进制
int n1 = 0b1010;
//n2 10进制
int n2 = 1010;
//n3 8进制
int n3 = 01010;
//n4 16进制
int n4 = 0X10101;
System.out.println("n1=" + n1);
System.out.println("n2=" + n2);
System.out.println("n3=" + n3);
System.out.println("n3=" + n4);
System.out.println(0x23A);
}
}
4.13 进制的图示
4.14 进制的转换(基本功)
4.14.1 进制转换的介绍
-
第一组:
1)二进制转十进制
2)八进制转十进制
3)十六进制转十进制
-
第二组:
1)十进制转二进制
2)十进制转八进制
3)十进制转十六进制
-
第三组
1)二进制转八进制
2)二进制转十六进制
-
第四组
1)八进制转二进制
2)十六进制转二进制
4.15 二进制转换成十进制示例
规则:从最低位(右边)开始,将每个位上的数提取出来,乘以2的(位数-1)次方,然后求和。
案例:请将 0b1011 转成十进制的数
0b1011 = 1 * 2的(1-1)次方 + 1 * 2的(2-1)次方 + 0 * 2的(3-1)次方 + 1 * 2的(4-1)次方法= 1 + 2 + 0 + 8 = 11
4.16 八进制转换成十进制示例
规则:从最低位(右边)开始,将每个位上的数提取出来,乘以8的(位数-1)次方,然后求和。
案例:请将 0234 转成十进制的数 0234 = 4 * 8 ^ 0 + 3 * 8 ^ 1 + 2 * 8 ^ 2 = 4 + 24 + 128 = 156
4.17 十六进制转换成十进制示例
规则:从最低位(右边)开始,将每个位上的数提取出来,乘以 16 的(位数-1)次方,然后求和。
案例:请将 0x23A 转成十进制的数
0x23A = 10 * 16 ^ 0 + 3 * 16 ^ 1 + 2 * 16 ^ 2 = 10 + 48 + 512 = 570
4.18 十进制转换成二进制
规则:将该数不断除以 2,直到商为 0 为止,然后将每步得到的余数倒过来,就是对应的二进制。一个字节有8位。
案例:请将 34 转成二进制 = 0B00100010
4.19 十进制转换成八进制
规则:将该数不断除以 8,直到商为 0 为止,然后将每步得到的余数倒过来,就是对应的八进制。 案例:请将 131 转成八进制 => 0203
4.20 十进制转换成十六进制
规则:将该数不断除以 16,直到商为 0 为止,然后将每步得到的余数倒过来,就是对应的十六进制。
案例:请将 237 转成十六进制 => 0xED
4.21 二进制转换成八进制
规则:从低位开始,将二进制数每三位一组,转成对应的八进制数即可。
案例:请将 0b11010101 转成八进制
0b11(3)010(2)101(5) => 0325
4.22 二进制转换成十六进制
规则:从低位开始,将二进制数每四位一组,转成对应的十六进制数即可。
案例:请将 0b11010101 转成十六进制
0b1101(D)0101(5) = 0xD5
4.23 八进制转换成二进制
规则:将八进制数每 1 位,转成对应的一个 3 位的二进制数即可。
案例:请将 0237 转成二进制
02(010)3(011)7(111) = 0b10011111
4.24 十六进制转换成二进制
规则:将十六进制数每 1 位,转成对应的 4 位的一个二进制数即可。
案例:请将 0x23B 转成二进制
0x2(0010)3(0011)B(1011) = 0b001000111011
4.25 位运算的思考题
1)请看下面的代码段,回答 a,b,c,d,e 结果是多少?
public static void maiin(String []args)
{
int a=1>>2; // 1 向右位移 2 位
int b=-1>>2;//算术右移
int c=1<<2;//算术左移
int d=-1<<2;//
int e=3>>>2;//无符号右移
//a,b,c,d,e 结果是多少
System.out.println("a="+a);
System.out.println("b="+b);
System.out.println("c="+c);
System.out.println("d="+d);
System.out.println("e="+e);
}
2)请回答在 java 中,下面的表达式运算的结果是: (位操作)
~2=? // 按位取反
2&3=?// 2 按位与 3
2|3=?
~-5=?
13&7=?
5|4=?
-3^3=?//^ 按位异或
4.26 二进制在运算中的说明
-
二进制是逢2进位的进位制,0、1是基本算符。
-
现代的电子计算机技术全部采用的是二进制,因为它只使用0、1两个数字符号,非常简单方便,易于用电子方式实现。计算机内部处理的信息,都是采用二进制数来表示的。二进制(Binary)数用0和1两个数字及其组合来表示任何数。进位规则是”逢2进1",数字1在不同的位上代表不同的值,按从右至左的次序,这个值以二倍递增。
4.27 原码、反码、补码(重点 难点)
网上对原码,反码,补码的解释过于复杂,我这里精简几句话:(背下来)对于有符号的而言:
-
二进制的最高位是符号位: 0表示正数,1表示负数(老韩口诀:0->0 1->-)
-
正数的原码,反码,补码都一样(三码合一)
-
负数的反码 = 它的原码符号位不变,其它位取反(0->1,1->0)
-
负数的补码 = 它的反码+1,负数的反码 = 负数的补码 - 1
-
0的反码,补码都是0
-
java没有无符号数,换言之,java中的数都是有符号的
-
在计算机运算的时候,都是以补码的方式来运算的.
-
当我们看运算结果的时候,要看他的原码(重点)
4.28 位运算符
4.28.1 java 中有 7 个位运算(&、|、 ^ 、~、>>、<<和 >>>)
按位与& | 两位全为1,结果为1,否则为0 |
---|---|
按位或| | 两位有一个为1,结果为1,否则为0 |
按位异或^ | 两位一个为0,一个为1,结果为1,否则为0 |
按位取反~ | 0->1,1->0 |
4.28.2 还有3 个位运算符>>、<< 和>>>,运算规则:
1)算术右移 >>: 低位溢出,符号位不变,并用符号位补溢出的高位
2)算术左移 <<: 符号位不变,低位补 0
3)>>>逻辑右移也叫无符号右移,运算规则是: 低位溢出,高位补 0
4)特别说明:没有 <<< 符号
4.28.3 应用案例
1)int a=1>>2; //1 => 00000001 => 00000000 本质 1 / 2 / 2 =0
2)int c=1<<2; //1 => 00000001 => 00000100 本质 1 * 2 * 2 = 4
public class BitOperator02 {
public static void main(String[] args) {
System.out.println(1 >> 2);// 0
System.out.println(1 << 2);// 4
System.out.println(4 << 3);// 4 * 2 * 2 * 2 = 32
System.out.println(15 << 2);//15 * 2 * 2 = 60
}
}
4.29 本章作业
第5章 程序控制结构
5.1 程序流程控制介绍
在程序中,程序运行的流程控制决定程序是如何执行的,是我们必须掌握的,主要有三大流程控制语句。
1)顺序控制 2)分支控制 3)循环控制
5.2 顺序控制
5.3 分支控制 if-else
5.3.1 分支控制 if-else 介绍
让程序有选择的的执行,分支控制有三种
1)单分支 if
2)双分支 if-else
3)多分支 if-else if -....-else
5.3.2 单分支
基本语法
if(条件表达式){
执行代码块;(可以有多条语句.)
}
说明: 当条件表达式为ture 时,就会执行{}的代码。如果为false,就不执行.特别说明,如果{}中只有一条语句,则可以不用 (},建议写上 {}
案例说明
编写一个程序,可以输入人的年龄,如果该同志的年龄大于18岁,则输出"你年龄大于18,要对自己的行为负责,送入监狱”
//if 的快速入门
import java.util.Scanner;//导入
public class If01 {
//编写一个 main 方法
public static void main(String[] args) {
//编写一个程序,可以输入人的年龄,如果该同志的年龄大于 18 岁, //则输出 "你年龄大于 18,要对自己的行为负责,送入监狱"
//思路分析
//1. 接收输入的年龄, 应该定义一个 Scanner 对象
//2. 把年龄保存到一个变量 int age
//3. 使用 if 判断,输出对应信息
//应该定义一个 Scanner 对象
Scanner myScanner = new Scanner(System.in);
System.out.println("请输入年龄");
//把年龄保存到一个变量 int age
int age = myScanner.nextInt();
//使用 if 判断,输出对应信息
if(age > 18) {
System.out.println("你年龄大于 18,要对自己的行为负责,送入监狱");
}
System.out.println("程序继续...");
}
}
单分支对应的流程图
5.3.3 双分支
基本语法
if(条件表达式){
执行代码块1;
}
else{
执行代码块2;
}
说明: 当条件表达式成立,即执行代码块1,否则执行代码块2.如果执行代码块只有一条语句,则{}可以省略,否则,不能省略
案例演示
//编写一个程序,可以输入人的年龄,如果该同志的年龄大于18岁,则输出"你年龄大于18,要对自己的行为负责,送入监狱”。否则,输出"你的年龄不大这次放过你了
//if-else 的快速入门
import java.util.Scanner;//导入
public class If02 {
//编写一个 main 方法
public static void main(String[] args) {
//编写一个程序,可以输入人的年龄,如果该同志的年龄大于 18 岁, //则输出 "你年龄大于 18,要对
//自己的行为负责, 送入监狱"。否则 ,输出"你的年龄不大这次放过你了."
//
//思路分析
//1. 接收输入的年龄, 应该定义一个 Scanner 对象
//2. 把年龄保存到一个变量 int age
//3. 使用 if-else 判断,输出对应信息
//应该定义一个 Scanner 对象
Scanner myScanner = new Scanner(System.in);
System.out.println("请输入年龄");
//把年龄保存到一个变量 int age
int age = myScanner.nextInt();
//使用 if-else 判断,输出对应信息
if(age > 18) {
System.out.println("你年龄大于 18,要对自己的行为负责,送入监狱");
} else {//双分支
System.out.println("你的年龄不大这次放过你了");
}
System.out.println("程序继续...");
}
}
双分支对应的流程图
单分支和双分支练习题
1)编写程序,声明 2 个 double 型变量并赋值。判断第一个数大于 10.0,且第 2 个数小于 20.0,打印两数之和。
2)【课后自己练】定义两个变量 int,判断二者的和,是否能被 3 又能被 5 整除,打印提示信息
3) 判断一个年份是否是闰年,闰年的条件是符合下面二者之一:(1)年份能被 4 整除,但不能被 100 整除; (2)能被 400整除
4)代码
//单分支和双分支的练习
public class IfExercise01{
public static void main(String[] args) {
double d1 = 11.0;
double d2 = 21.0;
if(d1 > 10.0 && d2 > 20.0){
System.out.println(d1 + d2);
}
//【课后自己练】定义两个变量 int,判断二者的和,
//是否能被 3 又能被 5 整除,打印提示信息
//
//思路分析
//1. 定义两个变量 int num1, num2
//2. 定义一个变量 int sum = num1 + num2;
//3. sum % 3 , 5 后 等于 0 说明可以整除
//4. 使用 if - else 来提示对应信息
//走代码
int i1 = 11;
int i2 = 4;
if((i1 + i2) % 3 == 0 && (i1 + i2) % 5 == 0){
System.out.println("i1 + i2的和能被3又能被5整除");
}
//判断一个年份是否是闰年,闰年的条件是符合下面二者之一:
//(1)年份能被 4 整除,但不能被 100 整除;(2)能被 400 整除
//
//思路分析
//1. 定义 int year 保存年
//2. 年份能被 4 整除,但不能被 100 整除, // => year % 4 == 0 && year % 100 != 0
//3. 能被 400 整除 => year % 400 == 0
//4. 上面的 2 和 3 是 或的关系
//代码实现
int year = 2020;
if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0){
System.out.println("此年是闰年");
} else{
System.out.println("此年不是闰年");
}
}
}
5.3.4 多分支
基本语法
if (条件表达式1){
执行代码块1;
}
else if (条件表达式2){
执行代码块2;
}
......
else{
执行代码块n;
}
特别说明: (1)多分支 可以没有 else ,如果所有的条件表达式都不成立,则一个执行入口都没有
(2)如果有 else,如果所有的条件表达式都不成立,则默认执行else代码块
多分支的流程图(重要)
案例演示1
import java.util.Scanner;
public class If03{
public static void main(String[] args) {
/*
输入保国同志的芝麻信用分:
如果:
信用分为 100 分时,输出 信用极好;
信用分为(80,99]时,输出 信用优秀;
信用分为[60,80]时,输出 信用一般;
其它情况 ,输出 信用 不及格
请从键盘输入保国的芝麻信用分,并加以判断
假定信用分数为 int
*/
Scanner myscanner = new Scanner(System.in);
//接收用户输入
System.out.println("请输入信用分(1-100):");
//请思考:如果小伙伴输入的不是整数,而是 hello.. //==>这里我们后面可以使用异常处理机制搞定-》老师点一下
int grade = myScanner.nextInt();
if(grade >=1 && grade <= 100) {
//因为有 4 种情况,所以使用多分支
if(grade == 100) {
System.out.println("信用极好");
} else if (grade > 80 && grade <= 99) { //信用分为(80,99]时,输出 信用优秀;
System.out.println("信用优秀");
} else if (grade >= 60 && grade <= 80) {//信用分为[60,80]时,输出 信用一般
System.out.println("信用一般");
} else {//其它情况 ,输出 信用 不及格
System.out.println("信用不及格");
}
} else {
System.out.println("信用分需要在 1-100,请重新输入:)");
}
}
}
案例演示2
5.4 嵌套分支
5.4.1 基本介绍
在一个分支结构中又完整的嵌套了另一个完整的分支结构,里面的分支的结构称为内层分支,外面的分支结构称为外层分支。建议: 不要超过 3 层 (可读性不好)
5.4.2 基本语法
if(){
if(){
//if-else
}else{
//if-else
}
}
5.4.3 应用案例1
import java.util.Scanner;
public class NestedIf{
public static void main(String[] args) {
//编写一个 main 方法
/*
参加歌手比赛,如果初赛成绩大于 8.0 进入决赛,
否则提示淘汰。并且根据性别提示进入男子组或女子组。
【可以让学员先练习下】, 输入成绩和性别,进行判断和输出信息。
提示: double score; char gender;
接收字符: char gender = scanner.next().charAt(0)
*/
//思路分析
//1. 创建 Scanner 对象,接收用户输入
//2. 接收 成绩保存到 double score
//3. 使用 if-else 判断 如果初赛成绩大于 8.0 进入决赛,否则提示淘汰
//4. 如果进入到 决赛,再接收 char gender, 使用 if-else 输出信息
//代码实现 => 思路 --> java 代码
Scanner myscanner = new Scanner(System.in);
System.out.println("输入初赛成绩");
double score = myscanner.nextDouble();
if(score > 8.0){
System.out.println("输入性别");
char gender = myscanner.next().charAt(0);
if(gender == '男'){
System.out.println("进入男子组");
}else{
System.out.println("进入女子组");
}
}else{
System.out.println("淘汰");
}
}
}
5.4.4 应用案例2
import java.util.Scanner;
public class IfExercise02{
public static void main(String[] args) {
Scanner myscanner = new Scanner(System.in);
System.out.println("请输入季节(1-12)");
int jijie = myscanner.nextInt();
if(jijie <= 12 && jijie > 0){
System.out.println("请输入年龄");
int age = myscanner.nextInt();
if(jijie >= 4 && jijie <= 10){
System.out.println("改季节为旺季");
if(age >= 18 && age <=60){
System.out.println("票价为60");
}else if(age < 18){
System.out.println("票价为30");
}else if(age > 60){
System.out.println("票价为20");
}
}else{
System.out.println("改季节为淡季");
if(age >= 18 && age <=60){
System.out.println("票价为60");
}else {
System.out.println("票价为20");
}
}
}else{
System.out.println("您输入的季节有误");
}
}
}
5.5 switch 分支结构
5.5.1 基本语法
5.5.2 流程图
5.5.3 快速入门
import java.util.Scanner;
public class Switch01{
public static void main(String[] args) {
/*
案例:Switch01.java
请编写一个程序,该程序可以接收一个字符,比如:a,b,c,d,e,f,g
a 表示星期一,b 表示星期二 …
根据用户的输入显示相应的信息.要求使用 switch 语句完成
思路分析
1. 接收一个字符 , 创建 Scanner 对象
2. 使用 switch 来完成匹配,并输出对应信息
代码
*/
Scanner myscanner = new Scanner(System.in);
System.out.println("请输入一个字符(a-g)");
char a = myscanner.next().charAt(0);
switch(a){
case 'a' :
System.out.println("星期一");
break;
case 'b' :
System.out.println("星期二");
break;
case 'c' :
System.out.println("星期三");
break;
case 'd' :
System.out.println("星期四");
break;
case 'e' :
System.out.println("星期五");
break;
case 'f' :
System.out.println("星期六");
break;
case 'g' :
System.out.println("星期日");
break;
default:
System.out.println("输入字符不正确");
}
System.out.println("退出了 switch ,继续执行程序");
}
}
5.5.4 switch 注意事项和细节讨论
-
表达式数据类型,应和case 后的常量类型一致,或者是可以自动转成可以相互比较的类型,比如输入的是字符,而常量是 int
-
switch(表达式)中表达式的返回值必须是:(byte,short,int,char,enum[枚举],String)
double c = 1.1; switch(c){//错误 case 1.1;//错误 System.out.println("ok3"); break; }
-
case子句中的值必须是常量,而不能是变量
-
default子句是可选的,当没有匹配的case时,执行default
-
break语句用来在执行完一个case分支后使程序跳出switch语句块;如果没有写break,程序会顺序执行到switch结尾,除非遇到break;
5.5.5 switch课堂练习
import java.util.Scanner;
public class SwitchExercise{
public static void main(String[] args) {
//使用 switch 把小写类型的
//char 型转为大写(键盘输入)。只转换 a->A, b->B, c, d, e.
//其它的输出 "other"。
//创建 Scanner 对象
Scanner myscanner = new Scanner(System.in);
System.out.println("请输入字母a-e");
char a = myscanner.next().charAt(0);
switch(a){
case 'a' :
System.out.println("A");
break;
case 'b' :
System.out.println("B");
break;
case 'c' :
System.out.println("C");
break;
case 'd' :
System.out.println("D");
break;
case 'e' :
System.out.println("E");
break;
default :
System.out.println("输入有误");
}
//对学生成绩大于 60 分的,输出"合格"。低于 60 分的,
//输出"不合格"。(注:输入的成绩不能大于 100), 提示 成绩/60
//思路分析
//1. 这道题,可以使用 分支来完成, 但是要求使用 switch
//2. 这里我们需要进行一个转换, 编程思路 :
// 如果成绩在 [60,100] , (int)(成绩/60) = 1
// 如果成绩在 [0,60) , (int)(成绩/60) = 0
System.out.println("输入学生成绩(0-100)");
int score = myscanner.nextInt();
if(score >= 0 && score <= 100){
switch(score/60){
case 1 :
System.out.print("合格");
break;
case 0 :
System.out.print("不合格");
break;
}
}else{
System.out.print("成绩有误");
}
//根据用于指定月份,
//打印该月份所属的季节。
//3,4,5 春季 6,7,8 夏季 9,10,11 秋季 12, 1, 2 冬季
//[课堂练习, 提示 使用穿透 ]
//
//思路分析
//1. 创建 Scanner 对象, 接收用户输入
//2. 使用 int month 接收
//3. 使用 switch 来匹配 ,使用穿透来完成,比较简洁
System.out.println("输入月份");
int month = myscanner.nextInt();
switch(month){
case 3:
case 4:
case 5:
System.out.println("这是春季");
break;
case 6:
case 7:
case 8:
System.out.println("这是夏季");
break;
case 9:
case 10:
case 11:
System.out.println("这是秋季");
break;
case 12:
case 1:
case 2:
System.out.println("这是冬季");
break;
default :
System.out.println("你输入的月份不对(1-12)");
}
}
}
5.5.6 switch和if的比较
1)如果判断的具体数值不多,而且符合 byte、short 、int、char,enum[枚举],String这6种类型。虽然两个语句都可以使用,建议使用 swtich 语句。 2)其他情况:对区间判断,对结果为 boolean 类型判断,使用if,if的使用范围更广
5.6 for 循环控制(!!!)
基本介绍:听其名而知其意,就是让你的代码可以循环的执行.
5.6.1 基本语法
for(循环变量初始化;循环条件;循环变量迭代){
循环操作(可以多条语句);
}
说明
-
for 关键字,表示循环控制
-
for 有四要素: (1)循环变量初始化(2)循环条件(3)循环操作(4)循环变量迭代
-
循环操作 , 这里可以有多条语句,也就是我们要循环执行的代码
-
如果 循环操作(语句) 只有一条语句,可以省略 {}, 建议不要省略
5.6.2 for循环执行流程分析
5.6.3 注意事项和细节说明
1)循环条件是返回一个布尔值的表达式
2)for(;循环判断条件;) 中的初始化和变量迭代可以写到其它地方(作用域不同),但是两边的分号不能省略。
3)循环初始值可以有多条初始化语句,但要求类型一样,并且中间用逗号隔开,循环变量迭代也可以有多条变量迭代语句,中间用逗号隔开
5.6.4 for 循环练习题
1)
public class ForExercise{
public static void main(String[] args) {
//打印 1~100 之间所有是 9 的倍数的整数,统计个数 及 总和.[化繁为简,先死后活]
//两个编程思想(技巧)
//1. 化繁为简 : 即将复杂的需求,拆解成简单的需求,逐步完成 编程 = 思想 --练习-> 代码
//2. 先死后活 : 先考虑固定的值,然后转成可以灵活变化的值
//
//思路分析
//打印 1~100 之间所有是 9 的倍数的整数,统计个数 及 总和
//化繁为简
//(1) 完成 输出 1-100 的值
//(2) 在输出的过程中,进行过滤,只输出 9 的倍数 i % 9 ==0
//(3) 统计个数 定义一个变量 int count = 0; 当 条件满足时 count++;
//(4) 总和 , 定义一个变量 int sum = 0; 当条件满足时累积 sum += i;
//先死后活
//(1) 为了适应更好的需求,把范围的开始的值和结束的值,做出变量
//(2) 还可以更进一步 9 倍数也做成变量 int t = 9;
int count = 0; //统计 9 的倍数个数 变量
int sum = 0; //总和
int start = 10;
int end = 200;
int t = 5; // 倍数
for(int i = start; i <= end; i++) {
if( i % t == 0) {
System.out.println("i=" + i);
count++;
sum += i;//累积
}
}
System.out.println("count=" + count);
System.out.println("sum=" + sum);
}
}
2)
①
public class ForExercise02{
public static void main(String[] args) {
for(int i = 0,j = 5;i <= 5;i++,j--){
System.out.println(i + " + " + j + " = " + (i + j));
}
}
}
②
public class ForExercise02 {
//编写一个 main 方法
public static void main(String[] args) {
//化繁为简
//先死后活
int n = 9;
for( int i = 0; i <= n; i++) {
System.out.println(i + "+" + (n-i) + "=" + n);
}
}
}
5.7 while 循环控制
5.7.1 基本语法
while(循环条件){
循环体(语句);
循环变量迭代;
}
说明:
1)while 循环也有四要素
2)只是四要素放的位置和for不一样
5.7.2 while 循环执行流程分析
1)流程图
2)使用 while 循环完成前面的题
//while 循环的案例
public class While01{
public static void main(String[] args) {
//输出 10 句 你好,韩顺平教育
int i = 1;//循环变量初始化
while(i <= 10){//循环条件
System.out.println(i);
i++;//循环变量迭代
}
}
}
5.7.3 注意事项和细节说明
1)循环条件是返回一个布尔值的表达式
2)while 循环是先判断再执行语句
5.7.4 课堂练习题
public class WhileExercise{
public static void main(String[] args) {
// 打印 1—100 之间所有能被 3 整除的数 [使用 while, 老师评讲 ]
// 化繁为简, 先死后活
int i = 0;
int endNum = 100;
while(i < endNum){
if(i % 3 == 0){
System.out.println(i);
}
i++;//变量自增
}
// 打印 40—200 之间所有的偶数 [使用 while, 课后练习]
// 化繁为简, 先死后活(利于思考)
//
System.out.println("========");
int j = 40;
while(j >= 40 && j <= 200){
if(j % 2 == 0){
System.out.println(j);
}
j++;
}
}
}
5.8 do..while 循环控制
5.8.1 基本语法
循环变量初始化;
do{
循环体(语句);
循环变量迭代;
}while(循环条件);
5.8.2 说明:
-
do while 是关键字
-
也有循环四要素, 只是位置不一样
-
先执行,再判断,也就是说,一定会至少执行一次
-
最后 有一个 分号 ;
-
while 和 do..while 区别举例: 要账
5.8.3 do...whie 循环执行流程分析
1)流程图
2)使用 do...while 循环完成前面的题
public class DoWhile01{
public static void main(String[] args) {
int i = 0;
do{
System.out.println("你好");
i++;
}while(i < 10);
}
}
5.8.4 注意事项和细节说明
1)循环条件是返回一个布尔值的表达式
2)do..while 循环是先执行,再判断, 因此它至少执行一次
5.8.5 课堂练习题
1)
public class DoWhileExercise01{
public static void main(String[] args) {
int i = 1;
do{
System.out.println(i);
i++;
}while(i <= 100);
System.out.println("----------");
int j = 0;
int sum = 0;
do{
sum += j;
j++;
}while(j <= 100);
System.out.println(sum);
System.out.println("----------");
//统计 1---200 之间能被 5 整除但不能被 3 整除的 个数
//化繁为简
//(1) 使用 do-while 输出 1-200
//(2) 过滤 能被 5 整除但不能被 3 整除的数 %
//(3) 统计满足条件的个数 int count = 0;
//先死后活
//(1) 范围的值 1-200 你可以做出变量
//(2) 能被 5 整除但不能被 3 整除的 , 5 和 3 可以改成变量
int k = 1;
int count = 0;
do{
if(k % 5 == 0 && k % 3 != 0){
count ++;
}
k++;
}while(k <= 200);
System.out.println(count);
}
}
2)
import java.util.Scanner;
public class DoWhileExercise02{
public static void main(String[] args) {
//如果李三不还钱,则老韩将一直使出五连鞭,直到李三说还钱为
//[System.out.println("老韩问:还钱吗?y/n")] do...while .. //
//化繁为简
//(1) 不停的问还钱吗?
//(2) 使用 char answer 接收回答, 定义一个 Scanner 对象
//(3) 在 do-while 的 while 判断如果是 y 就不在循环
Scanner myscanner = new Scanner(System.in);
char answer = ' ';
do{
System.out.println("老韩问:还钱吗?y/n");
answer = myscanner.next().charAt(0);
System.out.println("回答" + a);
}while(a != 'y');
System.out.println("李三还钱了");
}
}
5.9 多重循环控制(难点! 重点!)
5.9.1 介绍
1)将一个循环放在另一个循环体内,就形成了嵌套循环。其中,for ,while ,do…while 均可以作为外层循环和内层循环。
【建议一般使用两层,最多不要超过 3 层, 否则,代码的可读性很差】
2)实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的循环条件为 false 时,才会完全跳出内层循环,才可结束外层的当次循环,开始下一次的循环[听不懂,走案例]。
3)设外层循环次数为 m 次,内层为 n 次,则内层循环体实际上需要执行 m*n 次。
5.9.2 多重循环执行步骤分析:
请分析 下面的多重循环执行步骤, 并写出输出 => 韩老师的内存分析法
//双层 for MulFor.java
for(int i = 0; i < 2; i++) { //先思考
for( int j = 0; j < 3; j++) {
System.out.println("i=" + i + j=" + j);
}
}
5.9.3 应用实例:
1)
import java.util.Scanner;
public class MulForExercise01 {
//编写一个 main 方法
public static void main(String[] args) {
//统计 3 个班成绩情况,每个班有 5 名同学,
//求出各个班的平均分和所有班级的平均分[学生的成绩从键盘输入]。
//统计三个班及格人数,每个班有 5 名同学。
//
//思路分析
//化繁为简
//(1) 先计算一个班 , 5 个学生的成绩和平均分 , 使用 for
//1.1 创建 Scanner 对象然后,接收用户输入
//1.2 得到该班级的平均分 , 定义一个 doubel sum 把该班级 5 个学生的成绩累积
//(2) 统计 3 个班(每个班 5 个学生) 平均分
//(3) 所有班级的平均分
//3.1 定义一个变量,double totalScore 累积所有学生的成绩
//3.2 当多重循环结束后,totalScore / (3 * 5)
//(4) 统计三个班及格人数
//4.1 定义变量 int passNum = 0; 当有一个学生成绩>=60, passNum++
//4.2 如果 >= 60 passNum++
//(5) 可以优化[效率,可读性, 结构]
//创建 Scanner 对象
Scanner myScanner = new Scanner(System.in);
double totalScore = 0; //累积所有学生的成绩
int passNum = 0;//累积 及格人数
int classNum = 3; //班级个数
int stuNum = 5;//学生个数
for( int i = 1; i <= classNum; i++) {//i 表示班级
double sum = 0; //一个班级的总分
for( int j = 1; j <= stuNum; j++) {//j 表示学生
System.out.println("请数第"+i+"个班的第"+j+"个学生的成绩");
double score = myScanner.nextDouble();
//当有一个学生成绩>=60, passNum++
if(score >= 60) {
passNum++;
}
sum += score; //累积
System.out.println("成绩为" + score);
}
//因为 sum 是 5 个学生的总成绩
System.out.println("sum=" + sum + " 平均分=" + (sum / stuNum));
//把 sum 累积到 totalScore
totalScore += sum;
}
System.out.println("三个班总分="+ totalScore
+ " 平均分=" + totalScore / (classNum*stuNum));
System.out.println("及格人数=" + passNum);
}
}
2)打印出九九乘法表[课后题]
public class Test{
public static void main(String[] args) {
for(int i = 1;i <= 9;i++){
for(int j = 1;j < i + 1;j++){
System.out.print(j + "*" + i);
}
System.out.println();
}
}
}
5.9.4 经典的打印金字塔
使用 for 循环完成下面的案例
请编写一个程序,可以接收一个整数,表示层数(totalLevel),打印出金字塔。(Stars.java) [化繁为简, 先死后活]
public class Stars {
//编写一个 main 方法
public static void main(String[] args) {
/*
*
* *
* *
********
思路分析
化繁为简
1. 先打印一个矩形
*****
*****
*****
*****
*****
2. 打印半个金字塔
* //第 1 层 有 1 个*
** //第 2 层 有 2 个*
*** //第 3 层 有 3 个*
**** //第 4 层 有 4 个*
***** //第 5 层 有 5 个*
3. 打印整个金字塔
* //第 1 层 有 1 个* 2 * 1 -1 有 4=(总层数-1)个空格
*** //第 2 层 有 3 个* 2 * 2 -1 有 3=(总层数-2)个空格
***** //第 3 层 有 5 个* 2 * 3 -1 有 2=(总层数-3)个空格
******* //第 4 层 有 7 个* 2 * 4 -1 有 1=(总层数-4)个空格
********* //第 5 层 有 9 个* 2 * 5 -1 有 0=(总层数-5)个空格
4. 打印空心的金字塔 [最难的]
* //第 1 层 有 1 个* 当前行的第一个位置是*,最后一个位置也是*
* * //第 2 层 有 2 个* 当前行的第一个位置是*,最后一个位置也是*
* * //第 3 层 有 2 个* 当前行的第一个位置是*,最后一个位置也是*
* * //第 4 层 有 2 个* 当前行的第一个位置是*,最后一个位置也是*
********* //第 5 层 有 9 个* 全部输出*
先死后活
5 层数做成变量 int totalLevel = 5;
//小伙伴 技术到位,就可以很快的把代码写出
*/
int totalLevel = 20; //层数
for(int i = 1; i <= totalLevel; i++) { //i 表示层数
//在输出*之前,还有输出 对应空格 = 总层数-当前层
for(int k = 1; k <= totalLevel - i; k++ ) {
System.out.print(" ");
}
//控制打印每层的*个数
for(int j = 1;j <= 2 * i - 1;j++) {
//当前行的第一个位置是*,最后一个位置也是*, 最后一层全部 *
if(j == 1 || j == 2 * i - 1 || i == totalLevel) {
System.out.print("*");
} else { //其他情况输出空格
System.out.print(" ");
}
}
//每打印完一层的*后,就换行 println 本身会换行
System.out.println("");
}
}
}
5.10 跳转控制语句-break
5.10.1 看下面一个需求
随机生成 1-100 的一个数,直到生成了 97 这个数,看看你一共用了几次?
提示使用 (int)(Math.random() * 100) + 1
思路分析:
循环,但是循环的次数不知道. -> break ,当某个条件满足时,终止循环
通过该需求可以说明其它流程控制的必要性,比如 break
5.10.2 基本介绍:
break 语句用于终止某个语句块的执行,一般使用在 switch 或者循环[for , while , do-while]中
5.10.3 基本语法:
{ ……
break;
……
}
5.10.4 以 while 使用 break 为例,画出示意图
5.10.5 快速入门
5.10.6 注意事项和细节说明:
5.10.7 课堂练习题:
1)
public class BreakExercise{
public static void main(String[] args)
//1-100 以内的数求和,求出 当和 第一次大于 20 的当前数 【for + break】
//思路分析
//1. 循环 1-100, 求和 sum
//2. 当 sum > 20 时,记录下当前数,然后 break
//3. 在 for 循环外部,定义变量 n , 把当前 i 赋给 n
int sum = 0;
//注意 i 的作用范围在 for{}
int n = 0;
for(int i = 1; i <= 100; i++){
sum += i;
if(sum > 20){
System.out.println("和大于20时,当前数i" + i);
n = i;
break;
}
}
}
}
2)
补充说明字符串 的内容 比较 使用的 方法 equals
import java.util.Scanner;
public class BreakExercise02{
public static void main(String[] args) {
//实现登录验证,有 3 次机会,如果用户名为"丁真" ,密码"666"提示登录成功,
//否则提示还有几次机会,请使用 for+break 完成
//
// 思路分析
// 1. 创建 Scanner 对象接收用户输入
// 2. 定义 String name ; String passwd; 保存用户名和密码
// 3. 最多循环 3 次[登录 3 次],如果 满足条件就提前退出
// 4. 定义一般变量 int chance 记录还有几次登录机会
//
// 代码实现
Scanner myscanner = new Scanner(System.in);
String name = "";
String passwd = "";
int chance = 3;//登录一次 ,就减少一次
for(int i = 1;i <= 3;i++){
System.out.println("请输入名字");
name = myscanner.next();
System.out.println("请输入密码");
passwd = myscanner.next();
//比较输入的名字和密码是否正确
//补充说明字符串 的内容 比较 使用的 方法 equals
if("丁真".equals(name) && "666".equals(passwd)){
System.out.println("登陆成功");
break;
}else {
System.out.println("您还有" + (chance - i) + "次机会");
}
}
}
}
5.11 跳转控制语句-continue
5.11.1 基本介绍:
1)continue 语句用于结束本次循环,继续执行下一次循环。
2)continue 语句出现在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环 , 这个和前面的标签的
使用的规则一样
5.11.2 基本语法
{ ……
continue;
……
}
5.11.3 以 while 使用 continue 为例,画出示意图
5.11.4 快速入门案例
5.11.5 细节案例分析和说明:
public class ContinueDetai1 {
//编写一个main方法
public static void main(String[] args) {
label1:
for (int j = 0; j < 4; j++) {
label2:
for (int i = 0; i < 10; i++) {
if (i == 2) {
//看看分别输出什么值,并分析//continue ;//continue label2;continue label1;
System.out.println("i=" + i);
continue;
}
}
}
}
}
5.12 跳转语句-return
return 使用在方法,表示跳出所在的方法,在讲解方法的时候,会详细的介绍,这里我们简单的提一下。注意:如果 return 写在 main 方法,退出程序.
5.13 本章作业
1)
public class Homework01 {
//编写一个main方法
public static void main(String[] args) {
/*
某人有100,000元,每经过一次路口,需要交费,规则如下:
1) 当现金>50000时,每次交5%
2) 当现金<=50000时,每次交1000
编程计算该人可以经过多少次路口, 要求: 使用 while + break方式完成
思路分析
1. 定义 double money 保存 100000
2. 根据题的要求,我们分析出来有三种情况
money > 50000
money >=1000 && money <= 50000
money < 1000
3. 使用多分支 if-elseif-else
4. while+break[money < 1000], 同时使用一个变量count来保存通过路口
代码实现
*/
double money = 100000;//还有多少钱
int count = 0; //累积过的路口
while(true) { //无限循环
if(money > 50000) { //过路口
//money = money - money * 0.05;
money *= 0.95; //过了这个路口后,还有这么多钱
count++;
} else if(money >=1000) {
money -= 1000;
count++;
} else { //钱不够1000
break;
}
}
System.out.println("100000 可以过 " + count + " 路口..");
}
}
2)
public class Homework04 {
//编写一个main方法
public static void main(String[] args) {
/*
4. 判断一个整数是否是水仙花数,所谓水仙花数是指一个3位数,
其各个位上数字立方和等于其本身。
例如: 153 = 1*1*1 + 3*3*3 + 5*5*5
思路分析 => 多听. 见多识广..
1. 比如 int n = 153;
2. 先得到 n的百位,十位 ,各位的数字, 使用 if 判断他们的立方和是否相等
3. n的百位 = n / 100
4. n的十位 = n % 100 / 10
5. n的各位 = n % 10
6. 判断即可
*/
int n = 154;
int n1 = n / 100;
int n2 = n % 100 / 10;
int n3 = n % 10;
if(n1 * n1 * n1 + n2 * n2 * n2 + n3 * n3 * n3 == n) {
System.out.println(n + "是水仙花数");
} else {
System.out.println(n + "不是水仙花数");
}
}
}
3)
public class Homework08 {
//编写一个main方法
public static void main(string[] args){
/*
求出1-1/2+1/3-1/4...1/100的和
思路分析
1. 1-1/2+1/3-1/4..1/100=(1/1)-(1/2)+(1/3)-(1/4)...1/100
2. 从上面的分析我们可以看到
(1) 一共有100数,分子为1,分母从1-100
(2) 还发现 当分母为奇数时,前面是 +,当分母是偶数时,前面是-
3. 我们可以使用 for + 判断即可完成
4. 把结果存放到 double sum
5. 这里有一个隐藏的陷阱,要把 公式分子 1 写成 1.0 才能得到精确的小数
*/
double sum = 0;
for(int i = 1;i <= 100; i++){
//判断是奇数还是偶数,然后做不同的处理
if(i % 2 != 0){//分母为奇数
sum += 1.0/i;
}else{//分母为偶数
sum -= 1.0/i;
}
}
System.out.println("sum=" + sum);
}
}
4)
public class Homework08{
public static void main(String[] args) {
//求(1)+(1+2)+(1+2+3)+(1+2+3+4)+...+(1+2+3+..+100)的结果
//思路分析
//1. 一共有100项相加
//2. 每一项的数字在逐渐增加
//3. 很像一个双层循环
//i 可以表示是第几项,同时也是当前项的最后一个数
//4. 使用 sum 进行累计即可
int sum = 0;
for(int i = 1; i <= 100; i++){
for(int j = 1; j <= i;j++ ){//内层对1-i进行循环
sum += j;
}
}
System.out.println("sum=" + sum);
}
}
第6章 数组、排序和查找
6.1 为什么需要数组
一个养鸡场有 6 只鸡,它们的体重分别是 3kg,5kg,1kg,3.4kg,2kg,50kg 。请问这六只鸡的总体重是多少?平均体重是多少? 请你编一个程序。
思路:
定义 6 个变量 , 加起来 总体重, 求出平均体重.引出 -> 数组
6.1.1数组介绍
数组可以存放多个同一类型的数据。数组也是一种数据类型,是引用类型。
即:数(数据)组(一组)就是一组数据
6.1.2 数组快速入门
我们可以用数组来解决上一个问题。
//数组的引出
public class Array01{
public static void main(String[] args) {
/*
它们的体重分别是 3kg,5kg,1kg,3.4kg,2kg,50kg 。
请问这六只鸡的总体重是多少?平均体重是多少?
思路分析
1. 定义六个变量 double , 求和 得到总体重
2. 平均体重 = 总体重 / 6
3. 分析传统实现的方式问题. 6->600->566
4. 引出新的技术 -> 使用数组来解决.
*/
// double hen1 = 3;
// double hen2 = 5;
// double hen3 = 1;
// double hen4 = 3.4;
// double hen5 = 2;
// double hen6 = 50;
// double weight = hen1 + hen2 + hen3 + hen4 + hen5 + hen6;
// double avgweight = weight / 6;
// System.out.print("总体重" + weight + "平均体重" + avgweight);
//比如,我们可以用数组来解决上一个问题 => 体验
//
//定义一个数组
//解读
//1. double[] 表示 是 double 类型的数组, 数组名 hens
//2. {3, 5, 1, 3.4, 2, 50} 表示数组的值/元素,依次表示数组的第几个元素
double[] hens = {3,5,1,3.4,2,50};
//遍历数组得到数组的所有元素的和, 使用 for
//解读
//1. 我们可以通过 hens[下标] 来访问数组的元素
// 下标是从 0 开始编号的比如第一个元素就是 hens[0]
// 第 2 个元素就是 hens[1] , 依次类推
//2. 通过 for 就可以循环的访问 数组的元素/值
//3. 使用一个变量 totalWeight 将各个元素累积
System.out.println("===使用数组解决===");
//老师提示: 可以通过 数组名.length 得到数组的大小/长度
//System.out.println("数组的长度=" + hens.length);
double totalWeight = 0;
for(int i = 0;i < hens.length;i++){
//System.out.println("第" + (i+1) + "个元素的值=" + hens[i]);
totalWeight += hens[i];
}
System.out.println("总体重=" + totalWeight
+ "平均体重=" + (totalWeight / hens.length) )
}
}
6.2 数组的使用
6.2.1 使用方式1-动态初始化
数组的定义
数据类型 数组名[] = new 数据类型[大小]
int a[]=new int[5]; //创建了一个数组,名字a,存放5个int 说明:这是定义数组的一种方法。为了让大家明白,我画数组内存图说明
数组的引用(使用/访问/获取数组元素)
数组名[下标/索引/index]比如:你要使用a数组的第3个数 a[2]
数组的下标从 0开始.
快速入门案例 Array02.java
循环输入5个成绩,,保存到double数组,并输出
import java.util.Scanner;
public class Array02{
public static void main(String[] args) {
//演示 数据类型 数组名[]=new 数据类型[大小]
//循环输入 5 个成绩,保存到 double 数组,并输出
//步骤
//1. 创建一个 double 数组,大小 5
//(1) 第 1 种动态分配方式
//double scores[] = new double[5];
//(2) 第 2 种动态分配方式, 先声明数组,再 new 分配空间
double scores[] ; //声明数组, 这时 scores 是 null
scores = new double[5]; // 分配内存空间,可以存放数据
//这里可以达到某个条件再说分配多少空间给它
//2. 循环输入
// scores.length 表示数组的大小/长度
//
Scanner myScanner = new Scanner(System.in);
for( int i = 0; i < scores.length; i++) {
System.out.println("请输入第"+ (i+1) +"个元素的值");
scores[i] = myScanner.nextDouble();
}
//输出,遍历数组
System.out.println("==数组的元素/值输出的情况如下:==");
for(int i = 0;i < scores.length; i++){
System.out.println("第" + (i + 1) + "个元素的值" + scores[i]);
}
}
}
6.2.2 使用方式 2-动态初始化
√ 先声明数组
语法:数据类型 数组名[]; 也可以 数据类型[] 数组名;
int a[]; 或者 int[] a;
√ 创建数组
语法: 数组名=new 数据类型[大小];
a=new int[10];
6.2.3 使用方式 3-静态初始化
6.3 数组使用注意事项和细节
1)数组是多个相同类型数据的组合,实现对这些数据的统一管理
2)数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用。
3)数组创建后,如果没有赋值,有默认值
int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char \u0000,boolean false,String null
4)使用数组的步骤 1. 声明数组并开辟空间 2. 给数组各个元素赋值 3. 使用数组
5)数组的下标是从 0 开始的。
6)数组下标必须在指定范围内使用,否则报:下标越界异常,比如
int [] arr=new int[5]; 则有效下标为 0-4
7)数组属引用类型,数组型数据是对象(object)
代码:
public class ArrayDetail {
public static void main(String[] args) {
//1. 数组是多个相同类型数据的集合,实现对这些数据的统一管理
// int arr1[] = {1, 2, 3, 60, "hello"};//String -> int
double arr2[] = {1.1, 2.2, 3.3, 60.6, 100};//int -> double
//2. 数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用
String arr3[] = {"北京", "jack", "milan"};
//3. 数组创建后,如果没有赋值,有默认值
//int 0,short 0,byte 0,long 0,
//float 0.0,double 0.0,char \u0000,
//boolean false,String null
//
short arr4[] = new short[3];
System.out.println("=====数组 arr4=====");
for(int i = 0; i < arr4.length; i++){
System.out.println(arr4[i]);
}
//6. 数组下标必须在指定范围内使用,否则报:下标越界异常,比如
//int [] arr = new int[5];则有效下标为 0-4
//即数组的下标/索引 最小 0最大 数组长度-1 (4)
int arr[] = new int[5];
//System.out.println(arr[5]);//数组越界
}
}
6.4 数组应用案例
1)
public class ArrayExercise01{
public static void main(String[] args) {
/*
创建一个 char 类型的 26 个元素的数组,分别 放置'A'-'Z'。
使用 for 循环访问所有元素并打印出来。
提示:char 类型数据运算 'A'+1 -> 'B'
思路分析
1. 定义一个 数组 char[] chars = new char[26]
2. 因为 'A' + 1 = 'B' 类推,所以老师使用 for 来赋值
3. 使用 for 循环访问所有元素
*/
char chars[] = new char[26];
for(int i = 0;i < chars.length; i++){
//chars 是 char[]
//chars[i] 是 char
chars[i] = (char)('A' + i);//'A' + i 是 int , 需要强制转换
}
//循环输出
System.out.println("===chars 数组===");
for(int i = 0; i < c1.length;i++){
System.out.print(c1[i]);
}
}
}
2)
public class ArrayExercise02 {
//编写一个 main 方法
public static void main(String[] args) {
//请求出一个数组 int[]的最大值 {4,-1,9, 10,23},并得到对应的下标
//思路分析
//1. 定义一个 int 数组 int[] arr = {4,-1,9, 10,23};
//2. 假定 max = arr[0] 是最大值 , maxIndex=0;
//3. 从下标 1 开始遍历 arr, 如果 max < 当前元素,说明 max 不是真正的
// 最大值, 我们就 max=当前元素; maxIndex=当前元素下标
//4. 当我们遍历这个数组 arr 后 , max 就是真正的最大值,maxIndex 最大值
// 对应的下标
int[] arr = {4,-1,9,10,23};
int max = arr[0];//假定第一个元素就是最大值
int maxIndex = 0; //
for(int i = 1; i < arr.length; i++) {//从下标 1 开始遍历 arr
if(max < arr[i]) {//如果 max < 当前元素
max = arr[i]; //把 max 设置成 当前元素
maxIndex = i;
}
}
//当我们遍历这个数组 arr 后 , max 就是真正的最大值,maxIndex 最大值下标
System.out.println("max=" + max + " maxIndex=" + maxIndex);
}
}
6.5 数组赋值机制
1)基本数据类型赋值,这个值就是具体的数据,而且相互不影响。
int n1 = 2; int n2 = n1;
2)数组在默认情况下是引用传递,赋的值是地址。
看一个案例,并分析数组赋值的内存图(重点, 难点. )。
//代码 ArrayAssign.java
int[] arr1 = {1,2,3};
int[] arr2 = arr1;
6.6 数组拷贝
public class ArrayCopy{
public static void main(String[] args) {
//将 int[] arr1 = {10,20,30}; 拷贝到arr2数组,
//要求数据空间是独立的
//
int arr1[] = {10,20,30};
//创建一个新的数组arr2,开辟新的数据空间
//大小 arr1.length;
int arr2[] = new int[arr1.length];
//遍历 arr1,把每个元素拷贝到对应的元素位置
for(int i = 0; i < arr1.length; i++){
arr2[i] = arr1[i];
}
//修改 arr2, 不会对 arr1 有影响.
arr2[0] = 100;
//输出 arr1
System.out.println("====arr1 的元素====");
for(int i = 0;i < arr1.length;i++){
System.out.println(arr1[i]);//10,20,30
}
//
System.out.println("====arr2 的元素====");
for(int i = 0; i < arr2.length; i++) {
System.out.println(arr2[i]);
}
}
}
6.7 数组反转
要求:把数组的元素内容反转。
arr {11,22,33,44,55,66} {66, 55,44,33,22,11}
方式 1:通过找规律反转 【思路分析】
public class ArrayReverse{
public static void main(String[] args) {
//定义数组
int arr1[] = {11,22,33,44,55,66};
//思路
//规律
//1. 把 arr[0] 和 arr[5] 进行交换 {66,22,33,44,55,11}
//2. 把 arr[1] 和 arr[4] 进行交换 {66,55,33,44,22,11}
//3. 把 arr[2] 和 arr[3] 进行交换 {66,55,44,33,22,11}
//4. 一共要交换 3 次 = arr.length / 2
//5. 每次交换时,对应的下标 是 arr[i] 和 arr[arr.length - 1 -i]
//代码
//优化
int temp = 0;
int len = arr.length; //计算数组的长度
for( int i = 0; i < len / 2; i++) {
temp = arr[len - 1 - i];//保存
arr[len - 1 - i] = arr[i];
arr[i] = temp;
}
System.out.println("===翻转后数组===");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");//66,55,44,33,22,11
}
}
}
方式 2:使用逆序赋值方式
public class ArrayReverse02 {
//编写一个 main 方法
public static void main(String[] args) {
//定义数组
int[] arr = {11, 22, 33, 44, 55, 66};
//使用逆序赋值方式
//思路
//1. 先创建一个新的数组 arr2 ,大小 arr.length
//2. 逆序遍历 arr ,将 每个元素拷贝到 arr2 的元素中(顺序拷贝)
//3. 建议增加一个循环变量 j -> 0 -> 5
int[] arr2 = new int[arr.length];
//逆序遍历 arr
for(int i = arr.length - 1, j = 0; i >= 0; i--, j++) {
arr2[j] = arr[i];
}
//4. 当 for 循环结束,arr2 就是一个逆序的数组 {66, 55, 44,33, 22, 11}
//5. 让 arr 指向 arr2 数据空间, 此时 arr 原来的数据空间就没有变量引用
// 会被当做垃圾,销毁
arr = arr2;
System.out.println("====arr 的元素情况=====");
//6. 输出 arr 看看
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}
6.8 数组添加/扩容
要求:实现动态的给数组添加元素效果,实现对数组扩容。
import java.util.Scanner;
public class ArrayAdd{
public static void main(String[] args) {
/*
要求:实现动态的给数组添加元素效果,实现对数组扩容。ArrayAdd.java
1.原始数组使用静态分配 int[] arr = {1,2,3}
2.增加的元素 4,直接放在数组的最后 arr = {1,2,3,4}
3.用户可以通过如下方法来决定是否继续添加,添加成功,是否继续?y/n
思路分析
1. 定义初始数组 int[] arr = {1,2,3}//下标 0-2
2. 定义一个新的数组 int[] arrNew = new int[arr.length+1];
3. 遍历 arr 数组,依次将 arr 的元素拷贝到 arrNew 数组
4. 将 4 赋给 arrNew[arrNew.length - 1] = 4;把 4 赋给 arrNew 最后一个元素
5. 让 arr 指向 arrNew ; arr = arrNew; 那么 原来 arr 数组就被销毁
6. 创建一个 Scanner 可以接受用户输入
7. 因为用户什么时候退出,不确定,老师使用 do-while + break 来控制
*/
Scanner scanner = new Scanner(System.in);
int arr[] = {1,2,3};
char answer = ' ';
do {
int[] arrNew = new int[arr.length + 1];
//遍历 arr 数组,依次将 arr 的元素拷贝到 arrNew 数组
for(int i = 0; i < arr.length; i++) {
arrNew[i] = arr[i];
}
System.out.println("请输入你要添加的元素");
int addNum = myScanner.nextInt();
//把 addNum 赋给 arrNew 最后一个元素
arrNew[arrNew.length - 1] = addNum;
//让 arr 指向 arrNew, arr = arrNew;
//输出 arr 看看效果
System.out.println("====arr 扩容后元素情况====");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
//问用户是否继续
System.out.println("是否继续添加 y/n");
char key = myScanner.next().charAt(0);
if( key == 'n') { //如果输入 n ,就结束
break;
}
}while(true);
System.out.println("你退出了添加...");
}
}
6.8.1 课后练习题
有一个数组 {1, 2, 3, 4, 5}, 可以将该数组进行缩减,提示用户是否继续缩减,每次缩减最后那个元素。当只剩下最后一个元素,提示,不能再缩减。
import java.util.Scanner;
public class ArrayReduce{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int arr[] = {1,2,3};
char answer = ' ';
do{
int arr1[] = new int[arr.length - 1];
for(int i = 0;i < arr.length - 1; i++){
arr1[i] = arr[i];
}
arr = arr1;
System.out.print("缩减成功,当前数组为");
for(int i = 0;i < arr.length;i++){
System.out.print(arr[i]);
}
System.out.print("是否继续缩减y/n");
answer = scanner.next().charAt(0);
if(answer == 'n'){
break;
}
if(arr.length == 1){
System.out.print("不能再缩减");
break;
}
}while(true);
}
}
6.9 排序的介绍
排序是将多个数据,依指定的顺序进行排列的过程。
排序的分类:
6.9.1内部排序:
指将需要处理的所有数据都加载到内部存储器中进行排序。包括(交换式排序法、选择
式排序法和插入式排序法);
6.9.2外部排序法:
数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。包括(合并排序法和直接合并排序法)。
6.10 冒泡排序法
冒泡排序(Bubble Sorting)的基本思想是:通过对待排序序列从后向前(从下标较大的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就象水底下的气泡一样逐渐向上冒。
6.11 冒泡排序法
冒泡排序法案例:
下面我们举一个具体的案例来说明冒泡法。我们将五个无序:24,69,80,57,13 使用冒泡排序法将其排成一个从小到大的有序数列。
public class BubbleSort {
//编写一个 main 方法
public static void main(String[] args) {
//化繁为简,先死后活
/*
数组 [24,69,80,57,13]
第 1 轮排序: 目标把最大数放在最后
第 1 次比较[24,69,80,57,13]
第 2 次比较[24,69,80,57,13]
第 3 次比较[24,69,57,80,13]
第 4 次比较[24,69,57,13,80]
*/
int[] arr = {24, 69, 80, 57, 13, -1, 30, 200, -110};
int temp = 0; //用于辅助交换的变量
//将多轮排序使用外层循环包括起来即可
//先死后活 =》 4 就是 arr.length - 1
for( int i = 0; i < arr.length - 1; i++) {//外层循环是 4 次
for( int j = 0; j < arr.length - 1 - i; j++) {//4 次比较-3 次-2次-1 次
//如果前面的数>后面的数,就交换
if(arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
System.out.println("\n==第"+(i+1)+"轮==");
for(int j = 0; j < arr.length; j++) {
System.out.print(arr[j] + "\t");
}
}
// for( int j = 0; j < 4; j++) {//4 次比较
// //如果前面的数>后面的数,就交换
// if(arr[j] > arr[j + 1]) {
// temp = arr[j];
// arr[j] = arr[j+1];
// arr[j+1] = temp;
// }
// }
// System.out.println("==第 1 轮==");
// for(int j = 0; j < arr.length; j++) {
// System.out.print(arr[j] + "\t");
// }
// /*
// 第 2 轮排序: 目标把第二大数放在倒数第二位置
// 第 1 次比较[24,69,57,13,80]
// 第 2 次比较[24,57,69,13,80]
// 第 3 次比较[24,57,13,69,80]
// */
// for( int j = 0; j < 3; j++) {//3 次比较
如果前面的数>后面的数,就交换
//if(arr[j] > arr[j + 1]) {
//temp = arr[j];
//arr[j] = arr[j+1];
//arr[j+1] = temp;
//}
//}
// System.out.println("\n==第 2 轮==");
// for(int j = 0; j < arr.length; j++) {
// System.out.print(arr[j] + "\t");
// }
// 第 3 轮排序: 目标把第 3 大数放在倒数第 3 位置
// 第 1 次比较[24,57,13,69,80]
// 第 2 次比较[24,13,57,69,80]
// for( int j = 0; j < 2; j++) {//2 次比较
// //如果前面的数>后面的数,就交换
// if(arr[j] > arr[j + 1]) {
// temp = arr[j];
// arr[j] = arr[j+1];
// arr[j+1] = temp;
// }
// }
// System.out.println("\n==第 3 轮==");
// for(int j = 0; j < arr.length; j++) {
// System.out.print(arr[j] + "\t");
// }
// /*
// 第 4 轮排序: 目标把第 4 大数放在倒数第 4 位置
// 第 1 次比较[13,24,57,69,80]
// */
// for( int j = 0; j < 1; j++) {//1 次比较
// //如果前面的数>后面的数,就交换
// if(arr[j] > arr[j + 1]) {
// temp = arr[j];
// arr[j] = arr[j+1];
// arr[j+1] = temp;
// }
// }
// System.out.println("\n==第 4 轮==");
// for(int j = 0; j < arr.length; j++) {
// System.out.print(arr[j] + "\t");
// }
}
}
//自己的方法
public class BubbleSort{
public static void main(String[] args) {
int a[] = {24,69,80,57,13};
int temp = 0;
for(int i = 0; i < a.length -1; i++){
for(int j = i + 1;j < a.length ;j++){
if(a[i] > a[j]){
temp = a[j];
a[j] = a[i];
a[i] = temp;
}
}
}
for(int i = 0; i < a.length; i++){
System.out.println(a[i]);
}
}
}
6.12 查找
6.12.1 介绍:
在 java 中,我们常用的查找有两种:
1)顺序查找 SeqSearch.java
2)二分查找【二分法,放在算法讲解】
6.12.2 案例演示(重点):
import java.util.Scanner;
public class SeqSearch {
//编写一个 main 方法
public static void main(String[] args) {
/*
有一个数列:白眉鹰王、金毛狮王、紫衫龙王、青翼蝠王猜数游戏:
从键盘中任意输入一个名称,判断数列中是否包含此名称【顺序查找】
要求: 如果找到了,就提示找到,并给出下标值
思路分析
1. 定义一个字符串数组
2. 接收用户输入, 遍历数组,逐一比较,如果有,则提示信息,并退出
*/
//定义一个字符串数组
String[] names = {"白眉鹰王", "金毛狮王", "紫衫龙王", "青翼蝠王"};
Scanner myScanner = new Scanner(System.in);
System.out.println("请输入名字");
String findName = myScanner.next();
//遍历数组,逐一比较,如果有,则提示信息,并退出
//这里老师给大家一个编程思想/技巧, 一个经典的方法
int index = -1;
for(int i = 0; i < names.length; i++) {
//比较 字符串比较 equals, 如果要找到名字就是当前元素
if(findName.equals(names[i])) {
System.out.println("恭喜你找到 " + findName);
System.out.println("下标为= " + i);
//把 i 保存到 index
index = i;
break;//退出
}
}
if(index == -1) { //没有找到
System.out.println("sorry ,没有找到 " + findName);
}
}
}
6.13 多维数组-二维数组
多维数组我们只介绍二维数组。
二维数组的应用场景
比如我们开发一个五子棋游戏,棋盘就是需要二维数组来表示。如图:
6.14 二维数组的使用
6.14.1 快速入门案例:
请用二维数组输出如下图形
0 0 0 0 0 0
0 0 1 0 0 0
0 2 0 3 0 0
0 0 0 0 0 0
public class TwoDimensionalArray01 {
//编写一个 main 方法
public static void main(String[] args) {
/*
请用二维数组输出如下图形
0 0 0 0 0 0
0 0 1 0 0 0
0 2 0 3 0 0
0 0 0 0 0 0
*/
//什么是二维数组:
//解读
//1. 从定义形式上看 int[][]
//2. 可以这样理解,原来的一维数组的每个元素是一维数组, 就构成二维数组
int[][] arr = { {0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0},
{0, 2, 0, 3, 0, 0},
{0, 0, 0, 0, 0, 0} };
//关于二维数组的关键概念
//(1)
System.out.println("二维数组的元素个数=" + arr.length);
//(2) 二维数组的每个元素是一维数组, 所以如果需要得到每个一维数组的值
// 还需要再次遍历
//(3) 如果我们要访问第 (i+1)个一维数组的第 j+1 个值 arr[i][j];
// 举例 访问 3, =》 他是第 3 个一维数组的第 4 个值 arr[2][3]
System.out.println("第 3 个一维数组的第 4 个值=" + arr[2][3]); //3
//输出二维图形
for(int i = 0; i < arr.length; i++) {//遍历二维数组的每个元素
//遍历二维数组的每个元素(数组)
//解读
//1. arr[i] 表示 二维数组的第 i+1 个元素 比如 arr[0]:二维数组的第一个元素
//2. arr[i].length 得到 对应的 每个一维数组的长度
for(int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " "); //输出了一维数组
}
System.out.println();//换行
}
}
}
6.14.2 使用方式 1: 动态初始化
1)语法: 类型[] []数组名=new 类型[大小] [大小]
2)比如: int a[] []=new int[2] [3]
3)二维数组在内存的存在形式(!!画图)
public class TwoDimensionalArray02 {
//编写一个 main 方法
public static void main(String[] args) {
//int arr[][] = new int[2][3];
int arr[][]; //声明二维数组
arr = new int[2][3];//再开空间
arr[1][1] = 8;
//遍历 arr 数组
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {//对每个一维数组遍历
System.out.print(arr[i][j] +" ");
}
System.out.println();//换行
}
}
}
6.14.3 使用方式 2: 动态初始化
先声明:类型 数组名[] [];
再定义(开辟空间) 数组名 = new 类型[大小] [大小]
赋值(有默认值,比如 int 类型的就是 0)
6.14.4 使用方式 3: 动态初始化-列数不确定(重要)
public class TwoDimensionalArray03 {
//编写一个 main 方法
public static void main(String[] args) {
/*
看一个需求:动态创建下面二维数组,并输出
i = 0: 1
i = 1: 2 2
i = 2: 3 3 3 一个有三个一维数组, 每个一维数组的元素是不一样的
*/
//创建 二维数组,一个有 3 个一维数组,但是每个一维数组还没有开数据空间
int[][] arr = new int[3][];
for(int i = 0; i < arr.length; i++) {//遍历 arr 每个一维数组
//给每个一维数组开空间 new
//如果没有给一维数组 new ,那么 arr[i]就是 null
arr[i] = new int[i + 1];
//遍历一维数组,并给一维数组的每个元素赋值
for(int j = 0; j < arr[i].length; j++) {
arr[i][j] = i + 1;//赋值
}
}
System.out.println("=====arr 元素=====");
//遍历 arr 输出
for(int i = 0; i < arr.length; i++) {
//输出 arr 的每个一维数组
for(int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();//换行
}
}
}
6.14.5 使用方式 4: 静态初始化
定义 类型 数组名[] [] = {{值 1,值 2..},{值 1,值 2..},{值 1,值 2..}}
使用即可 [ 固定方式访问 ]
比如:
int[] [] arr = {{1,1,1}, {8,8,9}, {100}};
解读
-
定义了一个二维数组 arr
-
arr 有三个元素(每个元素都是一维数组)
-
第一个一维数组有 3 个元素 , 第二个一维数组有 3 个元素, 第三个一维数组有 1 个元素
6.14.6 案例:
int arr={{4,6},{1,4,5,7},{-2}}; 遍历该二维数组,并得到和
public class TwoDimensionalArray05 {
//编写一个 main 方法
public static void main(String[] args) {
/*
int arr[][]={{4,6},{1,4,5,7},{-2}}; 遍历该二维数组,并得到和
思路
1. 遍历二维数组,并将各个值累计到 int sum
*/
int arr[][]= {{4,6},{1,4,5,7},{-2}};
int sum = 0;
for(int i = 0; i < arr.length; i++) {
//遍历每个一维数组
for(int j = 0; j < arr[i].length; j++) {
sum += arr[i][j];
}
}
System.out.println("sum=" + sum);
}
}
6.15 二维数组的应用案例(重要)
public class YangHui {
//编写一个 main 方法
public static void main(String[] args) {
/*
使用二维数组打印一个 10 行杨辉三角
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
规律
1.第一行有 1 个元素, 第 n 行有 n 个元素
2. 每一行的第一个元素和最后一个元素都是 1
3. 从第三行开始, 对于非第一个元素和最后一个元素的元素的值. arr[i][j]
arr[i][j] = arr[i-1][j] + arr[i-1][j-1]; //必须找到这个规律
*/
int[][] yangHui = new int[12][];
for(int i = 0; i < yangHui.length; i++) {//遍历 yangHui 的每个元素
//给每个一维数组(行) 开空间
yangHui[i] = new int[i+1];
//给每个一维数组(行) 赋值
for(int j = 0; j < yangHui[i].length; j++){
//每一行的第一个元素和最后一个元素都是 1
if(j == 0 || j == yangHui[i].length - 1) {
yangHui[i][j] = 1;
} else {//中间的元素
yangHui[i][j] = yangHui[i-1][j] + yangHui[i-1][j-1];
}
}
}
//输出杨辉三角
for(int i = 0; i < yangHui.length; i++) {
for(int j = 0; j < yangHui[i].length; j++) {//遍历输出该行
System.out.print(yangHui[i][j] + "\t");
}
System.out.println();//换行.
}
}
}
6.16 二维数组使用细节和注意事项
1)一维数组的声明方式有:
int[] x 或者 int x[]
2)二维数组的声明方式有:
int y 或者 int[] y[] 或者 int y[] []
3)二维数组实际上是由多个一维数组组成的,它的各个一维数组的长度可以相同,也可以不相同。比如: map[] [] 是一个二维数组
int map [] [] = {{1,2},{3,4,5}}
由 map[0] 是一个含有两个元素的一维数组 ,map[1] 是一个含有三个元素的一维数组构成,我们也称为列数不等的二维数组
6.17 二维数组课堂练习
6.18 本章作业
1)
2)
public class Homework04{
public static void main(String[] args) {
/*
思路 本质数组扩容 + 定位
1. 先确定 添加数应该插入到哪个索引
2. 然后扩容
*/
//先定义原数组
int arr[] = {10, 12, 45, 90};
int insertNum = 23;
int index = -1; // index就是要插入的位置
//遍历 arr数组,如果发现 insertNum<=arr[i],说明 i 就是要插入的位置
//使用index 保留 index = i;
//如果遍历完后,没有发现 insertNum<=arr[i],说明 index = arr.length
//即:添加到arr的最后
for(int i = 0; i < arr.length; i++){
if(insertNum <= arr[i]){
index = i;
break;
}
}
//判断index 的值
if(index == -1){ //说明没有找到位置
index = arr.length;
}
//扩容
//先创建一个新的数组,大小 arr.length + 1
int arrNew[] = new int[arr.length + 1];
//下面老师准备将arr的元素拷贝到 arrNew,并且要跳过 index位置
/*
分析:
int[]arr={10, 12,45,90};
arrNew = { }
*/
//i 控制arrNew的下标 ,j用来控制arr数组的下标
for(int i = 0, j = 0; i < arrNew.length; i++){
if( i != index ){//说明可以把arr的元素拷贝到arrNew
arrNew[i] = arr[j];
j++;
}else{ //i这个位置就是要插入的数
arrNew[i] = insertNum;
}
}
//让arr 指向 arrNew, 原来的数组, 就成为垃圾被销毁
arr = arrNew;
System.out.println("====插入后,arr数组的元素情况====");
for(int i = 0; i < arr.length; i++){
System.out.print(arr[i] + "\t");
}
}
}
3)
public class Homework05{
public static void main(String[] args) {
/*
随机生成10个整数(1_100的范围)保存到数组
并倒序打印以及求平均值、求最大值和最大值的下标
并查找里面是否有 8
*/
int arr[] = new int[10];
//(int)(Math.random() * 100) + 1生产 随机数 1-100
for(int i = 0; i < arr.length; i++){
arr[i] = (int)(Math.random() * 100) + 1;
}
System.out.println("====arr的元素情况====");
for(int i = 0;i < arr.length; i++){
System.out.print(arr[i] + "\t");
}
System.out.println();
System.out.println("====arr的元素情况====");
for(int i = arr.length -1;i > 0; i--){
System.out.print(arr[i] + "\t");
}
//平均值、求最大值和最大值的下标
//
double sum = arr[0];
int max = arr[0];
int maxIndex = 0;
for(int i = 1; i < arr.length; i++){
if(max < arr[i]){//说明max不是最大值,就变化
max = arr[i];
maxIndex = i;
}
sum += arr[i];
}
System.out.println("max=" + max + "平均值等于" + (sum / 10) + "最大值的下标" + maxIndex);
//查找数组中是否有 8-> 使用顺序查找
int findNum = 8;
int index = -1;//如果找到,就把下标记录到 index
for(int i = 0; i < arr.length; i++){
if(findNum == arr[i]){
System.out.println("找到数字" + findNum + "下标=" + i);
index = 1;
break;
}
}
if(index == -1){
System.out.println("未找到" + findNum);
}
}
}
4)
public class Homework07{
public static void main(String[] args) {
//冒泡排序
//要求从小到大
int arr[] = {20, -1, 89, 2, 890, 7};
for(int i = 0; i < arr.length - 1; i++){
for(int j = 0; j < arr.length - 1 - i; j++){
int temp = 0;
//如果是从小到大,条件是 arr[j]>arr[j+1]
//如果是从大到小,条件是 arr[j]<arr[j+1]
if(arr[j] > arr[j + 1]){
temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
for(int i = 0; i < arr.length; i++){
System.out.println(arr[i] + "\t");
}
}
}