Java SE
一、Java SE 基础
1.变量
变量在作用域范围内才可以使用
变量名不允许重复定义
一条语句可以定义多个变量
变量在使用之前一定要进行赋值
2.标识符
* 作用:给类、变量、方法等取名字的符号单词
* 命名规则:
可以由数字、字母、下划线(_)和美元符($)其中一种或多种组成
不能以数字开头
不能是关键字或特殊直接量(true,flase,null)
* 区分大小写
* 注意:不需要记忆规则,使用idea自动检查即可
3.基本数据类型的分类和使用
整数型
byte:1个字节,范围-128~127
short:2个字节
int:4个字节
long:8个字节
浮点型:
float:4个字节
double:8个字节
字符型
char:2个字节
布尔型
boolean:1个字节,就两个值true和false
4.switch语句
5.String
Java概述
Java语言背景介绍
问题:
1.什么是计算机语言,学习它有什么作用?
2.java语言的创始人是谁,在哪一年发布的呢?
3.java目前分为几个平台版本,我们学习的是哪些版本?
4.JavaEE主要是用于什么方向的开发?
Java语言介绍
Java语言的三个版本
Java跨平台原理
问题:
1.对于跨平台,这个平台指的是什么呢?
2.java程序是如何做到能够在不同的操作系统上运行的呢?
3.不同平台上的JVM虚拟机是一样的吗?
JRE和JDK
问题:
1.开发一个java程序的三个步骤是什么?
2.什么是java类,有什么作用?
3.在JRE中提供核心类库,有什么意义呢?
4.JVM、JRE、JDK之间具有什么关系?
JRE:Java Runtime Environment,java运行环境,包含JVM虚拟机及Java核心类库,是java语法能够被使用的前提
JDK:Java Development Kit,java软件开发工具包,内部包含了代码的编译工具(javac.exe)和运行工具(java.exe)
开发Java程序的三个步骤
课后练习
JDK的下载和安装
问题:
1.安装jdk,能否安装在中文路径的文件夹下?
2.jdk的版本这么多,我们基础班学习,选择使用哪个版本?
3.怎么判断jdk已经安装成功了?
4.jdk根目录下的bin目录中主要是存放什么文件的?
Java语言的发展史
JDK的下载和安装
JDK的安装目录(根目录介绍)
第一个程序
常用DOS命令
问题:
1.打开DOS命令提示符操作窗口的步骤是什么?
2.常用的DOS命令有哪些,分别具有什么功能?
3.如何快速的进入某个文件所在目录的对应DOS环境中?
学习DOS命令意义
打开DOS的方式想·
常用DOS命令
命令补充
命令 说明
mkdir 文件夹名 创建一个文件夹
rmdir [/s] 文件夹名 删除一个[非空]文件夹
del 文件名 删除文件
cd.>要新建的文件名 创建一个空白文件
rename 要重命名的文件名 重命名之后的文件名 修改一个文件的文件名
move 被移动的文件 要移动到的位置[\移动后的文件名] 剪切一个文件到指定路径下,也可以更改剪切后的文件名
copy 被复制的文件 要复制到的位置[\复制后的文件名] 复制一个文件到指定路径下,也可以更改复制后的文件名
快速进入bin目录所在的DOS命令提示符
Path环境变量的配置
问题:
1.安装jdk之后,为什么要配置Path环境变量?
2.配置环境变量时,变量JAVA_HOME的值是什么?
3.Path变量的配置,是在用户变量中还是在系统变量中?
4.如何校验jdk的path环境变量是否配置成功?
配置Path环境变量的意义
可以在任意目录下,都能访问到bin目录中的javac和java工具
Path环境变量的配置
找到桌面上计算机图标,鼠标右击,选择属性
找到高级系统设置,一般在左上方
选择高级、环境变量
在系统变量中新建一个变量
变量名是:JAVA_HOME,变量值是jdk的根目录地址,点击确定
再到系统变量框里找到path变量,编辑它
在path变量的编辑框中,点击新建,然后输入:%JAVA_HOME%\bin
需要注意的是,如果path变量框是上面的样式,是不需要加分号结束的
但如果是下方的样式,那么输入%JAVA_HOME%\bin;是需要带分号结束
设置好之后,需要一直点击确定结束
验证path环境变量是否配置成功,需要重新打开一个dos命令行窗口界面验证,不能使用原有的窗口
在dos命令行窗口分别输入java -version,java,javac三个命令验证
HelloWorld案例详解
问题:
1.书写Java代码时,class这个单词是用来干什么的?
2.一个Java程序能不能没有main主方法?
3.代码System.out.println(“学习Java的人不是帅哥,就是美女!”);的作用是什么?
4.class前面的public这个单词,有什么作用?
一个java程序,有且仅有一个main方法,属于固定写法
类名必须和文件名保持一致,因为类名前面有public修饰
HelloWorld程序说明:
IDEA的安装和使用
IDEA的概述和安装
概述
IDEA全程是IntelliJ IDEA,是用于Java语言开发的集成环境,它是业界公认的目前用于Java程序开发最好的工具。
集成环境:把代码编写、编译、运行、调试等多种功能综合到一起的开发工具
下载和安装
下载:https://www.jetbrains.com/idea/download/other.html
安装:双击下一步即可,注意不要安装在中文路径下
IDEA中的项目结构
Idea项目结构介绍
小结
IDEA中的第一个代码
操作步骤(2021版):
创建Project(项目)
创建Module(模块)
project创建好之后,会自动弹出创建module的窗口
如果不通过自动弹出的创建module窗口创建,也可以在project的界面中操作
配置Module
创建Package(包)
创建class(类)
编写代码,运行程序
IDEA常用快捷键
//psvm: 一键生成主方法
//sout: 生成输出语句
//ctrl+alt+L: 格式化代码
//alt+Enter: 代码修正提示
//ctrl+/: 添加(取消)单行注释
//ctrl+shift+/ : 添加(取消)多行注释
//ctrl+D : 复制当前行的代码
//ctrl+X : 剪切
//ctrl+V : 粘贴
//alt+1: 打开/隐藏项目结构
//alt+4: 打开/隐藏控制台
//fori : 10次的for循环
IDEA操作模块
删除模块
导入模块
直接通过project界面导入已存在的module
通过Project structure设置导入module
最后就是一直选择next下一步即可
IDEA打开、关闭项目-类名、包名修改
关闭项目
打开项目
如果列表中要打开的项目已被移除:
修改类名
修改包名
基础语法
注释
问题:
1.什么是注释,程序当中的注释有什么作用?
2.java中注释分为几类,分别是什么?
3.注释会不会影响程序的编译和运行?
注释的概述
注释的分类
//练习:给HelloWorld程序添加注释
//这是一个类,类的名字叫A
public class A{
/*
这是程序的主方法,一个java程序有且仅有一个main方法。
*/
public static void main(String[] args){
//这是一个在控制台打印输出内容的语句,小括号中是输出的内容。
//在控制台输出自己的姓名、对喜欢的人想说的话
System.out.println(“好棒哦,notepad真给力”);
}
}
基础语法
关键字
问题:
1.java中的“关键字”是什么?
2.Java中的“关键字”有哪些特点?
3.main方法中的名字“main”是不是关键字?
字面量
问题:
1.Java中的字面量有哪几种类型?
2.'10’这个数据在Java中属于字符字面量吗?
3.能不能使用打印语句去打印空字面量?
字面量的分类:
变量
3.1 变量概述
概念:在程序运行期间,其值可以发生改变的量。
理解:变量就是内存中的存储空间,空间中存储着经常发生改变的数据
定义格式
变量的使用(变量名进行使用)
//练习
//定义一个int类型的变量,并且赋值为18
//使用变量,将变量中的数据打印出来
//再次给变量赋值,替换之前的数据
//再次打印该变量
内存图变化
第一步:
第二步:
3.2 变量的注意事项
数据类型
问题:
1.Java中的数据类型有几种?
2.Java中数据类型的转换方式有几种?
4.1 类型分类
Java的数据类型
基本数据类型分类
案例
//练习:在下面输出语句的后面添加注释,标明打印内容分别属于什么数据类型
System.out.println(‘1’);//
System.out.println(520);//
System.out.println(3.14);//
System.out.println(0.618F);//
System.out.println(5201314L);//
System.out.println(false);//
4.2 类型转换
隐式转换
概念:将数据类型中取值范围小的数值或变量,给取值范围大的类型赋值。直接赋值。
int xiao=10;
//int的取值范围比double小,所以可以给double类型直接赋值
double da=xiao;
//总结:小的给大的,天经地义
1.总结:
//举例:200ml的可乐导入1L的瓶子,直接倒水,不会‘溢出’。所谓的数据类型转换就是不同类型的杯子中装水,怎么装更合适。
2.举例:
数据类型范围从小到大排序
隐式转换的细节
不同数据类型进行运算,小的数据类型会提升为大的之后,再参与运算
//买早餐案例
//买包子,2元,int类型收
int baoZi = 2;
//买了个鸡蛋,1.5元,double类型接收
double egg = 1.5;
//小类型的baoZi和大类型的鸡蛋相加,包子提升成double类型参与运算:double+double
double zaoCan=baoZi+egg;
特殊关注:byte、short、char(比int类型范围小的)三种数据进行运算的时候,不管是否有更高的数据类型,都会提升为int,再参与运算
//案例1:byte+short
byte b=10;
short s=29;
//分析:byte+short -> int +int -> int
int num1=m+s;
//自案例
//案例2:byte+char
char c=‘a’;
//分析:byte+char -> int+int -> int
int num2=b+c;
//案例3:byte+short+double
double d=3.14;
//分析:byte+short+double -> int+int+double -> double+double+double -> double
double num3=b+s+d;
强制转换
概念:把一个表示数据范围大的数值或变量赋值给另一个表示数据范围小的变量
格式:目标数据类型 变量名 = (目标数据类型) 值或变量;
//案例1:
int a=10;
//byte b=a; //编译报错:错误,不兼容的类型,从int转换到byte可能会有损失(精度损失)
//利用强转格式解决
byte b=(byte)a;
精度损失
//案例1:浮点数强转成整数
//给定一个变量为double类型
double d=520.1314;
//给定一个变量为int类型,比double类型范围小,强制数据类型转换
int i=(int)d;
System.out.println(a);//结果:520
//思考:是否遵循四舍五入?
//double类型变量重新复制
d=0.618;
//再次强转
i=(int)d;
System.out.println(a);//结果:0
//结论:小数强转成整数,会直接舍掉小数部分
//案例2:大整数强转成小数
//给定一个变量为int类型
int num1=520;
//强转byte类型,注意byte取值范围:-128~127
byte num2=(byte)num1;
System.out.println(num2);//结果:8
//思考:byte类型最大值为127,为什么结果是8?
精度损失的原因
标识符
问题:
1.什么是标识符,有什么作用?
2.标识符的定义规则是什么?
3.标识符常见的命名规定有哪些?
概述:给类、变量、方法等起名字的符号
硬性规则(必须得遵守,不遵守,程序就报错):
//合法标识符
age
L_ni3
$get
//非法标识符
7shang8xia //不能以数字开头
&abc //&不属于标识符的组成
class //不能是关键字
常见命名规定(软性规则)
//练习1:以下哪些变量的命名是符合标识符规则的?在注释后面标注
String name=“张三”;//
int age=17;//
int do=23;//
double π=3.14;//
char d o l l a r = ′ dollar=' dollar=′';//
char 86RMB=‘¥’;//
//练习2:使用大驼峰或小驼峰式进行命名
//2.1 定义一个类名,该类用来表示一个学生
//2.2 定义一个变量名,用来代表人的年龄
//2.3 定义一个变量名,用来代表学生的学号
//2.4 定义一个类名,用来代表第一个变量练习的类
键盘录入
导包:需要在class的上面写
创建Scanner对象,只有sc可以变,其他是固定格式
使用变量接收键盘录入的数据,变量名num可以变,其他固定格式
使用键盘录入的数据,这里是打印数据
//练习:利用键盘录入,在控制台录入自己的座右铭,并打印
运算符
运算符和表达式
案例
int a=10;
int b=20;
int c=a+b;
// + 是算数运算符,a+b 是表达式,也叫算术表达式。
种类
案例
//案例1:+、-、*
int a=2;
int b=3;
// + 运算
int num1=a+b;
// - 运算
int num2=a-b;
// * 运算
int num3=a*b;
System.out.println(num1);
System.out.println(num2);
System.out.println(num3);
//案例2:/
//整数除法
System.out.println(10/2);//结果:5
System.out.println(10/3);//结果:3
//分析:10/3 -> int/int -> int。 所以小数部分直接省去。
//要得到小数,表达式中得有小数
System.out.println(10.0/3);
System.out.println(10/3.0);
//案例3:%
//求10除以3的余数: 10 / 3 = 3 ······ 1
System.out.println(10%3);//结果:1
//案例4:混合运算
int a=2;
byte b=3;
char c=‘a’;
System.out.println(c+a*b);
//类型分析:char+int+byte -> int+int+int -> int
//顺序分析:先乘后减
//结果:字符怎么加!!! 提升成int是多少呀?
//试着编译:不报错!
计算机底层所有的数据都是二进制数字,字符也不例外。我们使用电脑能看到的文字都是一个个的字符组成的。那这些字符应该用哪些二进制数字表示呢?如果每个国家都不一样,数据在互联网上就很难在国际上流通了。
所以老美就搞了这么一个标准,大家都共同遵守。
常用的字符码表对照
运算过程
char类型在参与数学运算的时候,先查找码表中对应的数字,再参与运算
char c=‘a’;
System.out.println(c+1); //结果:98
概述:字符串的“+”操作不是算数运算,而是字符串拼接运算。
特点:在“+”操作的时候,如果出现了字符串,“+”就是连接运算符。当连续进行“+”操作时,从左往右逐个进行。
//案例1:
//做一行爱一行
System.out.println(“Java”+520+1314);
//挑几个我喜欢的数字,我喜欢高一点的女孩子,175…
System.out.println(175+120+66+103+56+“Hello”);
个位数:数值 / 10的0次方 % 10;
十位数:数值 / 10的1次方 % 10;
百位数:数值 / 10的2次方 % 10;
千位数:数值 / 10的3次方 % 10;
…
//需求:键盘录入一个三位数,将其拆分为个位、十位、百位后,打印在控制台
//1. 使用Scanner键盘录入一个三位数
//1.1 导入Scanner包:import java.util.Scanner;
import java.util.Scanner;
public class Test{
public static void main(String[] args){
//1.2 创建Scanner对象
Scanner sc = new Scanner(System.in);
//1.3 提示用户键盘录入
System.out.println(“亲,请输入一个三位数哦:”);
//1.4 键盘录入数字
int num = sc.nextInt();
//2. 计算个位数:数值 % 10
int ge = num % 10;
//3. 计算十位数:数值 / 10 % 10
int shi = num / 10 % 10;
//4. 计算百位数:数值 / 100
int bai = num / 100;
//5. 假设输入的数字是520,打印内容:整数520的个位为:0,十位为2,百位为:5
//5.1 分析:字符串拼接操作
System.out.println(“整数” + num + “的个位为:” + ge + “,十位为” + shi + “,百位为:” + bai);
}
}
大家都玩微信吧?如果有朋友给你发消息,如果你没看,每发一条消息,红点的消息记录就多一条。说明微信有个程序一直再计数,每次增加1。
System.out.println("女神:在吗?我有事跟你说");
//定义一个int类型的变量记录未读消息数
int count = 1;
System.out.println("---您有" + count + "条未读消息---");
System.out.println("女神:我怀孕了");
count = count + 1;
System.out.println("---您有" + count + "条未读消息---");
System.out.println("女神:可能不是你的,但我还是爱你的");
count = count + 1;
System.out.println("---您有" + count + "条未读消息---");
System.out.println("女神:我想和你结婚,尽快");
System.out.println("开启了好友人认证,你还不是他的好友。请先发送好友申请...");
//问题:每次count都得加1再赋值给自己,特别麻烦,有没有更简单的方法呢?利用java的自增运算符就可以简化
注意事项:
案例演示
//案例1:单独使用
int count=0;
//在前
++count;
System.out.println(count);//结果:1
count++;
System.out.println(count);//结果:2
//无区别,都是自己的值加1
//案例2:参与运算
int num=1;
//在前:
int result=--num;//赋值也算参与运算
System.out.println(result);//结果:0
System.out.println(num);//结果:0
//在后:
result=num--;
System.out.println(result);//结果:0
System.out.println(num);//结果:-1
//操作常量
++520//编译报错
520--//编译报错
总结
自增自减最后都要给自己加1或者减1,然后会给自己赋值。当然这个赋值运算省略了。说道到赋值,在java中我们已经知道了=是赋值运算符,那除了=之外,还有没有其他的赋值运算符呢?这里可以告诉大家,还有5种赋值运算符。
介绍
案例演示
案例1:加后赋值
int a=24;
int b=2;
a+=b;// a=a+b;
System.out.println(a);
案例2:减后赋值
a-=b;// a=a-b;
System.out.println(a);
案例3:乘后赋值
a*=b;// a=a*b;
System.out.println(a);
案例4:除后赋值
a/=b;// a=a/b;
System.out.println(a);
案例4:取余后赋值
a/=5;// a=a%5;
System.out.println(a);
注意事项:扩展的赋值运算符隐含了强制类型转换
//案例1
int a=23;
byte b=12;
b=a+b; //编译报错
//分析:int+byte -> int+int -> int。int不能直接赋值给byte
System.out.println(b);
//案例2:扩展的赋值运算符
int a=23;
byte b=12;
b+=a;//编译通过
//分析:b+=a -> b=(b的数据类型)(b+a) -> byte=(byte)(byte+int) -> byte=byte
System.out.println(b);
在java中,普通的赋值运算符是用=号表示,所以以后int a=23;的实际读法,应该是把23赋值给了int类型的a。话说到这,如果我不是做赋值,就是要判断相等呢?=号都被占用了,哪个符合能用作判断相等的操作呢?
介绍
关系运算符是用来判断两个变量(常量、表达式)之间的关系,比如相等关系、不等关系和大小关系。
运算结果都是布尔值,要么是true,要么是false。
代码演示
//案例1:操作变量
int a=23;
int b=12;
System.out.println(a>b);//结果:true
//案例2:操作常量
System.out.println(3<2);//结果:false
//案例3:操作变量和常量
System.out.println(a>=3);//结果:true
//案例4:操作表达式
int num1 = 5;
System.out.println(num1 * 2 + 1 != 11);//结果:false
国家开始推新冠疫苗啦,让全民接种。但是不是所有人都能打的,在年龄上有限制。规定是只给18~59岁的人群注射。
//定义一个变量,代表要接种疫苗的人,叫小明
String name="小明";
//小明今年14岁
int age=14;
//筛选,结果是true就能打,否则不能打
boolean result= 18<=age<=59; //编译报错,不允许这么写。
//如果不能一次性写,那就得写两行代码,在java中,能不能一次判断完呢?
介绍
作用:用于连接多个比较表达式的条件,得到最终的结果是个布尔值
代码案例
//案例1:操作变量
//有房
boolean fang = true;
//没车
boolean che = false;
//&:左右两边都是true,结果才是true。 要求高
System.out.println(fang & che);//结果:false
//|:左右两边有一个为true,结果就是true。要求低
System.out.println(fang | che);//结果:true
//案例2:操作变量和常量
System.out.println(fang & false);//结果:false
System.out.println(fang & true);//结果:true
System.out.println(che | true );//结果:true
//案例3:操作常量
System.out.println(true & false);//结果:false
System.out.println(false | true);//结果:true
// ^:左右两边的值不一样,结果才是true
System.out.println(true ^ true);//结果:false
System.out.println(false ^ true);//结果:true
//案例4:操作表达式
//今年18岁
int age = 18;
//年龄必须在18到59岁才能打疫苗
System.out.println(age >= 18 & age <= 59);//结果:true
介绍
与运算:
或运算:
代码演示
//案例1:&&的短路效果
int a=3;
int b=4;
System.out.println(a>3&&++b>4);
//分析:a>2的结果是false,所以&&后面不执行。b没有做自增运算
System.out.println(“b:”+b); //结果:4
//案例2:||的短路效果
int num1=3;
int num2=4;
System.out.println(num1>2||num2–<4);
//分析:num1>2的结果是true,所以||后不执行,num2没有做自减运算
System.out.println(“num2:”+num2); //结果:4
格式:关系表达式 ? 表达式1:表达式2;
执行流程:
代码演示
//案例1:求两个变量中的最大值
int a=28;
int b=18;
//分析:先让看a是否大于b,如果a大于b,则a是最大值,将a的值赋值给变量max,否则就是b赋值给max
int max=a>b?a:b;
System.out.println(“最大值是:”+max);
//注意事项:表达式1和表达式2最终结果的数据类型必须一致。为什么?如果不一致,三元运算符最后的要赋值的话,拿什么数据类型接收?是不是就无法确定了?
分支语句
介绍:java代码的默认执行流程:从上到下,从左往右
代码案例
//案例
//从上往下
System.out.println(“我是黑马程序员”);
System.out.println(“我的目标是月薪过万”);
System.out.println(“前提是要努力学习,键盘敲烂”);
//从左往右
System.out.println(“高薪就业!”+“人生巅峰!”+“迎娶白富美!”);
2.1 第一种格式
格式
…
if(关系表达式){
语句体;
}
…
//执行流程
//1. 首先计算关系表达式的值,这个结果只能是布尔值
//2. 如果关系表达式的值为true,就执行语句体
//3. 如果关系表达式的值为false,就不执行语句体
//4. if语句结束,继续执行后面的代码内容
代码案例
//案例1:小明上网
System.out.println(“今天是周末,天气真好,小明出门玩耍”);
//定义一个int类型变量,代表小明的年龄
int age=19;
System.out.println(“看到了一间网吧,准备进去玩两把”);
System.out.println(“网管问:你成年了吗?”);
//使用if语句进行判断
if(age>=18){
System.out.println(“小明说:我成年了”);
System.out.println(“领卡、卡机、五连跪”);
}
System.out.println(“小明转身回家”);
注意事项
2.2 第二种格式
格式
…
if(关系表达式){
语句体1;
} else {
语句体2;
}
…
//执行流程
//1. 首先计算关系表达式的值,这个结果只能是布尔值
//2. 如果关系表达式的值为true,就执行语句体1
//3. 如果关系表达式的值为false,就不执行语句体2
//4. if语句结束,继续执行后面的代码内容
代码案例
//案例1:判断一个数是奇数还是偶数
//给定一个待判断的整数
int num=23;
//开始进行判断
//寻找奇数的规律,偶数可以被2整除,意味着偶数对2取余数的结果是0,这个就可以作为判断的条件
if(num % 2==0){
System.out.println(“偶数”);
}else{
System.out.println(“奇数”);
}
//案例2:判断两个数谁是最大值
int num1=5;
int num2=3;
//三元运算的方式
int max= num1>num2?num1:num2;
//利用if-else完成
//谁最大,需要判断num1是否大于num2,这就可以作为一个条件
if(num1>num2){
System.out.println(“最大数是:”+num1);
}else{
System.out.println(“最大数是:”+num2);
}
2.3 第三种格式
格式
…
if(关系表达式1){
语句体1;
} else if(关系表达式2) {
语句体2;
} else if
…
} else {
语句体n+1;
}
…
//执行流程
//1. 首先计算关系表达式1的值,这个结果只能是布尔值
//2. 如果关系表达式1的值为false,就执行关系表达式2
//3. 如果关系表达式2的值为false,就执行关系表达式3
//4. …
//5. 有任何关系表达式的值为true,就执行对应的语句体
//6. 如果没有任何关系表达式的值为true,就执行语句体n+1
代码案例
/**
2.4 案例:考试奖励
//需求:键盘录入学生考试成绩,根据成绩,程序给出不同的奖励
//思路:
//1. 考试成绩未知,需要用键盘录入,拿到考试成绩
//1.1 导入Scanner包,在代码的最上方第一行
import java.util.Scanner;
//1.2 创建Scanner对象
Scanner sc=new Scanner(System.in);
//1.3 提示用户键盘录入成绩
int score=sc.nextInt();
//2. 判断录入的学生成绩是否在合法范围之内
if(score>=0&&score<=100){
//合法成绩
//3. 在合法的if块中,判断成绩范围
if(score>=95&&score<=100){
//4. 为每种判断设置对应的奖励
System.out.println("奖励自行车一辆");
} else if(score>=90&&score<=94){
System.out.println("奖励游乐场玩一次");
} else if(score>=80&&score<=89){
System.out.println("奖励变形金刚一个");
} else {
System.out.println("挨顿揍,这个城市又多了一个伤心的人");
}
//注意,下面这个else是外层判断输入成绩是否合法对应if结构,不是内层的。
}else{
//非法成绩
System.out.println("您输入的成绩有误");
}
3.1 格式和执行流程
格式
switch(表达式){
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
…
case 值n:
语句体n;
break;
default:
语句体n+1;
break;
}
/**
/**
注意事项
3.2 case穿透
注意:在switch语句中,如果case控制的语句体后面不写break,将出现穿透现象;
现象:当开始出现case穿透,后续的case就不会具有匹配效果,内部的语句不会结束,继续向下执行。直到看到break,或者将整个switch语句执行完毕,switch才会结束
应用:当发现switch语句中,多个case给出的语句体出现重复的时候,就可以考虑使用case穿透来优化代码
//案例:键盘录入112,代表当前月份。其中35是春季,68是夏季,911是秋季,12~2是冬季。
//1.使用Scanner键盘录入
//1.1 导包
import java.util.Scanner;
public class Test03 {
public static void main(String[] args) {
//1.2 创建Scanner对象
Scanner sc = new Scanner(System.in);
//1.3 提示用户键盘录入,防止程序要开始录入的时候,用户不知道
System.out.println(“请输入当前月份”);
//1.4 开始键盘录入选择,并用int类型的变量season接收键盘录入的数字值
int season = sc.nextInt();
//2.根据录入的数字值,匹配不同的月份
switch (choice) {
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(“您输入的月份有问题哦!”);
break;
}
}
}
循环语句
循环:重复做某件事情,具有明确的开始和停止标记
1.1 格式和执行流程
格式
for(初始化语句;条件判断语句;条件控制语句){
循环体语句;
}
//执行流程
//1.执行初始化语句
//2.执行条件判断语句,看起结果是true还是false。
//3.如果是false,循环结束
//4.如果是true,继续执行循环体语句
//5.循环体语句执行结束,执行条件控制语句
//6.回到第二步继续
代码演示
1.2 案例:输出数据15和51
思路分析:
打印1~5:
打印5~1:
代码演示
//打印1~5
//打印的动作是重复的,所以必须把输出语句放到循环内部
//重复5次,并且是从1开始打印,那么就要控制变量在1,2,3,4,5都能取到
for(int i=1;i<=5;i++){
System.out.println(i);
}
//打印5~1
//同上,只是打印从5开始,变量的值取5,4,3,2,1,依次递减
for(int i=5;i>=1;i–){
System.out.println(i);
}
//思考:如何只利用一个循环解决?
//分析:总共循环打印10次,可以先让变量取到1~10
for(int i=1;i<=10;i++){
//如果仅仅是直接打印i的值,则无法打印51,打印的是610
//System.out.println(i);
//所以不能直接打印i,必须加条件限制,只有当i<=5的时候可以直接打印
if(i<=5&&i>=1){
System.out.println(i);
}
//如果只有上面的条件限制,则无法阻挡610的打印,思考610和5~1之间的关系
//11-6=5,11-7=4,11-8=3,11-9=2,11-10=1
//找到规律,可以开始判断条件,当i取6~10的时候如此操作
if(i<=10&&i>=6){
System.out.println(11-i);
}
}
1.3 案例:求1~5数据和
思路分析
代码演示
//定义一个int类型的变量,专门用来接收求和的值,一开始没有任何值,所以是0
int sum=0;
//因为是求15的和,所以要保证能取到15这几个数字,并且求和的话是加了5次,所以循环也能控制成5次
for(int i=1;i<=5;i++){
//每次相加,都是拿累计好的值加新取到的1~5的值,累计值是由sum表示,所以是拿sum和i相加
//sum+i;
//加完之后,累计值要改变,所以还得赋值回给sum
//sum=sum+i;
//这种自己加某个值再赋值给自己的操作,可以使用扩展赋值运算符搞定
sum+=i;
}
//循环结束,可以确定i的每个值都取到了,并且加过了,这个时候的sum已经是最后的结果
System.out.println(“1-5之间的数据和是:”+sum);
1.4 案例:求1~100偶数和
思路分析
代码演示
//分析:要取到1~100的值,数字有100个,那么得循环100次
//定义一个变量,做累计相加的值的容器
int sum=0;
for(int i=1;i<=100;i++){
//这100个数字,不是所有数字都是偶数,什么样的数字才能被称为偶数?一个数被2整除,没有余数就是偶数
if(i%2==0){
//满足条件的i才会进来,此时i就是偶数,利用上一个案例的知识,可以在此处累计相加
sum+=i;
}
}
//循环结束,就可以打印sum的值
System.out.println(“1-100之间的偶数和是:”+sum);
1.5 案例:水仙花数
水仙花数
思路分析
代码演示
//1. 通过循环能获得100~999这所有的数
for(int i=100;i<=999;i++){
//针对当前i的值,i一定是三位数,所以要拆分成个位、十位、百位
//2.分别定义变量代表个位、十位、百位
int ge=i%10;
int shi=i/10%10;
int bai=i/100;
//3.水仙花数的条件就是:个位数的三次方+十位数的三次方+百位数的三次方等于原来的数
if(gegege+shishishi+baibaibai==i){
//4.满足条件的数就是水仙花数,可以打印
System.out.println(“水仙花数:”+i);
}
}
1.6 案例:每行打印2个水仙花数(统计)
需求分析
代码实现
//1. 通过循环能获得100~999这所有的数
//2. 定义一个变量,记录打印了多少个数,定义的时候还一个都没有打印,所以初始值是0
int count=0;
for(int i=100;i<=999;i++){
//针对当前i的值,i一定是三位数,所以要拆分成个位、十位、百位
//3.分别定义变量代表个位、十位、百位
int ge=i%10; 521-------1
int shi=i/10%10; 521—52—2
int bai=i/100; 521------5
//4.水仙花数的条件就是:个位数的三次方+十位数的三次方+百位数的三次方等于原来的数
if(gegege+shishishi+baibaibaii){
//5.满足条件的数就是水仙花数,打印的时候注意,第一不要换行,第二要留一个空格隔开
System.out.print(i+" ");
//6.每打印一个数字,count的值就得记录1次,值要加1
count++;
//7.此时就应该马上判断打印了多少个数字,如果是偶数,马上就要开始换行了
//8.判断一个数是否是偶数,只需要对2取余数是0就可以了
if(count%20){
//9.仅仅换行,不打印
System.out.println();
}
}
}
2.1 格式和执行流程
格式
//基本格式
while(条件判断语句){
循环体语句;
}
//完整格式
初始化语句;
while(条件判断语句){
循环体语句;
条件控制语句;
}
//执行流程
//1.执行初始化语句;
//2.执行条件判断语句,看结果是true还是false
//3.如果是false,循环结束。如果是true,则继续执行循环体语句
//4.执行条件控制语句
//5.若循环内部没有使用特殊关键字结束循环,则回到第2步继续
代码案例
//案例:打印999次“我爱你的第X天”
//1.有记录次数,并且循环的次数和记录的次数相关,所以初始化语句就可以定义一个int类型的变量
int count=1;
//2.开始循环,当count值一直小于等于999次的时候,就还可以打印
while(count<=999){
System.out.println(“我爱你的第”+count+“天”);
//每打印1次,count的次数就得加1
count++;
}
注意事项
//1.while后面的小括号后,千万不要写分号,例如
int count=1;
//1.1小括号后面马上接分号,代表没有循环体语句,后面的大括号部分就不属于while循环的范围
//1.2这就会导致count的值一直无法执行到自加操作,会一直满足count<=999,而出现程序卡死的情况
while(count<=999);
{
System.out.println(“我爱你的第”+count+“天”);
//每打印1次,count的次数就得加1
count++;
}
2.2 案例:珠穆朗玛峰
需求分析
代码实现
//1.需要求次数,那就说明每次循环需要计数一次,那就得在循环外定义一个变量去接收折叠的次数
//循环开始前,没有折叠,所以初始化值是0。注意不能放到循环内去定义变量
int count=0;
//2.要判断停止循环的条件是什么,就是纸张的厚度大于等于珠峰高度的时候
//纸张的高度是随着折叠而变化的,属于变化的量,那就定义一个变量代表纸张厚度
double paper=0.1;
//3.反复折叠属于重复操作,并且不知道折多少次,使用while循环比较合适
while(paper<=8844430){
//4.当纸张厚度小于珠峰的时候就要折叠,折叠的动作是重复的,折叠的后果是纸张厚度要乘以2
paper*=2;
//5.折叠一次,计数器要加1次
count++;
}
//通过不断的循环,paper的厚度一直增加,知道大于等于珠峰高度的时候,条件判断的结果为false,结束循环
//此时就可以打印折叠次数
System.out.println(“折叠”+count+“次,达到珠峰高度”);
格式
//基本格式
do{
循环体语句;
}while(条件判断语句);
//完整格式
初始化语句;
do{
循环体语句;
条件控制语句;
}while(条件判断语句);
//执行流程
//1.执行初始化语句
//2.执行循环体语句
//3.执行条件控制语句
//4.执行条件判断语句,看结果是true还是false
//5.如果是false,循环结束。如果是true,继续执行
//6.回到第2步继续
代码案例
//案例:在控制台输出3次:代码练习了X遍(X代表次数)
//定义一个变量用来记录打印的次数
int count=0;
do{
//进入循环就练习一遍代码,所以次数要加1次
count++;
System.out.println(“代码练习了”+count+“遍”);
//这里不能是<=,因为练了5次,就可以结束了,不能再循环练习
}while(count<5);
特点
do…while循环,无论条件是否满足,都会执行一次循环体语句
很少用,了解即可
三种循环的区别
循环开始前,知道次数,使用for循环
循环开始前,不知道次数,使用while循环
do…while一般不用
//案例1:for循环外尝试使用变量
//循环开始,可以知道循环3次
for(int i=1;i<=3;i++){
//for循环内部使用for循环中定义的变量,没有问题
System.out.println(“i:”+i);
}
//编译报错,因为变量i是for循环中定义,只能在循环中使用,循环结束,i也从内存中消失
System.out.println(“i:”+i);
//案例2:将上面的for循环,替换成while循环
//1.将变量i的声明和初始化提取到循环外操作
int i=1;
//2.条件判断保留
while(i<=3){
//可以打印
System.out.println(“i:”+i);
}
//循环外打印循环外定义的变量,可以打印
System.out.println(“i:”+i);
格式
//1.while死循环
while(true){
循环体语句;
}
//2.for死循环
for(;{
循环体语句;
}
//3.do…while死循环
do{
循环体语句;
}while(true);
代码演示
//案例1:死循环使用的场景-while
//当重复的动作完全无法判断会执行多少次的时候,并且可能没有上限或下限时,使用while死循环
//例如:键盘录入一个3位数,当录入的数字是一个水仙花数的是时候,打印该数字,并结束程序
//分析:3位数的数字非常多,用户可能一直都无法录入成功,所以无法判断录入的次数,重复的上下限也不好判断
//使用while死循环
//1. 导包
import java.util.Scanner;
public class TestWhileLoop {
public static void main(String[] args) {
//2.创建Scanner对象
Scanner sc = new Scanner(System.in);
//无法判断录入多少次会成功,并且录入数字的次数,上下限无法确定
//3.使用while死循环
while (true) {
//4.提示用户录入一个三位数
System.out.println(“亲,请输入一个三位数哦:”);
//5.键盘录入一个整数
int num = sc.nextInt();
//6.获取该数字的个位、十位、百位
int ge = num % 10;
int shi = num / 10 % 10;
int bai = num / 100;
//7.判断该数字是否是水仙花数
if (ge * ge * ge + shi * shi * shi + bai * bai * bai == num) {
//8.如果是水仙花数,就能进入,打印该数字
System.out.println(num);
/*
* 9.问题来了,此时我们是想让循环能够结束的,但是现在还做不到。
* 循环依然还是不断执行,无法结束。
* 所以如果java能具备一个可以随时结束循环的操作,死循环就可以完美的使用。
* 在DOS界面中,可以直接利用Ctrl+C强制结束程序而结束循环,这样不推荐
/
}
}
}
}
/*
概述
代码演示
//案例1:打印1到10之间的整数,不要把2和4打印出来
for(int i=1;i<=10;i++){
//i等于2和4都不能打印,所以必须加条件判断限制
if(i2||i4){
//当i等于2或者4的时候进来,但是此时是不想要执行后面的打印语句的
//使用continue把当前循环体过程马上结束,后面的打印语句就无法执行了,直接进入下一次循环中
continue;
}
System.out.println(i);
}
//案例2:在上一个视频案例中,加上break,让程序可以被结束
…
if (ge * ge * ge + shi * shi * shi + bai * bai * bai == num) {
//如果是水仙花数,就能进入,打印该数字
System.out.println(num);
//已经获得了水仙花数,不需要再重复执行,循环可以结束,利用break
break;
}
…
//案例3:学生管理系统
//我们在学习switch的时候,练过一个学生管理系统的案例
Scanner sc = new Scanner(System.in);
//1.以下内容,我们是需要能够反复执行,知道用户录入退出系统的时候,才会结束
//2.不知道用户要用多久,所以无法判断循环次数和使用上限,选择while死循环
while(true){
System.out.println(“欢迎使用本学生管理系统”);
//提示用户键盘录入
System.out.println(“请选择功能:1.增加学生 2.删除学生 3.修改学生 4.查询学生 5.退出”);
int choice = sc.nextInt();
//根据录入的数字值,选择执行不同的功能
switch (choice) {
case 1:
System.out.println(“增加学生…”);
break;
case 2:
System.out.println(“删除学生…”);
break;
case 3:
System.out.println(“修改学生…”);
break;
case 4:
System.out.println(“查询学生…”);
break;
default:
System.out.println(“退出系统…”);
//3.退出系统,我们本想着用break结束循环,但是发现无法做到
break;
}
}
注意事项
总结:break和continue只能跳出、跳过自己所在的那一层关系,如果想要跳出、跳过指定的一层,可以加入标号
示例
标号名:while(true){
switch(表达式){
case 值1:
break 标号;
…
}
}
代码演示
//给当前循环加上一个标号’loop’,名字可以随便取
loop:while(true){
System.out.println(“欢迎使用本学生管理系统”);
//提示用户键盘录入
System.out.println(“请选择功能:1.增加学生 2.删除学生 3.修改学生 4.查询学生 5.退出”);
int choice = sc.nextInt();
//根据录入的数字值,选择执行不同的功能
switch (choice) {
case 1:
System.out.println(“增加学生…”);
break;
case 2:
System.out.println(“删除学生…”);
break;
case 3:
System.out.println(“修改学生…”);
break;
case 4:
System.out.println(“查询学生…”);
break;
default:
System.out.println(“退出系统…”);
//3.利用结束标号的形式,指定让break结束外层循环语句
break loop;
}
}
Random
作用:用于产生一个随机数
使用步骤
代码演示
//案例:有一个摇号机,可以摇出1~16号的球,当摇出6号球的时候,获得一等奖
//1. 导包
import java.util.Random;
public class TestRandom {
public static void main(String[] args) {
//2.创建Random对象,这个对象就好比是“摇号机”
Random random = new Random();
//3.号码是不断的获取的,直到获得6号的时候中一等奖
//4.使用while死循环
while (true) {
//5.利用Random对象,获取随机数,随机数范围是1~16
//.nextInt(16)的随机数范围是015,在这个范围上加1,范围就变成了116
int num = random.nextInt(16) + 1;
//6.如果随机数是6,就获得一等奖
if (num == 6) {
System.out.println(“恭喜你获得一等奖,奖品是:李小璐亲自为你做头发”);
//7.结束循环
break;
}
}
}
数组
是一种容器,用来存储(同种数据类型)的多个值。
格式
//数组类型变量的声明方式1:
数据类型[] 数组名;
//数组乐行变量的声明方式2:
数据类型 数组名[];
代码演示
//声明一个用来存放int类型数据的数组
int[] arrs;
//或
int arrs[];
//声明一个用来存放double类型数据的数组
double[] nums;
//或
double nums[];
//声明一个用来存放String类型数据的数组
String[] strs;
//或
String strs[];
//注意:数组类型变量和基本数据类型的变量一样,都必须先初始化,才能使用
数组的动态初始化
初始化:就是在内存中,为数组容器开辟空间,并将数据存入容器中的过程
动态初始化:初始化时只指定数组长度,由系统为数组分配初始值
格式
//格式
数据类型[] 变量名= new 数据类型[数组长度];
//范例
int[] arr= new int[3];
代码演示
//案例:
//利用数组的冬天初始化,创建一个int类型的数组,可以存放5个int类型的值
int[] arr=new int[5];
//同上,创建一个可以存放3个byte类型的数组
byte[] bts=new byte[3];
//分别打印这两个数组
System.out.println(arr); //结果:[I@10f87f48
System.out.println(bts); //结果:[B@b4c966a
//直接打印数组,无法获取数组中的数据
//打印的值是该数组容器的内存地址值
/**
数组元素访问
索引
代码演示
//访问数组内部存储的数据:通过索引访问
//数组名[索引]
//代码演示:取数据
//动态初始化一个长度为5的int类型数组
int[] arr=new int[5];
//访问该数组中索引为3的位置的数据
System.out.println(arr[3]);//结果:0
//访问int数组中索引为5的位置的数组
System.out.println(arr[5]);//运行错误,因为数组长度是5,索引最大只能到4
//动态初始化一个String类型的数组,长度为3
String[] strs=new String[3];
System.out.println(strs[2]);//结果:null
//总结
/**
//代码演示:存数据
//数组名[索引]=数据值;
//套用格式
arr[0]=2;
arr[3]=4;
System.out.println(arr[0]);//结果:2
System.out.println(arr[3]);//结果:4
一个数组内存图
栈内存:方法运行时,进入的内存,局部变量都存放于这块内存中
堆内存:new出来的内容都会进入堆内存,并且会存在地址值
方法区:字节码文件(.class文件)加载时进入的内存
本地方法栈:调用操作系统相关资源
寄存器:交给CPU去使用
两个数组内存图
int[] arr1 = new int[2];
System.out.println(arr1);
arr1[0] = 11;
arr1[1] = 22;
System.out.println(arr1[0]);
System.out.println(arr1[1]);
System.out.println(“---------------”);
int[] arr2 = new int[3];
System.out.println(arr2);
arr1[0] = 33;
arr1[1] = 44;
arr1[2] = 55;
System.out.println(arr1[0]);
System.out.println(arr1[1]);
System.out.println(arr1[2]);
多个数组指向相同内存图
int[] arr1 = new int[2];
arr1[0] = 11;
arr1[1] = 22;
int[] arr2 = arr1;
arr1[0] = 33;
System.out.println(arr1[0]);
System.out.println(arr1[1]);
System.out.println(“---------------”);
System.out.println(arr2[0]);
System.out.println(arr2[1]);
数组的静态初始化
静态初始化:初始化时指定每个数组元素的初始值,由系统决定数组长度
格式范例
//完整格式
//数据类型[] 数组名=new 数据类型[]{数据1,数据2,数据3,…,数据n};
//简化格式
//数据类型[] 数组名={数据1,数据2,数据3,…,数据n};
//完整格式范例
int[] arr = new int[]{23, 14, 9};
System.out.println(arr[0]);//结果:23
System.out.println(arr[1]);//结果:14
System.out.println(arr[2]);//结果:9
//简化格式范例
int[] arr2 = {66,88};
System.out.println(arr[0]);//结果:66
System.out.println(arr[1]);//结果:88
两种初始化的使用场景
索引越界异常:访问了数组中不存在的索引,造成索引越界异常
public class Demo01 {
public static void main(String[] args) {
int[] arr = new int[]{23, 14, 9};
System.out.println(arr[3]);
}
}
空指针异常:访问的数组已经不再指向堆内存的数据,造成空指针异常
null:空值,代表不存在。表示不指向任何有效对象。
public class Demo01 {
public static void main(String[] args) {
int[] arr = new int[]{23, 14, 9};
System.out.println(arr[1]);
arr = null;
System.out.println(arr[1]);
}
}
格式
//数组定义及初始化
int[] arr={…};
//…
//遍历数组
for(int i=0;i
//由于i的值从0开始,逐一增加,所以每次循环就能获得一个数组数据,循环结束,数组数据也都拿了一遍
// arr[i];
//至于拿出来的数据是直接打印,还是用一个变量接收,用作后面使用,完全看需求决定
}
注意
数组获取最大值
求最值的思路:
1.假设数组中的0索引元素为最大值max(擂主)
2.让其他的元素和max比较,把较大的值赋值给max(打赢的站在擂台上)
3.最终max就是最大值(最后站在擂台上的就是最大值)
//案例:求数组中的最小值,并打印
//定义一个数组,静态初始化
int[] arr={1,3,46,8,2,5,9,7};
//1.假设数组中的0索引元素为最小值(擂主)
int min=arr[0];
//2.让其他的元素和min比较,把较小的值赋值给min(打赢的站在擂台上)
for (int i = 1; i < arr.length; i++) {
if(arr[i]
min=arr[i]; //打赢的站在擂台上
}
}
//4.最终min就是最小值(最后站在擂台上的就是最小值)
System.out.println(“最小值为:”+min);
数组元素求和
需求:键盘录入5个整数,存储到数组中,并对数组求和
思路
代码演示
//1.创建键盘录入对象,准备键盘录入数字
Scanner sc = new Scanner(System.in);
//2.定义一个求和变量,准备记录累加后的值
int sum = 0;
//3.动态初始化一个长度为5的int数组,准备存储键盘录入的数据
int[] arr = new int[5];
//4.由于数组有多长录入几次,就是遍历数组录入
for (int i = 0; i < arr.length; i++) {
//5.提示用户录入数字
System.out.println(“请录入一个整数:”);
int num = sc.nextInt();
//6.将键盘录入的数值存储到数组中,
arr[i] = num;
}
//7.遍历数组,求和
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
//8.输出总和
System.out.println(“数组中所有元素的和是:”+sum);
需求:已知一个数组==arr = {19,28,37,46,50};==键盘录入一个数据,查找该数据在数组中的索引,并在控制台输出找到的索引值
分析思路
思路:
代码演示
int[] array={10,20,30,40,15,60,15,80};
//1.键盘录入需要查找的元素
Scanner sc=new Scanner(System.in);
//提示用户录入数据
System.out.println(“请录入需要查找的数据:”);
int key=sc.nextInt();
int index=-1; //记录查找的索引,规定-1表示没有找到元素
//2.遍历数组中的元素和key进行比较
for (int i = 0; i < array.length; i++) {
if(array[i]key){
index=i;
//一旦找到了,后面的数据就不需要再遍历了,直接结束循环即可
break;
}
}
//判断index的值,是否等于-1
if(index-1){
System.out.println(“对不起,没有这个元素”);
}else{
System.out.println(key+“元素在数组中的索引为:”+index);
}
需求
思路
代码实现
//1.定义数组,用于存储评委的分数
int[] array=new int[6];
//2.循环的采用键盘录入的方式,代表评委打分
Scanner sc=new Scanner(System.in);
for (int i = 0; i < array.length; i++) {
//2.1 提示用户录入分数
System.out.println(“请输入第”+(i+1)+“评委的分数:”);
int num = sc.nextInt();
//2.2 把分数存入数组中
array[i]=num;
}
//3.求数组元素的最大值
//3.1 把数组中的0索引元素假设为最大值
int max=array[0];
for (int i = 1; i < array.length; i++) {
//3.2 把数组中元素较大的值赋值给max
if(array[i]>max){
max=array[i];
}
}
System.out.println(“最大值为:”+max);
//4.求数组元素的最小值
int min=array[0];
for (int i = 1; i < array.length; i++) {
//4.1 把数组中元素较小的值赋值给min
if(array[i]
}
}
System.out.println(“最小值为:”+min);
//5.求数组元素的和
int sum=0;
for (int i = 0; i < array.length; i++) {
sum+=array[i];
}
System.out.println(“所有元素的和为:”+sum);
//6.求平均值
double avg=(sum-max-min)*1.0/(array.length-2);
System.out.println(“最终得分:”+avg);
二维数组
动态初始化
//格式1:数据类型[][] 变量名 = new 数据类型[m][n];
//m表示这个二维数组,可以存放多少个一维数组。n表示每一个一维数组,可以存放多少个元素
int[][] arr = new int[2][3];
System.out.println(arr);//结果:[[I@10f87f48
System.out.println(arr[0]);//结果:[I@b4c966a
System.out.println(arr[1]);//结果:[I@2f4d3709
//以上结果表明,二维数组中存储的数据还是数组,所以打印的就是地址值
System.out.println(arr[0][0]);//结果:0
System.out.println(arr[0][1]);//结果:0
System.out.println(arr[0][2]);//结果:0
//以上结果表明,二维数组中存储的是一维数组,可以通过二维数组和一维数组的索引拿到存储的数据值
//可以存值,就可以赋值
arr[1][0] = 11;
arr[1][1] = 22;
arr[1][2] = 33;
访问元素的细节问题
int[] arr1 = {11, 22, 33};
int[] arr2 = {44, 55, 66};
int[] arr3 = {77, 88, 99, 100};
int[][] arr = new int[3][3];
//此时二维数组索引2位置指向的数组是一个长度为3的数组,此时给该数组索引为3的位置赋值会索引越界
arr[2][3] = 101;
arr[0] = arr1;
arr[1] = arr2;
//通过赋值操作,让原本指向长度为3的数组指向了一个长度为4的数组,该数组索引最大值是3
arr[2] = arr3;
//由于已经更换了指向的数组,所以可以通过二维索引3找到对应的值
System.out.println(arr[2][3]);
静态初始化
//格式:数据类型[][] 变量名={{元素1,元素2,…},{元素1,元素2,…},…};
//范例:int[][] arr={{11,22},{33,44}};
//代码案例
int[] arr1 = {11, 22, 33};
int[] arr2 = {44, 55, 66};
int[][] arr = {{11, 22, 33}, {44, 55, 66}};
System.out.println(arr[0][1]);
int[][] array = {arr1, arr2};//结果:22
System.out.println(arr[1][0]);//结果:44
案例:遍历
需求:已知一个二维数组arr = {{11, 22, 33}, {33, 44, 55,}};遍历该数组,取出所有元素并打印
思路:
代码实现
int[][] arr = {{11, 22, 33}, {33, 44, 55,}};
//1.先遍历二维数组,把里面的一维数组拿出来
for (int i = 0; i < arr.length; i++) {
//2.根据拿出的一维数组,再遍历这个一维数组
for (int j = 0; j < arr[i].length; j++) {
//3.打印对应一维数组中的值
System.out.println(arr[i][j]);
}
}
案例:求和
需求:某公司季度和月份统计的数据如下:单位(万元)
思路:
代码实现
//1.定义求和变量,准备记录最终累加结果
int sum = 0;
//2.使用二维数组来存储数据,每个季度是一个一维数组,再将4个一维数组装起来
int[][] arr = {{22, 66, 44}, {77, 33, 88}, {25, 45, 65}, {11, 66, 99}};
//3.遍历二维数组,取出所有元素,累加求和
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
sum += arr[i][j];
}
}
//4.打印最终累加结果
System.out.println(sum);
方法
格式
//方法定义格式(无参数、无返回值的公共静态方法)
public static void 方法名(){
//方法体:就是需要复用(被反复使用)的逻辑代码
}
//范例
public static void printHello(){
System.out.println(“Hello method!”);
}
//方法调用:方法名();
//范例:
public static void main(String[] args) {
printHello();
}
注意事项
方法必须先定义后调用,否则程序将报错
方法与方法之间是平级关系,不能嵌套定义
练习:奇偶数判断
需求
思路
代码演示
public static void main(String[] args){
//3.调用方法
method();
}
//1.定义一个方法,功能为:判断一个数是否为奇数或者偶数
public static void method(){
//2.判断奇偶数逻辑
int a=10;
if(a%2==0){
System.out.println(“偶数”);
}else{
System.out.println(“奇数”);
}
}
带参数方法的定义和调用
为什么要有带参数方法
带参数方法的定义
//单个参数
public static void 方法名(数据类型 变量名){方法体;}
//范例
public static void method(int num){方法体;}
//多个参数
public static void 方法名(数据类型 变量名1,数据类型 变量名2,…){方法体;}
//范例
public static void getMax(int num1,int num2){方法体;}
//注意
//1.方法定义时,参数中的数据类型与变量名都不能缺少,缺少任意一个程序都将报错
//2.方法定义时,多个参数之间使用逗号分隔
带参数方法的调用
代码练习
/*
/*
形参和实参
概念
带参数方法的练习:打印n~m之间所有的奇数
需求:设计一个方法(print)用于打印n到m之间所有的奇数
思路:
代码演示
为什么要有带返回值的方法
带返回值方法的定义
带返回值方法的调用
代码演示
//案例:计算两个数的乘积
public static void main(String[] args) {
//3.调用方法,因为方法定义了两个参数,都是整数,所以这里要给两个整数的实参
//4.因为方法有返回值,所以可以在方法调用处使用一个变量接收这个方法调用完的返回值
//5.方法返回值什么类型,接收的变量就应该是什么类型
int result = cheng(2, 3);
System.out.println(result);//结果:6
}
//1.两个整数的乘积,结果还是整数,所以返回值类型应该为int
public static int cheng(int num1,int num2) {
//2.通过return关键,返回乘积
return num1 * num2;
}
需求:设计一个方法可以获取两个数的较大值,数据来自于参数
思路:
代码实现
扩展练习
//仿照课堂案例,求三个数的最大值
格式
代码演示
方法不能嵌套定义
方法的返回值类型为void,表示该方法没有返回值,没有返回值的方法可以省略return语句不写,如果要写return语句,后面不能跟具体的数据
return语句下面,不能编写代码,因为永远执行不到,属于无效代码
return语句,如果要返回值,只能带回一个结果
//案例:没有返回值的方法,可以省略return不写
public static void eat(){
System.out.println(“吃饭”);
//return的其中一个作用,是结束整个方法,但是不可以带返回值
return;
//return 3; 方法本身没有规定返回值,在此处就不能带返回值,因为你也不知道返回什么类型比较合适
}
//案例:计算器加法运算
public static int add(int num1,int num2){
// return的第二个作用,就是返回一个值
return num1+num2;
}
//案例:return语句下面,不能编写代码
public static void drink(int age){
if(age<8){
System.out.println(“喝白开水”);
//此处是个if判断语句,按照逻辑推断,如果进入if语句中,下面的代码逻辑肯定是不想再执行
//如果此处不加以限制,if执行结束,代码依然会执行:喝红牛
//所以此处可以加上return,直接结束方法
return;
//注意,说的return下面不能加代码,是指同一个逻辑代码块(大括号)中而已
}
System.out.println(“喝红牛”);
}
需求:使用方法重载的思想,设计比较两个整数是否相同的方法,兼容全整数类型(byte,short,int,long)
思路:
代码练习
方法的形参在内存当中也就是一个变量而已
一个方法在传递参数的时候,如果是基本数据类型,那么传递的就是该变量所记录的具体的数值
public static void main(String[] args) {
int number = 100;
System.out.println(“main方法中,调用change方法前:” + number);//结果:100
//基本数据类型,传递的是number的数值,而非变量
change(number);
//打印的变量,依然还是main方法中的变量,此变量的值未有任何改变,依然是100
System.out.println(“main方法中,调用change方法后:” + number);//结果:100
}
//方法的形参相当于是这个方法中的一个局部变量,属于change方法,和main方法中的变量不是同一个
public static void change(int number) {
//在未执行下方赋值操作时,从main方法传递过来的是值100,将100赋值给了change方法的变量number
//此时修改的是change方法中的变量number值,对main方法中的number无影响
number = 200;
System.out.println(“在change方法中的:” + number);//结果:200
}
方法传递,如果传入的是引用数据类型,传进去的就是该引用数据类型的内存地址
public static void main(String[] args) {
//定义一个数组,数组是引用数据类型
int[] arr = {23, 12, 44, 77};
//该数组在堆内存中的一个空间存放,变量arr持有的是这个空间的地址
System.out.println(“在main方法中,调用change方法前:” + arr[1]);//结果:12
//arr是引用数据类型变量,传入的就是arr持有的数组在堆内存的地址,而非数组本身
change(arr);
System.out.println(“在main方法中,调用change方法后:” + arr[1]);//结果:0
}
public static void change(int[] arr) {
//调用方法,将传递过来的地址赋值给了change方法中的变量arr,change方法中的arr也持有这个地址
//通过持有的地址,可以找到堆内存中的数组,所以可以对其修改值
arr[1] = 0;
//打印的就是修改之后的0值
System.out.println(“在change方法中的:” + arr[1]);//结果:0
}
需求:设计一个方法,用于数组遍历,要求遍历的结果是在一行上的。例如:[11,22,33,44,55]
思路:
代码演示
public static void main(String[] args) {
//1.静态初始化一个数组
int[] arr = {11, 22, 33, 44, 55};
printArr(arr);
}
//2.定义一个方法,对数组进行遍历。因为是打印,所以是不需要返回值的
public static void printArr(int[] arr) {
//3.要打印数组中所有数据,必须要先遍历数组
for (int i = 0; i < arr.length; i++) {
//4.将数组中每个元素取出来
int num = arr[i];
//5.打印数组中该元素的值,但是因为有格式要求,所以不要换行打印
//6.当i=0和i是最后一个索引的时候,打印格式要加上中括号
if (i == 0) {
System.out.print(“[” + num + ", ");
} else if (i == arr.length - 1) {
System.out.print(num + “]”);
} else {
//7.打印的数字之间要用逗号和空格隔开
System.out.print(num + ", ");
}
}
}
需求:设计一个方法用于获取数组中元素的最大值
思路:
代码演示:
需求:设计一个方法,该方法能够同时获取数组的最大值,和最小值
思路:
代码演示:
基础练习
案例需求
朋友聚会的时候可能会玩一个游戏:逢七过。
规则是:从任意一个数字开始报数,当你要报的数字包含7或者是7的倍数时都要说:过。
为了帮助大家更好的玩这个游戏,这里我们直接在控制台打印出1-100之间的满足逢七必过规则的数据。
这样,大家将来在玩游戏的时候,就知道哪些数据要说:过。
代码实现
/*
思路:
1:数据在1-100之间,用for循环实现数据的获取
2:根据规则,用if语句实现数据的判断:要么个位是7,要么十位是7,要么能够被7整除
3:在控制台输出满足规则的数据
*/
public class Test1 {
public static void main(String[] args) {
//数据在1-100之间,用for循环实现数据的获取
for(int x=1; x<=100; x++) {
//根据规则,用if语句实现数据的判断:要么个位是7,要么十位是7,要么能够被7整除
if(x%10==7 || x/10%10==7 || x%7==0) {
//在控制台输出满足规则的数据
System.out.println(x);
}
}
}
}
案例需求
有这样的一个数组,元素是{68,27,95,88,171,996,51,210}。求出该数组中满足要求的元素和,
要求是:求和的元素个位和十位都不能是7,并且只能是偶数
代码实现
package com.itheima.test;
public class Test2 {
/*
有这样的一个数组,元素是{68,27,95,88,171,996,51,210}。求出该数组中满足要求的元素和,
要求是:求和的元素个位和十位都不能是7,并且只能是偶数
*/
public static void main(String[] args) {
// 1. 定义数组
int[] arr = {68, 27, 95, 88, 171, 996, 51, 210};
// 2. 求和变量
int sum = 0;
// 3. 遍历数组
for (int i = 0; i < arr.length; i++) {
// 4. 拆分出个位和十位
int ge = arr[i] % 10;
int shi = arr[i] / 10 % 10;
// 5. 条件筛选
if (ge != 7 && shi != 7 && arr[i] % 2 == 0) {
sum += arr[i];
}
}
// 6. 打印结果
System.out.println(sum);
}
}
案例需求
定义一个方法,用于比较两个数组的内容是否相同
代码实现
/*
思路:
1:定义两个数组,分别使用静态初始化完成数组元素的初始化
2:定义一个方法,用于比较两个数组的内容是否相同
3:比较两个数组的内容是否相同,按照下面的步骤实现就可以了
首先比较数组长度,如果长度不相同,数组内容肯定不相同,返回false
其次遍历,比较两个数组中的每一个元素,只要有元素不相同,返回false
最后循环遍历结束后,返回true
4:调用方法,用变量接收
5:输出结果
*/
public class Test3 {
public static void main(String[] args) {
//定义两个数组,分别使用静态初始化完成数组元素的初始化
int[] arr = {11, 22, 33, 44, 55};
//int[] arr2 = {11, 22, 33, 44, 55};
int[] arr2 = {11, 22, 33, 44, 5};
//调用方法,用变量接收
boolean flag = compare(arr,arr2);
//输出结果
System.out.println(flag);
}
//定义一个方法,用于比较两个数组的内容是否相同
/*
两个明确:
返回值类型:boolean
参数:int[] arr, int[] arr2
*/
public static boolean compare(int[] arr, int[] arr2) {
//首先比较数组长度,如果长度不相同,数组内容肯定不相同,返回false
if(arr.length != arr2.length) {
return false;
}
//其次遍历,比较两个数组中的每一个元素,只要有元素不相同,返回false
for(int x=0; x
案例需求
已知一个数组 arr = {19, 28, 37, 46, 50}; 键盘录入一个数据,查找该数据在数组中的索引。
并在控制台输出找到的索引值。如果没有查找到,则输出-1
代码实现
/*
思路:
1:定义一个数组,用静态初始化完成数组元素的初始化
2:键盘录入要查找的数据,用一个变量接收
3:定义一个索引变量,初始值为-1
4:遍历数组,获取到数组中的每一个元素
5:拿键盘录入的数据和数组中的每一个元素进行比较,如果值相同,就把该值对应的索引赋值给索引变量,并结束循环
6:输出索引变量
*/
public class Test4 {
public static void main(String[] args) {
//定义一个数组,用静态初始化完成数组元素的初始化
int[] arr = {19, 28, 37, 46, 50};
//键盘录入要查找的数据,用一个变量接收
Scanner sc = new Scanner(System.in);
System.out.println("请输入要查找的数据:");
int number = sc.nextInt();
//调用方法
int index = getIndex(arr, number);
//输出索引变量
System.out.println("index: " + index);
}
//查找指定的数据在数组中的索引
/*
两个明确:
返回值类型:int
参数:int[] arr, int number
*/
public static int getIndex(int[] arr, int number) {
//定义一个索引变量,初始值为-1
int index = -1;
//遍历数组,获取到数组中的每一个元素
for(int x=0; x
案例需求
已知一个数组 arr = {19, 28, 37, 46, 50}; 用程序实现把数组中的元素值交换,
交换后的数组 arr = {50, 46, 37, 28, 19}; 并在控制台输出交换后的数组元素。
代码实现
/*
思路:
1:定义一个数组,用静态初始化完成数组元素的初始化
2:循环遍历数组,这一次初始化语句定义两个索引变量,判断条件是开始索引小于等于结束索引
3:变量交换
4:遍历数组
*/
public class Test5 {
public static void main(String[] args) {
//定义一个数组,用静态初始化完成数组元素的初始化
int[] arr = {19, 28, 37, 46, 50};
//调用反转的方法
reverse(arr);
//遍历数组
printArray(arr);
}
/*
两个明确:
返回值类型:void
参数:int[] arr
*/
public static void reverse(int[] arr) {
//循环遍历数组,这一次初始化语句定义两个索引变量,判断条件是开始索引小于等于结束索引
for (int start = 0, end = arr.length - 1; start <= end; start++, end--) {
//变量交换
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
}
}
/*
两个明确:
返回值类型:void
参数:int[] arr
*/
public static void printArray(int[] arr) {
System.out.print("[");
for (int x = 0; x < arr.length; x++) {
if (x == arr.length - 1) {
System.out.print(arr[x]);
} else {
System.out.print(arr[x] + ", ");
}
}
System.out.println("]");
}
}
案例需求
在编程竞赛中,有6个评委为参赛的选手打分,分数为0-100的整数分。
选手的最后得分为:去掉一个最高分和一个最低分后 的4个评委平均值 (不考虑小数部分)。
代码实现
思路:
1:定义一个数组,用动态初始化完成数组元素的初始化,长度为6
2:键盘录入评委分数
3:由于是6个评委打分,所以,接收评委分数的操作,用循环改进
4:定义方法实现获取数组中的最高分(数组最大值),调用方法
5:定义方法实现获取数组中的最低分(数组最小值) ,调用方法
6:定义方法实现获取数组中的所有元素的和(数组元素求和) ,调用方法
7:按照计算规则进行计算得到平均分
8:输出平均分
案例需求
请从26个英文字母(大小写都包含),以及数字0-9中,随机产生一个5位的字符串验证码并打印在控制台
效果:uYq8I,3r4Zj
代码实现
import java.util.Random;
public class Test {
public static void main(String[] args) {
// 1. 将所需要用到的字符存入数组
char[] datas = initData();
Random r = new Random();
String result = "";
// 2. 随机取出5个字符
for (int i = 1; i <= 5; i++) {
int index = r.nextInt(datas.length);
char c = datas[index];
result += c;
}
// 3. 打印验证码
System.out.println(result);
}
private static char[] initData() {
char[] chs = new char[62];
int index = 0;
for (char i = 'a'; i <= 'z'; i++) {
chs[index] = i;
index++;
}
for (char i = 'A'; i <= 'Z'; i++) {
chs[index] = i;
index++;
}
for (char i = '0'; i <= '9'; i++) {
chs[index] = i;
index++;
}
return chs;
}
}
面向对象基础
1.1 面向对象编程思想
面向对象编程(oop)
需求:洗衣服
对象:客观存在的事物。例如厨师、洗衣机这些都是客观存在的事物,并且都有自己能够完成的功能。这些事物就可以通过java代码的形式描述成为程序中的对象。然后就可以指挥这些对象去调用里面一个个的功能
小结
代码演示
//面向过程:解决数组遍历问题
int[] arr = {11, 22, 33, 44, 55, 66};
//1. 打印左括号,不能换行
System.out.print(“[”);
//2. 遍历数组,取出数组中每一个值
for (int i = 0; i < arr.length; i++) {
//3. 判断是否是最后一个元素
if (i == arr.length - 1) {
//4.如果是最后一个元素,除了打印元素值,还要加上括号
System.out.println(arr[i] + “]”);
} else {
//5. 如果不是最后一个元素,打印数值不能换行,而且还要用空格隔开
System.out.print(arr[i] + " ");
}
}
//总结:面向过程的思想,总共分为了5个步骤,每一个步骤都需要自己实现
//面向对象:解决数组遍历问题
public class OopTest {
public static void main(String[] args) {
int[] arr = {11, 22, 33, 44, 55, 66};
//1.先想谁可以实现数组遍历的功能
//2.想起了数组操作员,创建数组操作员对象
//3.利用对象解决问题
数组操作员 二狗 = new 数组操作员();
二狗.遍历打印数组(arr);
}
}
class 数组操作员 {
public static void 遍历打印数组(int[] arr) {
//1. 打印左括号,不能换行
System.out.print(“[”);
//2. 遍历数组,取出数组中每一个值
for (int i = 0; i < arr.length; i++) {
//3. 判断是否是最后一个元素
if (i == arr.length - 1) {
//4.如果是最后一个元素,除了打印元素值,还要加上括号
System.out.println(arr[i] + “]”);
} else {
//5. 如果不是最后一个元素,打印数值不能换行,而且还要用空格隔开
System.out.print(arr[i] + " ");
}
}
}
}
1.2 类和对象的关系
什么是类
类的组成
什么是对象?
1.3 类的定义
类的组成:属性和行为
类的定义步骤:
定义类
编写类的成员变量
编写类的成员方法
public class 类名{
//成员变量
//变量1的数据类型 变量1;
//变量2的数据类型 变量2;
//…
//成员方法
//方法1
//方法2
//...
}
代码实现
//视频案例:学生类
public class Student {
//1.属性:姓名,年龄
//成员变量:跟之前定义的变量格式一样,只不过位置发生了改变,从方法中跑到了类中方法外
//姓名是一段内容,可以使用字符串类型去表示
String name = "张三";
//年龄是一个整数,可以使用int类型去表达
int age = 23;
//2.行为:学习
//成员方法:跟之前定义的方法一样,只不过去掉了static
public void study() {
System.out.println("好好学习,天天向上");
}
//3.不建议在这种用来描述事物的类中写main主方法,主方法一般单独写一个测试类去实现
}
/**
1.4 对象的创建和使用
创建对象
使用对象
使用成员方法
代码演示
//创建学生类对象,并且给其属性赋值。获取其属性值,调用其方法
public class TestStudent {
public static void main(String[] args) {
//1. 创建学生类对象,把对象赋值给学生类型的变量stu
Student stu = new Student();
//2. 使用成员变量
System.out.println(stu.name);//结果:null
System.out.println(stu.age);//结构:0
//3. 就算没有给成员变量赋值,也可以使用,整数基本数据类型默认是0,字符串类型默认是null
//4. 给成员变量赋值
stu.name = “张三”;
stu.age = 23;
System.out.println(stu.name);//结果:张三
System.out.println(stu.age);//结果:23
//5.使用成员方法
stu.study();
//6.打印对象
System.out.println(stu);//结果:com.itheima.test.Student@b4c966a
//打印对象,默认打印的是:全类名(包名+类名)+ 地址哈希值
}
}
public class Student {
String name;
int age;
public void study() {
System.out.println(“好好学习,天天向上”);
}
}
1.5 案例:手机类的创建和使用
需求:定义一个手机类,然后定义一个手机测试类,在收集测试类中通过对象完成成员变量和成员方法的使用
分析:
思路
代码实现
public class Phone {
//成员变量:品牌、价格
String brand;
int price;
//成员方法:打电话
public void call(String name) {
System.out.println("给" + name + "打电话");
}
//成员方法:发短信
public void sendMessage() {
System.out.println("群发短信");
}
}
//测试类
public class TestPhone {
public static void main(String[] args) {
//1. 创建对象
Phone phone = new Phone();
//2. 给成员变量赋值
phone.brand = “大米”;
phone.price=2999;
//3. 打印赋值后的成员变量
System.out.println(phone.brand + “…” + phone.price);
//4. 调用成员方法
phone.call(“张三”);
phone.sendMessage();
}
}
2.1 单个对象内存图
2.2 两个对象内存图
2.3 两个引用指向同一个对象内存图
代码执行到Student stu2=stu1;的时候,通过s1指向的堆内存中对象的地址,将s2也指向这个地址,所以s1和s2都指向同一个对象
代码执行到stu1=null;的时候,stu1原本持有的是堆内存中学生对象的地址,由于置null,此指向切断了。s1再也无法找到堆内存中该学生对象
在执行完stu2=null;之后,就没有变量再指向堆内存中的学生对象,此对象无法再被使用到。所以垃圾回收器会在空闲的时候将这个学生对象的空间给清理掉
当堆内存中,对象或数组产生的地址,通过任何方式都不能被找到后,就会判定为内存中的"垃圾",垃圾会被Java垃圾回收器,空闲的时候自动进行清理
4.1 private关键字
问题:
1.为什么说通过对象名给其属性赋值具有安全隐患问题?
2.private关键字可以用来修饰哪些内容?
3.使用private修饰属性之后,还需要做什么操作?
4.2 private关键字的使用
把成员变量用private修饰
提供对应的setXxx()/getXxx()方法
/**
学生类:
属性:姓名,年龄
需求:
1.利用private对类的属性进行封装
2.给属性提供设置值和获取值的方法
3.在测试类中测试
*/
public class Student {
//1.为了以后别人不能随意给我的属性赋值,就给这两个成员变量加上private
private int age;
private String name;
//2.加上了private之后,这两个属性的变量,以后就只能在当前这个Student类中被访问,外类无法访问
//3.外类无法访问,这个变量定义的就没有意义了,所以还要对外提供对这两个变量的访问方式
//提供set和get方法,给外界使用
//4.提供给属性设置值的方法
//设置年龄值,目的是给本类的age变量赋值,赋的值应该是int类型
//这个值是别人调用方法的时候传过来的,所以应该作为形式参数声明
public void setAge(int a) {
//声明了形式参数,别人调用的时候就得传一个int值过来,那这个值目的是给age变量赋值
age = a;
}
//有了赋值的,就应该要有取值的
public int getAge() {
//这里是把age变量的值返回给方法调用处,直接return
return age;
}
public void setName(String n) {
name = n;
}
public String getName() {
return name;
}
public void show() {
//这个方法只是做展示对象数据的作用,也没有返回值
System.out.println(name + “…” + age);
}
}
public class Test03 {
public static void main(String[] args) {
Student stu = new Student();
stu.show();
stu.setAge(17);
stu.setName(“张三”);
stu.show();
System.out.println(stu.getAge());
System.out.println(stu.getName());
}
}
4.3 this关键字
问题:
1.类方法的形式参数名和类属性名出现重名,会有什么问题?
2.this关键字有哪些作用?
3.在方法中打印this关键字,打印的内容代表谁?
概述:
作用:可以调用本类的成员(变量、方法),解决局部变量和成员变量的重名问题
注意:如果局部变量和成员变量重名,Java使用的是就近原则
//练习:使用this关键字,优化老师类的set方法
public class Teacher {
//属性:姓名、年龄、学科
//1.利用private修饰各个属性
private String name;
private int age;
private String obj;
//2.行为:工作
public void work() {
System.out.println("传道受业解惑");
}
//3.针对属性,增加set\get方法。并且使用this优化get方法
public void setName(String name) {
this.name=name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age=age;
}
public int getAge() {
return age;
}
public void setObj(String obj) {
this.obj=obj;
}
public String getObj() {
return obj;
}
}
4.4 this内存原理
4.5 封装
问题:
1.封装的思想指的是什么?
2.将一个类的属性私有化就是封装吗?
3.在程序中引入封装思想,有什么好处?
5.1 构造方法的格式和执行时机
问题:
1.没有给一个类定义构造方法,为什么也能够调用?
2.能不能在构造方法中使用return关键字返回一个值?
3.构造方法是在什么时候就会被调用?
概述:构建、创造对象的时候,所调用的方法
格式:
方法名和类名相同,大小写也要一致;
没有返回值类型,连void都没有;
没有具体的返回值(不能由return带回结果数据)
//格式:
public class 类名{
//…
public 类名(参数列表){
构造方法体;
}
//…
}
//2.范例:
public class Person{
private String name;
private int age;
public Person(){
}
}
执行时机:
5.2 构造方法的作用
问题:
1.构造方法除了创建对象,还有什么作用?
2.给一个类提供了有参数的构造方法,还会有默认空参的构造吗?
创造属于类的对象
用于给对象的数据==(属性)==进行初始化
//案例:
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void show() {
System.out.println(name + "..." + age);
}
}
//练习:修改Person类,能够让Person类通过构造方法给对象属性赋值。并在测试类中验证
5.3 构造方法的注意事项
问题:
1.无论什么情况下,系统都会提供一个默认构造方法吗?
2.以后在写一个标准类的时候,构造方法应该如何写?
5.4 案例:标准类的代码编写和使用
无参构造方法创建对象后使用setXxx()赋值
使用带参构造方法直接创建带有属性值的对象
/**
因为程序是为了现实服务的,以后假设我们写了一个学生管理系统,系统中就存在一个数据叫学生数据
而仅仅用基本数据类型的数据无法完全描述学生数据,因为学生数据中有学号、姓名、年龄、分数等等
这些数据里面有各种数据类型:int、String等
这个时候就可以使用面向对象思想,用一个类去描述这类信息
*/
public class Student {
//1.定义类的属性,学生有哪些属性?
//学号
private String id;
//姓名
private String name;
//年龄
private int age;
//分数
private int score;
//2.为了不让外接随意更改我的属性值,给我一些非法的值,比如分数给一个-100分,全部用private修饰
//3.属性被封装了,但是这些属性值,未来外接还是要使用的呀,那怎么用呢?提供对应的set\get方法
//5.提供构造方法
public Student(String id, String name, int age, int score) {
//这里给属性赋值,那么构造方法就应该有形式参数
this.id = id;
this.name = name;
this.age = age;
this.score = score;
}
public Student() {
}
//4.针对所有的属性,都有对应方法给这些属性设置值和获取他们的值
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public void show() {
System.out.println(id + “…” + name + “…” + age + “…” + score);
}
}
public class Test01 {
public static void main(String[] args) {
//1.创建一个学生对象:类名 变量名=new 构造方法();
Student stu1 = new Student();
//2.对象现在只有默认值,没有使用的价值,开始赋值
//使用常规的set方法赋值。格式:对象名.方法名(值);
stu1.setId(“001”);
stu1.setName(“张三”);
stu1.setAge(23);
stu1.setScore(98);
//3.现在stu1对象已经有了值,展示看看
stu1.show();
//代表值赋值成功,以后你可以在程序中使用对象去存储比较复杂的数据值
//4.但是上面的代码还是复杂了一点,赋值操作台频繁
//有一种简单的赋值操作,就是利用构造方法赋值,给这个类提供一个带参数的构造方法
Student stu2 = new Student(“002”, “李四”, 22, 100);
stu2.show();
//5.明明有了构造方法可以赋值,为什么还要有set方法?
//因为一用构造方法,就是一个新的对象,因为构造方法不能修改属性值,只能创建对象的时候给它赋值一次
//而set方法可以反复修改同一个对象的值,作用不一样
}
}
1.1 API概述-帮助文档的使用
问题:
1.什么是API,使用API文档有什么好处?
2.如何使用API文档,应该看文档的哪些内容?
1.2 键盘录入字符串
问题:
1.Scanner键盘录入字符串总共有几种方式?
2.Scanenr使用next()方法录入字符串会存在什么问题?
3.是否需要解决nextLine()方法存在的问题?
Scanner类录入字符串的方法:
注意事项:
nextLine()和录入其他数据的问题解决方案:
总结:
案例练习:
键盘录入学生信息:
打印所有学生信息:
代码材料:
public class Student {
//学生id
private String id;
//学生姓名
private String name;
//学生年龄
private int age;
//学生评语
private String estimate;
}
代码实现:
//1.要键盘录入四名学生信息,存入数组,数组长度是4
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//创建一个长度为4的学生数组
Student[] stus = new Student[4];
//2.开始录入4名学生信息,录入的操作是重复的,重复的次数是明确的,使用for
for (int i = 0; i < stus.length; i++) {
//3.提示用户录入信息
System.out.println(“请输入第” + (i + 1) + “名学生信息”);
System.out.println(“请输入学生学号:”);
String id = sc.next();
System.out.println(“请输入学生姓名:”);
String name = sc.next();
System.out.println(“请输入学生年龄:”);
int age = sc.nextInt();
//加一个nextLine消费回车
sc.nextLine();
System.out.println(“请输入学生评语:”);
String estimate = sc.nextLine();
//4.学生信息录入了,但是都是零散的数据,要把这些零散数据统一管理
//根据信息创建学生对象
Student stu = new Student(id, name, age, estimate);
//5.存入数组
stus[i] = stu;
}
//6.循环结束,所有学生信息都存入了数组,开始遍历打印所有学生信息
for (int i = 0; i < stus.length; i++) {
//7.取出学生对象
Student student = stus[i];
System.out.println(“学号:” + student.getId() + “,姓名:” + student.getName() + “,年龄:” + student.getAge() + “,评语:” + student.getEstimate());
}
2.1 String概述
问题:
1.如果使用的是java.lang包下的类,是否需要进行导包?
2.在创建String类对象的时候,它有什么特殊的地方?
3.String类的length()方法返回的长度是根据什么得到的?
2.2 String类常见构造方法
问题:
1.有多少种常见的字符串对象创建方式?
2.哪种字符串创建方式,实际上是创建了两个字符串对象?
常用的构造方法
示例代码
//案例:分别用以上4种方式创建字符串对象,并且打印
2.3 创建字符串对象的区别对比
问题:
1.如何比较两个字符串对象在内存中的地址是否相同?==
2.在什么情况下,字符串不会重新创建,而是直接复用?赋值一个已经存在的字符串常量
3.字符串常量在内存中的哪个位置进行存储?字符串常量池
通过构造方法创建
通过 new 创建的字符串对象,每一次 new 都会申请一个堆内存空间,虽然内容相同,但是地址值不同
直接赋值方式创建
以“”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会建立一个 String 对象,并在字符串池中维护
//案例:分别用构造方法创建的字符串和用“”方式给出的字符串,使用==进行比较
//用字符串常量赋值
String s1 = “hello”;
String s2 = “hello”;
//以上两个字符串对象在字符串常量池,s1和s2指向的地址相同
System.out.println(s1 == s2);//结果:true
String s3 = new String(“abc”);
String s4 = new String(“abc”);
//以上两个字符串对象不在字符串常量池,就直接在堆内存中
//s3和s4指向的地址不相同,有几个new,就有几个地址
System.out.println(s3 == s4);//结果:false
2.4 String特点:常见面试题
字符串变量直接赋值字符串常量,指向的地址是字符串常量池中的对象
字符串变量赋值的是一个字符串类型变量和其他字符串的拼接
字符串白能量赋值的是两个字符串常量拼接,会有常量优化机制,指向的还是常量池中的那个拼接后的字符串对象
//定义两个变量,接收相同字符串常量
String s1 = “abc”;
String s2 = “abc”;
System.out.println(s1 == s2);//true。都是指向常量池的"abc"字符串
String s3 = “ab”;
String s4 = s3 + “c”;
//底层在堆内存中会有StringBuilder对象做拼接,得到StringBuilder对象,然后调用它的toString方法
//得到String对象,这个String对象是在堆内存中,只是拿到了常量池中的字符串值
//所以s3指向的是常量池中的字符串对象,s4指向的是堆内存中的字符串对象,地址不一样
System.out.println(s4 == s1);//flase。
String s4=“ab”+“c”;
//如果字符串拼接都是用字符串常量,会有常量优化机制,底层不会用StringBuilder做拼接
//所以s1和s4都还是指向常量池中的字符串
System.out.println(s4 == s1);//true。
//给一个变量加上final关键字,就相当于这个变量变成了常量
final String s5 = “ab”;
String s6 = s5 + “c”;
System.out.println(s6 == s1);//true
2.5 字符串的比较
问题:
1.在实际开发中,字符串的比较一般使用什么方式?
2.如果要忽略大小写去比较两个字符串内容是否相同,用哪个方法?
String类 : public boolean equals(String s) 比较两个字符串内容是否相同、区分大小写
代码 :
//equals练习:使用equals方法分别比较字符串常量、变量以及使用new创建的字符串对象
//equalsIgnoreCase练习:使用方法比较两个大小写不同的字符串
2.6 用户登录案例
案例需求 :
实现步骤 :
代码实现 :
//1.用户登录功能,实际上是用你录入的信息和系统中已存在的正确信息比较
//2.定义一对正确的用户名和密码
String usr = "admin";
String pwd = "123";
Scanner sc = new Scanner(System.in);
//3.开始键盘录入用户名和密码,有3次机会,重复录入,并且知道次数,使用for
for (int i = 0; i < 3; i++) {
System.out.println("请输入用户名:");
String username = sc.next();
System.out.println("请输入密码:");
String password = sc.next();
//4.有了键盘录入的信息,开始比较
if (username.equals(usr) && password.equals(pwd)) {
System.out.println("登录成功");
//登录成功,结束循环
break;
} else {
if (i==2) {
System.out.println("您今日登录次数已达上限,请明日再来");
break;
}
System.out.println("登录失败,您还有" + (2 - i) + "次机会");
}
}
2.7 遍历字符串案例
案例需求 :
键盘录入一个字符串,使用程序实现在控制台遍历该字符串
实现步骤 :
核心方法:
代码实现 :
//1.键盘录入一个字符串
System.out.println("请输入:");
Scanner sc = new Scanner(System.in);
String str = sc.next();
//2.先获取字符串长度,然后遍历,使用length()方法获取字符串长度
for (int i = 0; i < str.length(); i++) {
//3.要根据i的值获取字符串中的字符,推荐使用charAt方法
System.out.println(str.charAt(i));
}
System.out.println("===========================");
//4.直接现将字符串转换成字符数组,推荐使用toCharArray
char[] chars = str.toCharArray();
//5.遍历字符数组
for (int i = 0; i < chars.length; i++) {
System.out.println(chars[i]);
}
2.8 统计字符次数案例
案例需求 :
键盘录入一个字符串,使用程序实现在控制台遍历该字符串
实现步骤 :
代码实现 :
//1.创建键盘录入对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入:");
String str = sc.next();
//2.要统计字符串中大小写字符,数字字符的个数,你得先把字符串转换成数组
char[] chars = str.toCharArray();
//定义计数器,记录大小写字符和数字字符的个数
int bigCount = 0;
int smallCount = 0;
int numCount = 0;
//3.遍历字符数组
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
//4.拿到字符之后,该判断这个字符是属于哪一个区间
if (c >= '0' & c <= '9') {
//5.统计小写字符出现的次数
numCount++;
} else if (c >= 'a' && c <= 'z') {
smallCount++;
//因为除了大小写字母和数字字符,还有其他字符,所以不能直接用else
} else if (c >= 'A' & c <= 'Z') {
bigCount++;
}
}
//6.循环结束,打印各个字符的个数
System.out.println(numCount);
System.out.println(smallCount);
System.out.println(bigCount);
2.9 手机号屏蔽-字符串截取
案例需求 :
以字符串的形式从键盘接受一个手机号,将中间四位号码屏蔽
最终效果为:1561234
实现步骤 :
代码实现 :
//1.使用键盘录入
Scanner sc = new Scanner(System.in);
System.out.println("请输入手机号:");
String telPhone = sc.next();
//2.假设录入的字符串是13912341234,接下来开始针对这个字符串进行截取操作
//如果要替换中间四个数字,变为*,可以截取前三个和后四个,中间拼接****
//使用substring方法,截取前三个,调用方法截取后,调用方法的字符串不变,只是返回一个新的字符串
String start = telPhone.substring(0, 3);
//3.拿结尾的四个
String end = telPhone.substring(7);
//4.最后把头+****+尾进行拼接
System.out.println(start + "****" + end);
2.10 敏感词替换-字符串替换
案例需求 :
键盘录入一个 字符串,如果字符串中包含(TMD),则使用***替换
实现步骤 :
键盘录入一个字符串,用 Scanner 实现
替换敏感词
String replace(CharSequence target, CharSequence replacement)
将当前字符串中的target内容,使用replacement进行替换,返回新的字符串
CharSquence:以后如果你看到方法的形式参数是它,说明就丢字符串进去就可以了。它是字符串的干爹。
输出结果
代码实现 :
//1.创建键盘录入对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入一句话:");
String str = sc.next();
//2.把字符串中非法字符串使用***替换,核心方法是replace
str = str.replace("TMD", "***");
//3.打印替换后的字符串
System.out.println(str);
课后练习:
/**
* 需求:
* 1.键盘录入一个初始字符串,例如:I love heima,heiheimama love me
* 2.再使用键盘录入一个目标字符串,可以将初始字符串中的目标字符串删除
* 3.在控制台打印处理后的字符串内容,例如输入目标字符串:heima,控制台输出:
* I love , love me
*/
2.11 切割字符串
案例需求 :
以字符串的形式从键盘录入学生信息,例如:“张三 , 23”
从该字符串中切割出有效数据,封装为Student学生对象
实现步骤 :
代码实现 :
//1.键盘录入
Scanner sc = new Scanner(System.in);
System.out.println("请输入:");
String str = sc.nextLine();
//2.针对字符串做切割操作,以逗号座位分隔进行切割,按照题意,切出来有2个部分
String[] strs = str.split(",");
//结果返回的是一个字符串数组,说明切出来的是多个字符串,根据题意,切出来2个
System.out.println(strs[0]);
System.out.println(strs[1]);
//3.一般情况下,在工作中,如果我们获取到了零散的数据,我们通常都会使用一个对象将其封装起来
//专门用来封装数据的类,一般放在domain包下
//创建学生对象,存储数据
Student stu = new Student(strs[0], strs[1]);
System.out.println(stu.getName() + "的年龄是" + stu.getAge());
2.12 String方法小结
String类的常用方法 :
方法名 返回值类型 说明
equals(Object anObject) boolean 比较字符串的内容,严格区分大小写
equalsIgnoreCase(String anotherString) boolean 比较字符串的内容,忽略大小写
length() int 返回此字符串的长度
charAt(int index) char 返回指定索引处的 char 值
toCharArray() char[] 将字符串拆分为字符数组后返回
substring(int beginIndex, int endIndex) String 根据开始和结束索引进行截取,得到新的字符串(包含头,不包含尾)
substring(int beginIndex) String 从传入的索引处截取,截取到末尾,得到新的字符串
replace(CharSequence target, CharSequence replacement) String 使用新值,将字符串中的旧值替换,得到新的字符串
split(String regex) String[] 根据传入的规则切割字符串,得到字符串数组
3.1 StringBuilder类概述
问题:
1.使用StringBuilder有什么好处?
2.如何获取1970-01-01 00:00:00到系统当前时间所经历的毫秒值?
3.将一段代码抽取到方法中的快捷键是什么?
概述 : StringBuilder 是一个可变的字符串类,我们可以把它看成是一个容器,这里的可变指的是 StringBuilder 对象中的内容是可变的
作用:提高字符串的操作效率
System.currentTimeMillis():获取1970年1月1日0时0分0秒到当前时间所经历过的毫秒值
代码练习:
//练习:分别用String和StringBuilder操作字符串,对比两者操作的时间
public class Test01 {
public static void main(String[] args) {
//1.对比String和StringBuilder操作字符串消耗的时间
method1();
method2();
}
public static void method1() {
//2.在操作字符串之前,获取系统当前时间的毫秒值
long start = System.currentTimeMillis();
String s = "";
for (int i = 0; i < 50000; i++) {
s += i;
}
//操作之后,再去获取系统的毫秒值
long end = System.currentTimeMillis();
System.out.println(end - start);
}
public static void method2() {
//2.在操作字符串之前,获取系统当前时间的毫秒值
long start = System.currentTimeMillis();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 50000; i++) {
builder = builder.append(i);
}
//操作之后,再去获取系统的毫秒值
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}
3.2 StringBuilder类的构造方法
问题:
1.打印用空参构造方法创建的StringBuilder对象,会有什么结果?
2.打印用带参构造方法创建的StringBuilder对象,会有什么结果?
常用的构造方法
方法名 说明
public StringBuilder() 创建一个空白可变字符串对象,不含有任何内容
public StringBuilder(String str) 根据字符串的内容,来创建可变字符串对象
示例代码
public class StringBuilderDemo01 {
public static void main(String[] args) {
//public StringBuilder():创建一个空白可变字符串对象,不含有任何内容
StringBuilder sb = new StringBuilder();
System.out.println("sb:" + sb);
System.out.println("sb.length():" + sb.length());
//public StringBuilder(String str):根据字符串的内容,来创建可变字符串对象
StringBuilder sb2 = new StringBuilder("hello");
System.out.println("sb2:" + sb2);
System.out.println("sb2.length():" + sb2.length());
}
}
3.3 StringBuilder常用的成员方法
问题:
1.StringBuilder有哪几种常见的功能方法?
2.StringBuilder对象是否可以添加不同的数据类型到容器中?
3.StringBuilder的append方法返回对象自己,有什么作用?
添加和反转方法
方法名 说明
public StringBuilder append(任意类型) 添加数据,并返回对象本身
public StringBuilder reverse() 返回相反的字符序列
public int length() 返回长度(字符出现的个数)
public String toString() 把StringBuilder转换为String
示例代码
//需求:创建一个StringBuilder对象,分别调用几个成员方法,观察效果
3.4 StringBuilder提高效率的原理
原理图:
字符串的加法拼接:
StringBuilder拼接:
StringBuilder类和String类的区别:
3.5 对称字符串案例:String和StringBuilder之间的相互转换
需求:键盘接收一个字符串,程序判断该字符串是否是对称字符串,并在控制台打印是或不是
思路:
代码实现:
//1.键盘录入
Scanner sc = new Scanner(System.in);
System.out.println(“请输入一个对称字符串:”);
String str = sc.nextLine();
//2.要判断一个字符串是不是对称字符串,把这个字符串反转一下,然后对比内容
//如果反转后的内容和反转前的内容一样,就属于对称字符串,比如123321
//要把字符串进行反转,这个时候我们就要想,字符串对象自己能不能做?
//查了api,发现不能做。这个时候要想,和字符串相关的工具还有哪些?想到了StringBuilder
//就去查api,发现了一个reverse方法可以做到
//3.通过构造方法把String变成StringBuilder
StringBuilder sb = new StringBuilder(str);
//4.调用reverse反转
sb.reverse();
//5.将反转后的字符串内容和原字符串内容比较
//注意,这里要保证都是字符串类型比较,所以sb要转成String
if (str.equals(sb.toString())) {
System.out.println(“是对称字符串”);
} else {
System.out.println(“不是对称字符串”);
}
StringBuilder转换为String
public String toString():通过 toString() 就可以实现把 StringBuilder 转换为 String
String转换为StringBuilder
public StringBuilder(String s):通过构造方法就可以实现把 String 转换为 StringBuilder
3.6 StringBuilder拼接字符串案例
需求 :
实现步骤 :
代码实现 :
public class Test03 {
public static void main(String[] args) {
//1.静态初始化
int[] arr = {1, 2, 3};
String str = getStr(arr);
System.out.println(str);
}
public static String getStr(int[] arr) {
//2.要操作字符串,就要创建StringBuilder对象,去做拼接
//拼接的数据从数组中来,所以还要遍历数组
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < arr.length; i++) {
//3.直接拼接不太好,因为字符串里面有特殊的格式,以中括号开始,而且是拼接数据之前
//开始拼接数字,但是有区别,最后一个跟中括号的结束
if (i == arr.length - 1) {
//是最后一个元素,拼接的时候不能拼逗号
sb.append(arr[i]).append("]");
} else {
sb.append(arr[i]).append(",");
}
}
//4.方法返回的是字符串,要转一下
return sb.toString();
}
}
1.1 集合和数组的区别对比
问题:
1.相对于数组,集合容器有什么特点?
2.在什么情况下,更推荐使用集合容器存放数据?
1.2 ArrayList的构造方法和添加方法
问题:
1.ArrayList集合的大小可变,底层是通过什么实现的?数组
2.通过空参构造创建的ArrayList集合对象,初始容量是多少?10
3.ArrayList集合可以存放多种数据类型的数据吗?可以
4.如何指定ArrayLList集合只存储特定的数据类型?加一个泛型
public ArrayList() 创建一个空的集合对象
public boolean add(E e) 将指定的元素追加到此集合的末尾
public void add(int index,E element) 在此集合中的指定位置插入指定的元素
ArrayList :
可调整大小的数组实现
: 是一种特殊的数据类型,泛型。
泛型可以代表一种不确定的类型,类型的确定在声明这个类的变量的时候
注意,不是所有的类都可以加泛型哦。目前你只在ArrayList后面加泛型
怎么用呢 ?
在出现E的地方我们使用引用数据类型替换即可
举例:ArrayList, ArrayList
练习:
/**
1.3 ArrayList类常用方法
问题:
1.调用ArrayList集合删除的功能,可以返回哪些数据类型?
2.调用ArrayList集合的修改指定位置元素的方法,返回值是什么?
成员方法 :
public boolean remove(Object o) 删除指定的元素,返回删除是否成功
public E remove(int index) 删除指定索引处的元素,返回被删除的元素
public E set(int index,E element) 修改指定索引处的元素,返回被修改的元素
public E get(int index) 返回指定索引处的元素
public int size() 返回集合中的元素的个数
示例代码 :
//练习:创建一个集合,用来存储和管理学生对象数据
//增加数据
//删除数据
System.out.println("======删除数据======");
//指定位置删除
System.out.println("======修改数据======");
System.out.println("======获取数据======");
System.out.println("======获取集合长度======");
1.4 案例:ArrayList存储字符串并遍历
案例需求 :
创建一个存储字符串的集合,存储3个字符串元素,使用程序实现在控制台遍历该集合
实现步骤 :
代码实现 :
//1.创建集合
ArrayList hanzimen = new ArrayList<>();
//2.使用add方法添加3个字符串
hanzimen.add("王宝强");
hanzimen.add("贾乃亮");
hanzimen.add("吴签");
//3.使用循环遍历集合。集合提供了size()方法,可以获取集合的长度
for (int i = 0; i < hanzimen.size(); i++) {
//4.使用集合get方法可以获取集合中的元素,根据索引获取
String hanzi = hanzimen.get(i);
System.out.println(hanzi);
}
1.5 案例:ArrayList存储学生对象并遍历
案例需求 :
创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
实现步骤 :
代码实现 :
//1.创建集合,用于存储学生对象,这里存储的数据是学生对象,类型指定为Student
//注意,如果没有Student类,要先去创建Student类
ArrayList stus = new ArrayList<>();
//在一个类中使用了另外一个包下的类,就需要先导包才能使用,idea可以自动导包
//2.创建学生对象,封装学生数据
Student stu1 = new Student("张三", 23, 98.8, "男");
Student stu2 = new Student("李四", 24, 96.8, "女");
Student stu3 = new Student("王五", 20, 100, "男");
//3.使用集合容器,用add方法添加数据
stus.add(stu1);
stus.add(stu2);
stus.add(stu3);
//4.集合中有数据了,开始遍历集合
for (int i = 0; i < stus.size(); i++) {
//5.从集合中取出索引对应的学生对象,使用get方法
Student stu = stus.get(i);
//6.拿出来的是学生对象,不能直接打印,得调用学生对象的获取属性的方法
System.out.println(stu.getName() + "..." + stu.getAge());
}
1.6 案例:键盘录入学生信息到集合
案例需求 :
创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
学生的姓名和年龄来自于键盘录入
实现步骤 :
代码实现 :
public class Test05 {
public static void main(String[] args) {
//1.创建集合,用来存储Student对象
ArrayList stus = new ArrayList<>();
//2.键盘录入学生信息,封装成学生对象,使用循环录入也可以,但是比较麻烦
//为了提高代码的复用性,可以把录入学生数据的这些代码使用方法封装起来
//6.利用写好的方法获取3次学生对象
Student stu1 = getStudent();
Student stu2 = getStudent();
Student stu3 = getStudent();
//7.将对象存储到集合中
stus.add(stu1);
stus.add(stu2);
stus.add(stu3);
//8.遍历集合,打印学生数据
for (int i = 0; i < stus.size(); i++) {
//9.通过集合get方法获取集合中存储的学生对象
Student stu = stus.get(i);
//10.通过学生对象的get方法获取属性
System.out.println(stu.getName() + "..." + stu.getAge());
}
}
//3.定义一个获取学生对象的方法,这个方法返回值就是Student类型
public static Student getStudent() {
//4.创建键盘录入对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入学生姓名:");
String name = sc.next();
System.out.println("请输入学生年龄:");
int age = sc.nextInt();
System.out.println("请输入学生分数:");
double score = sc.nextDouble();
System.out.println("请输入学生性别:");
String sex = sc.next();
//5.有了零散的学生数据,封装成学生对象管理
Student stu = new Student(name, age, score, sex);
//返回学生对象
return stu;
}
}
1.7 案例:集合删除元素
案例需求 :
创建一个存储String的集合,内部存储(test,张三,李四,test,test)字符串,删除所有的test字符串,删除后,将集合剩余元素打印在控制台
实现步骤 :
代码实现:
//1.创建集合
ArrayList strs = new ArrayList<>();
//2.存储几个字符串,用于测试
strs.add("test");
strs.add("张三");
strs.add("李四");
strs.add("test");
strs.add("test");
//3.删除集合中的test字符串,遍历集合,将里面的元素一个个取出来
for (int i = 0; i < strs.size(); i++) {
//4.使用get方法获取集合中的字符串
String s = strs.get(i);
//5.判断拿出来字符串s是否内容是test,如果是就删除
//这里要注意,为了防止空指针异常,使用字符串常量去调用equals方法
/*if (s.equals("test")) {
//这里不建议这么写,容易出现空指针
}*/
if ("test".equals(s)) {
//如果是test,就删除,调用集合的remove方法
strs.remove(i);
//6.集合删除一个元素后,后面的所有元素会往前挪动一位,如果此时索引不做操作
//就会导致所以继续往后,挪过来的第一个元素就会漏掉,应该让索引减1
i--;
}
}
//7.打印集合,看看是否删除
System.out.println(strs);
1.8 案例:集合数据筛选
案例需求 :
定义一个方法,方法接收一个集合对象(泛型为Student),方法内部将年龄低于18的学生对象找出并存入集合对象,方法返回新集合
实现步骤 :
代码实现:
public class Test07 {
public static void main(String[] args) {
//7.创建学生对象和集合,用于测试
ArrayList stus = new ArrayList<>();
stus.add(new Student("张三",23,98.0,"男"));
stus.add(new Student("李四",12,98.0,"男"));
stus.add(new Student("王五",15,98.0,"男"));
//8.调方法测试
ArrayList newStus = getStus(stus);
//打印新集合
for (int i = 0; i < newStus.size(); i++) {
Student stu = newStus.get(i);
System.out.println(stu.getName() + "..." + stu.getAge());
}
}
//1.定义一个方法,用于获取我们要的集合
public static ArrayList getStus(ArrayList stus) {
//2.方法内部遍历传过来的集合,把低于18岁的学生存入新集合
//创建一个新的集合
ArrayList newStus = new ArrayList<>();
//3.遍历传过来的集合
for (int i = 0; i < stus.size(); i++) {
//4.从集合中获取学生对象,并判断年龄
Student stu = stus.get(i);
if (stu.getAge() < 18) {
//5.把这个学生对象存入新集合
newStus.add(stu);
}
}
//6.返回新的集合对象
return newStus;
}
}
2.1 学生管理系统实现步骤
2.2 学生类的定义
package com.itheima.domain;
/**
* 该类用于存储和管理本系统的学生数据
*/
public class Student {
//属性:学号、姓名、年龄、生日,分别用成员变量代表
//为了提高安全性,使用private修饰属性
private String sid;
private String name;
private int age;
private String birthday;
//标准类的书写,写完了属性,就要写构造方法,空参和满参
public Student() {
}
public Student(String sid, String name, int age, String birthday) {
this.sid = sid;
this.name = name;
this.age = age;
this.birthday = birthday;
}
//属性被private修饰了,要给他们添加设置值和获取值的方法,以供外界使用
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
}
2.3 菜单搭建
/**
* 本类就是用于完成学生管理系统的核心功能,所以要加上主方法
*/
public class StudentManager {
public static void main(String[] args) {
//1.程序从这里开始,软件一旦运行,首先展示的页面就是它第一个需要完成的功能,菜单显示
//菜单显示:提示用户根据展示的信息录入选择,在根据选择执行不同的功能,这个过程可能有很多次
//技术体系:while死循环+switch选择结构
//2.展示菜单页面,用输出语句
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//5.到这一步,该选择只能完成1次,不符合软件的需求,要能够重复选择执行,不知道重复的次数
//使用while死循环,不用把创建键盘录入对象放进来,反复创建对象比较消耗内存
lo:
while (true) {
System.out.println("--------欢迎来到学生管理系统--------");
System.out.println("1 添加学生");
System.out.println("2 删除学生");
System.out.println("3 修改学生");
System.out.println("4 查看学生");
System.out.println("5 退出");
System.out.println("请输入您的选择:");
//3.录入选择,录入字符串,因为这样的话,你录入错了,也不会报错
String choice = sc.next();
//4.根据录入的内容,执行不同的分支,这是switch结构
switch (choice) {
case "1":
System.out.println("添加");
break;
case "2":
System.out.println("删除");
break;
case "3":
System.out.println("修改");
break;
case "4":
System.out.println("查看");
break;
case "5":
System.out.println("感谢您的使用");
//注意,break可以被switch和循环消费,这里要指定结束循环,使用标号的方式
break lo;
default:
System.out.println("您的输入有误,请检查后重试");
break;
}
}
}
}
2.4 添加学生:基本实现
public static void main(String[] args) {
//2.1 我们的学生数据是放到集合中存储的,先创建ArrayList集合
ArrayList stus = new ArrayList<>();
......
case "1":
// System.out.println("添加学生");
//2.2 定义一个方法来处理添加学生的逻辑
addStudent(stus);
break;
......
}
public static void addStudent(ArrayList stus) {
//2.3 提示用户键盘录入学生信息
Scanner sc = new Scanner(System.in);
System.out.println("请输入学号:");
String sid = sc.next();
System.out.println("请输入姓名:");
String name = sc.next();
System.out.println("请输入年龄:");
int age = sc.nextInt();
System.out.println("请输入生日:");
String birthday = sc.next();
//2.4 拥有了零散的学生信息,必须封装到学生对象中,方便管理
Student stu = new Student(sid, name, age, birthday);
//2.5 有了学生数据,将这个学生对象丢进通过方法的参数传递过来的集合中
stus.add(stu);
//方法需不需要返回集合对象?不需要,因为集合对象是引用数据类型,你对她的操作,主方法也能看到更改
}
2.5 查看学生代码实现
public static void main(String[] args) {
......
case "4":
//System.out.println("查看学生");
queryStudents(stus);
break;
......
}
/**
* 查看学生
*
* @param stus
*/
public static void queryStudents(ArrayList stus) {
//3.1 如果执行查询学生,不能马上就开始遍历,因为有可能传过来的集合是个空的
//先判断集合是否是空的,如果是空的,就可以提示用户,然后结束方法
if (stus.size() == 0) {
System.out.println("无数据,请添加后再查询");
//直接使用return结束方法,方法弹栈
return;
}
//3.2 在遍历之前,先把格式上的表头打印出来,让你知道打印的每一列分别是什么数据
System.out.println("学号\t\t姓名\t\t年龄\t\t生日");
//3.3 如果没有进入if语句,说明集合不是空的,可以打印。另外也不会结束方法
for (int i = 0; i < stus.size(); i++) {
//3.4 从集合中拿出学生对象
Student student = stus.get(i);
//3.5 开始打印数据
System.out.println(student.getSid() + "\t" + student.getName() + "\t" + student.getAge() + "\t\t" + student.getBirthday());
}
}
2.6 判断学号是否存在的方法定义
/**
* 定义一个方法用来返回学号在集合中对应的索引位置
* 需要提供集合、被查询的学号
* 返回的是索引
*/
public static int getIndex(ArrayList list, String sid) {
//4.1 定义一个变量代表要返回的索引值,现在没有开始判断,假设这个索引不存在,给个不存在的初始化值
int index = -1;
//4.2 遍历集合,拿出里面的学生对象
for (int i = 0; i < list.size(); i++) {
Student stu = list.get(i);
//4.3 从学生对象中拿出学号
String id = stu.getSid();
//4.4 开始判断从学生对象中拿出来的id是否和你传递过来的id内容相同
if (id.equals(sid)) {
//4.5 如果相同,说明学生集合中有你传过来的学号对应的学生,用集合中的索引替换index
index = i;
}
}
//4.6 循环结束,如果if语句一直没有进去过,index就是-1,那就是没找到
return index;
}
2.7 删除学生代码实现
public static void main(String[] args) {
......
case "2":
//System.out.println("删除学生");
deleteStudent(stus);
break;
......
}
/**
* 删除学生
* @param stus
*/
public static void deleteStudent(ArrayList stus) {
//5.1 提示用户录入要删除的学号
Scanner sc = new Scanner(System.in);
System.out.println("请输入要删除的学号:");
String delSid = sc.next();
//5.2 你输入的学号不一定就存在,如果不存在重新输入,存在才能删除,先判断输入的学号是否存在
//获取学号对应的索引的逻辑已经写好,调用getIndex方法即可
int index = getIndex(stus, delSid);
//5.3 判断index的值,如果index是-1,就说明没找到,否则就找到了
if (index == -1) {
//5.4 没找到,提示用户
System.out.println("查无此人,请重新输入");
} else {
//5.5 找到了,就可以根据索引,直接从集合中删除学生对象
stus.remove(index);
System.out.println("删除成功!");
}
}
2.8 修改学生代码实现
public static void main(String[] args) {
......
case "3":
//System.out.println("修改学生");
updateStudent(stus);
break;
......
}
/**
* 修改学生
* @param stus
*/
public static void updateStudent(ArrayList stus) {
//6.1 键盘录入需要修改的学生学号,判断是否存在,不存在重新输入。存在,就开始修改
//逻辑和删除一样,直接复制代码
//6.2 提示用户录入要修改的学号
Scanner sc = new Scanner(System.in);
System.out.println("请输入要修改的学号:");
String updateSid = sc.next();
int index = getIndex(stus, updateSid);
//6.3 判断index的值,如果index是-1,就说明没找到,否则就找到了
if (index == -1) {
//6.4 没找到,提示用户
System.out.println("查无此人,请重新输入");
} else {
//6.5 找到了,就要开始修改,你要录入修改的内容
System.out.println("请输入新的学生姓名:");
String name = sc.next();
System.out.println("请输入新的学生年龄:");
int age = sc.nextInt();
System.out.println("请输入新的学生生日:");
String birthday = sc.next();
//6.6 有了学生数据,重新封装到学生对象中
Student stu = new Student(updateSid, name, age, birthday);
//6.7 把这个学生对象,改到集合中,使用集合的set方法
stus.set(index, stu);
System.out.println("修改成功!");
}
}
2.9 解决添加学生学号重复的问题
public static void addStudent(ArrayList stus) {
//2.3 提示用户键盘录入学生信息
Scanner sc = new Scanner(System.in);
//7.1 输入学号,如果存在就得重新输入学号,因为不能添加已存在的学生,无法判断输入多少次成功
String sid;
while (true) {
System.out.println("请输入学号:");
sid = sc.next();
//7.2 调用getIndex方法,判断你输入的学号是否存在
int index = getIndex(stus, sid);
if (index == -1) {
//不存在,可以继续输入,结束这个死循环
break;
}
}
System.out.println("请输入姓名:");
String name = sc.next();
System.out.println("请输入年龄:");
int age = sc.nextInt();
System.out.println("请输入生日:");
String birthday = sc.next();
//2.4 拥有了零散的学生信息,必须封装到学生对象中,方便管理
Student stu = new Student(sid, name, age, birthday);
//2.5 有了学生数据,将这个学生对象丢进通过方法的参数传递过来的集合中
stus.add(stu);
System.out.println("添加成功!");
//方法需不需要返回集合对象?不需要,因为集合对象引用数据类型,你对她的操作,主方法也能看到更改
}