JAVA基础学习
一. java环境的配置及JDK下载安装
- 浏览器搜索Oracle进入官网点击product并点击java,选择JDK对应电脑系统版本进行下载(由于处于学习阶段最好选择JDK17后期可使用最新版本)这里直接以windows11为例:JDK下载直链
- 下载安装完成之后可进行环境配置检验,打开此电脑找到JDK下载的位置并鼠标点击图中红色箭头(现象:程序不被打开反而一闪而过)即可安装成功
二.基本HelloWorld语法及IDEA下载
-
按win+r键打开命令窗输入cmd回车进入运行窗口 下面是几个常用的运行符号
-
java记事本编译运行代码为javac HelloWorld.java和java HelloWorld。**区别:**javac HelloWorld.java编译后会在bin文件下新出现一个编译后的文件,而java HelloWorld不会出现
-
由于记事本方式进行编译比较麻烦,我们选择IDEA进行编译IDEA下载链接 IDEA分为旗舰版(收费)与社区版(免费),根据自己需求先下载即可。下载安装完成后打开软件新建文件即可在线运行
-
public class HelloWorld{ public static void main(String[] args){ System.out.println("Hello World"); } }
红线部分必须相同否则无法运行点击运行并出现Hello World代表运行成功
三.IDEA的入门使用及快捷键
-
idea项目结构介绍 1.project(项目,工程)2module(模块)3.package(包)4.class(类)结构的划分方便文件的管理与代码的划分
-
快捷键
-
导入模块 建议:新建模块→复制文件→粘贴到新建模块
四.JAVA基础语法
1. 注释
在程序中对代码进行解释说明的文字,方便自己或其他人理解·查看,不影响程序的正常运行
2. 字面量
- 告诉程序员,数据在程序中的书写格式。下面是实际演示!
3. 变量
:变量就是用来储存一个数据的内存区域(可以理解成一个盒子),且里面储存的数据可以变化
int(整数类型),double(小数类型)下面是实际演示定义变量要注意的问题:
4.二进制
计算器调用:按win+r输入calc
5.数据类型的分类
下面是详细实操与讲解!
- ASCLL编码:编号规则
6. 关键字
- :不能用关键字作为类名或者变量名称下面是实际演示
7.标识符
- :标识符就是有一些字符·符号组成的名称,用于给类,方法,变量起名字的规矩演示如下
8.自动强制类型转换
:类型范围小的变量,可以直接赋值给类型范围大的变量
在表达式中,byte short char 直接转化成int类型参与运算
可以将类型范围大的变量·数据赋值给类型范围小的变量。要求:要在变量前面加上数据类型下面是实际操作演示
9.运算符
+既可以参与数学运算,也可以做连接符。当数无法运算时,+就做连接符下图是演示能算则算,不能算就连接演示
实际操作
实际操作
实际操作
- 三元运算符
- 运算符优先级
五.if switch for while 的循环及穿透
1.if switch的分支
- if其实在功能上远远强大于switch
- if适合做区间分配
- switch适合做:值匹配的分支选择,代码优雅
实际操作
实际操作
注意事项的演示 break的穿透性
2.for循环及求和,水仙花数案例
实际演示
求奇数和
水仙花数案例实现
3.while循环,珠穆朗玛峰案例
珠穆朗玛峰案例
4.闰年判断
基本知识
普通闰年:公历年份是4的倍数且不是100的倍数为普通闰年(如2004、2020年就是闰年)。
世纪闰年:公历年份是整百数的,必须是400的倍数才是世界闰年(如2000是世纪闰年,1900不是世纪闰年)。
总结:能被4整除却不能被100整除或能被400整除的年份就是闰年!
import java.util.Scanner;
public class runnian {
public static void main(String[] args) {
// 能被4整除却不能被100整除或能被400整除的年份就是闰年!
Scanner sc=new Scanner(System.in);
System.out.println("请输入年份:");
int i=sc.nextInt();
if(i%4==0 && i%100!=0 || i%400==0) //与或
{
System.out.println("是闰年");
}
else
{
System.out.println("不是闰年");
}
}
}
六.数组
- 什么是数组:数组就是用来储存一批同类型数据的内存区域(可以直接理解成区域)。数组分为:静态初始化数组和动态初始态数组
- ***“数据类型【】数组名”*也可以写成“数据类型 数组名
- 当前已经知道存入的元素值,用静态初始化
当前还不清楚要存入哪些数据,用动态初始化
1.静态初始化数组:
2.访问数组
3.动态初始化数组:
定义数组的时候只确定元素的类型和数组的长度,之后再存入具体数据。
4.遍历:
1.遍历元素求和
2.数组求最值
3.猜数字游戏
4.随机排名
5.冒泡排序
数组变量传递给另一个数组
七.方法
方法事一种语言结构,它可以把一段代码封装成一个功能,以便重复调用
使用方法前的代码:
使用方法后的代码:
1.方法定义格式
2.完整方法的调用与使用以及其他方法的写法
多种调用方式
3.方法案例:求和,判断奇偶数,求最值
求和
判断奇偶
求最值
4.方法参数传递机制
- 基本类型的参数传递
- 引用类型的参数传递
先写方法,后调用
5.打印整型数组内容
该数组内容为:【11,22,33,44,55】
分析:
1.定义一个方法,要求该方法能够接收数组,并输出数组内容。
2.定义一个静态初始化的数组,调用该方法,并传入该数组
6.从数组中查询指定元素的索引
需求:存在则输出索引,不存在则返回-1
7.判断两个数组的数据是否相同
相同true,不同false
8.重载方法
同一个类中,出现多个方法名称相同,但是形参列表是不同的,那么 这些方法叫做重载方法。
使用重载方法的好处:对于相似功能的业务场景:可读性好,方法名称相同提示是统一类型的功能,通过形参不同实现功能差异化的选择,这是一种专业化的代码。
1.重载方法的识别技巧
只要是同一个类中,方法名称相同,形参列表不同,那么他们就是重载的方法,其他都不管!(如:修饰符,返回值类型都无所谓)
9.return关键字单独使用
return可以立即跳出并结束当前方法的执行;return关键字单独使用可以放在任何方法中。
如果b=0,则可用到return作用
八.案例实现
1.买飞机票
package com.itheima;
import java.util.Scanner;
public class honmwork1 {
public static void main(String[] args) {
//旺季(5~10月)头等舱9折,经济舱8.5折,淡季(11月到来年4月)头等舱7折,经济舱6.5折
//录入购买信息,调用方法
Scanner sc=new Scanner(System.in);
System.out.println("机票原价:");
double price=sc.nextDouble();
System.out.println("月份");
int month=sc.nextInt();
System.out.println("仓位类型(头等舱,经济舱)");
String type=sc.next();
double rs= calc(price,month,type);
System.out.println("您当前购买的机票价格是:"+rs);
}
public static double calc(double money,int month,String type){
//判断月份是淡季还是旺季
if(month>=5&&month<=10){
//旺季
switch (type){
case"经济舱":
money*=0.85;
break;
case"头等舱":
money*=0.9;
break;
default:
System.out.println("您输入的仓位不正确");
money=-1; //直接结束,无法计算结果
}
}else if(month==11||month==12||month>=1&&month<=4) {
//淡季
switch (type) {
case "经济舱":
money *= 0.65;
break;
case "头等舱":
money *= 0.7;
break;
default:
System.out.println("您输入的仓位不正确");
money = -1; //直接结束,无法计算结果
}
}else{
System.out.println("月份有问题");
money=-1; //直接结束,无法计算结果
}
return money;
}
}
2.找素数
说明
素数:如果除了1和它本身以外,不能被其他正整数整除,就叫素数。
分
101-200之间的数据可以采用循环依次拿到; 每拿到一个数,判断该数是否是素数
判断规则是:从2开始遍历到该数的一半的数据,看是否有数据可以整除它,有则不是素数,没有则是素数
3.验证码
package com.itheima;
import java.util.Random;
public class homewolk3 {
public static void main(String[] args) {
//调用方法
String code = createCode(5);
System.out.println("随机验证码"+code);
}
public static String createCode(int n){
//1.定义一个字符串变量记录生成的随机字符
String code="";
Random r =new Random();
//定义一个循环,循环n次
for (int i = 0; i < n; i++) {
//生成一个随机字符串,英文大写,英文小写,数字0,1,2
int type=r.nextInt(3);//0,1,2
switch (type){
case 0:
//大写字符(A65~ Z 65+25)减加法 (0-25)+65
char ch=(char)(r.nextInt(26)+65);
code+=ch;
break;
case 1:
//大写字符(a 97~ z 97+25)减加法 (0-25)+97
char ch1=(char)(r.nextInt(26)+97);
code+=ch1;
break;
case 2:
//数字
code+=r.nextInt(10);//0~9
break;
}
}
return code;
}
}
4.数组的复制
package com.itheima;
public class homework4 {
//数组的赋值拷贝
public static void main(String[] args) {
int []arr1={11,22,33,44};
int[]arr2=new int[arr1.length];
copy(arr1,arr2);
printArray(arr1);
printArray(arr2);
}
public static void printArray(int[]arr){
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
System.out.print(i==arr.length-1?arr[i]:arr[i]+",");
}
System.out.println("]");
}
public static void copy(int[]arr1,int[]arr2){
for (int i = 0; i < arr1.length; i++) {
arr2[i]=arr1[i];
}
}
}
5.评委打分
需求:在唱歌比赛中,有6名评委给选手打分,分数范围是0~100之间的整数。选手最后的得分位:去掉最高分和最低分后的4个评委打分的平均数,请完成上述过程计算出选手的得分。
分析:①把6个评委的分数录入到程序中去······>使用数组
int [ ] scores = new int [6 ] ;
②遍历数组中每个数据,进行累加求和,并找出最高分,最低分。
③按照分数的规则算出平均分
package com.itheima;
import java.util.Scanner;
public class homework5 {
public static void main(String[] args) {
//1.定义一个动态初始化数组,用于后期录入6个评委的分数
int[]scores= new int [6];
//录入6各评委打分
Scanner sc= new Scanner(System.in);
for (int i = 0; i < scores.length; i++) {
System.out.println("请您输入第"+(i+1)+"个评委打分:");
int score=sc.nextInt();
//把这个分数存入对应的数组位置
scores[i]=score;
}
//遍历数组中的每个数据,找出最大值,最小值,总分
int max=scores[0];
int min=scores[0];
int sum=0;
for (int i = 0; i < scores.length; i++) {
if (scores[i] > max) {
max = scores[i];
}
if (scores[i] < min) {
min = scores[i];
}
sum +=scores[i];
}
System.out.println("最高分是"+max);
System.out.println("最低分是"+min);
//按平均分算出即可
double result= (sum-max-min)*1.0/(scores.length-2);
System.out.println("选手的总分是"+result);
}
}
6.数字加密
需求:某系统的数字密码,比如1983,采用加密的方式进行传输,规则如下:先得到每位数,然后每位数都加上5,再对10求余,最后将所有数字反转,得到一串新数
package com.itheima;
public class homework6 {
public static void main(String[] args) {
//定义一个数组存储需要加密的数据
int [] arr= new int [] {1,9,8,3};
//遍历数组中的每个数据,按照规则进行修改
for (int i = 0; i < arr.length; i++) {
arr[i]=(arr[i]+5)%10;
}
//把数组中的元素进行反转操作
for (int i = 0,j= arr.length-1; i < j; i++,j--) {
//交换i和j的值即可完成反转
int temp=arr[j];
arr[j]=arr[i];
arr[i]=temp;
}
//遍历数组中的每个元素输出即可
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
}
}
}
7.双色球项目
要求:一共投注7个球,红球6个 1~33之间号码,不能重复。篮球1个,1-16之间号码
分析:第一步:用户投注一组号码
第二步:随机生成一组中奖号码
第三步:判断中奖详情
package com.itheima;
import java.util.Random;
import java.util.Scanner;
public class shuangseqiu1 {
public static void main(String[] args) {
//完成双色球系统的开发!!!
int []userNumbers=userSelectNumber();
System.out.println("投注的号码");
printArray(userNumbers);
int[]luckNumbers= createLuckNumbers();
System.out.println("中奖的号码");
printArray(luckNumbers);
judge(userNumbers,luckNumbers);
}
// 第一步:用户投注一组中奖号码
public static void printArray(int []arr){
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
System.out.print(i== arr.length-1?arr[i]:arr[i]+",");
}
System.out.println("]");
}
//设计一个方法
public static int [] userSelectNumber() {
//创建一个整型数组
int[] numbers = new int[7];
//numbers=[0,0,0,0,0,0,0]
// 0 1 2 3 4 5 6
Scanner sc = new Scanner(System.in);
//遍历前6个位置的数组,让用户依次输入前6个红球号码
for (int i = 0; i < numbers.length - 1; i++) {
while (true) {
System.out.println("请您输入第" + (i + 1) + "个红球号码(1~33之间)");
int number = sc.nextInt();
//先判断红球号码是否在1~33之间
if (number < 1 || number > 33) {
System.out.println("对不起,您输入的红球号码不在1~33之间,请确认!");
} else {
//号码在此区间,还需要判断号码是否重复
if(exist(numbers, number)){
//号码重复
System.out.println("对不起,您当前输入的红球号码以前投注过,重复了,请确认!");
}else {
//不重复
numbers[i]=number;
break;//结束当次投注,结束当次死循环
}
}
}
}
while (true) {
//投注最后一个蓝球号码
System.out.println("请您输入最后一个蓝球号码(1~16)之间");
int number =sc.nextInt();
if(number<1||number>16){
System.out.println("对不起,您当前输入的蓝球号码不对!");
}else{
numbers[6]=number;
break;//录入成功,结束死循环
}
}
return numbers;
}
private static boolean exist(int[] numbers, int number) {
//需求:判断number这个数是否在numbers数组中存在,判断是否在输入前之前就存在了
for (int i = 0; i < numbers.length; i++) {
if(numbers[i]==number){
return true;
}
}
return false;
}
//第二步:随机生成一组中奖号码
public static int[] createLuckNumbers(){
//创建一个整型数组,用于存储这7个数
int[]numbers=new int[7];
Random r = new Random();
//遍历6个位置处,依次随机一个红球号码1~33不重复
for (int i = 0; i < numbers.length-1; i++) {
//i=1 2 3 4 5
while (true) {
//为当前位置随机一个红球号码存储起来,减加法 1·~33==》-1==》(0,32)+1
int number =r.nextInt(33)+1;
//判断这个号码之前是否出现过,红色号码不能重复
if(!exist(numbers ,number)){
//不重复
numbers[i]=number;
break;//结束死循环,代表找到了当前这个位置的一个不重复的红色号码了。
}
}
}
//录入一个篮球号码 1~16
numbers[6]=r.nextInt(6)+1;
return numbers;
}
//第三步:判断中奖情况
public static void judge(int []userNumbers,int[] luckNumber){
//userNumber=[12,14,16,18,23,26,8]
//luckNumber=[16,17,18,19,26,32,8]
//分别定义2个变量用于记录红球命中几个,篮球命中几个
int redCount=0;
int blueCount=0;
//遍历用户投注的6个红球
//判断红球的命中数量
for (int i = 0; i < userNumbers.length-1; i++) {
for (int j = 0; j < luckNumber.length-1; j++) {
if(userNumbers[i]==luckNumber[j]){
redCount++;
break;
}
}
}
// 判断篮球的命中数量
blueCount = userNumbers[6]==luckNumber[6]?1:0;
System.out.println("您命中的红球数量是:"+redCount);
System.out.println("您命中的蓝球数量是:"+blueCount);
//判断中奖详情,并输出
if(redCount==6&&blueCount==0){
System.out.println("恭喜您,中奖1000万");
}else if(redCount==6&&blueCount==1){
System.out.println("恭喜您,中奖500万");
}else if(redCount==5&&blueCount==1) {
System.out.println("恭喜您,中奖3000元");
}else if(redCount==5&&blueCount==0) {
System.out.println("恭喜您,中奖200元");
}else if(redCount==4&&blueCount==0) {
System.out.println("恭喜您,中奖10元");
} else if(redCount<3&&blueCount==1) {
System.out.println("恭喜您,中奖5元");
}else {
System.out.println("感谢您对福彩的支持");
}
}
}
九.面向对象基础
在java中,必须先设计类,才能获得对象。
类(设计图):是对象共同特征的描述;
对象:是真实存在的具体实例。
如何定义类:
public class 类名{
1.成员变量(代表属性,一般是名词)
2.成员方法(代表行为,一般是动词)
3.构造器 (后面学习)
4.代码块 (后面学习)
5.内部类 (后面学习)
}
public class Car{
//属性(成员变量)
String name;
double price;
//行为(方法)
public void start(){
}
public void run(){
}
}
如何得到类的对象
类名 对象名 = new 类名();
Car c = new Car ();
注意事项
- 成员变量的完整定义格式是:修饰符 数据类型 变量名称=初始化值;一般无需指明初始值,存在默认值。
- 类名首字母建议大写
- 一个java文件中可以定义多个class类,且只能有一个类是public修饰,而且public修饰的类名必须成为代码文件名。实际开发中建议还是一个文件定义一个class类。
1.模拟购物车案例
- 需求分析,架构搭建
- 添加商品到购物车,查询购物车信息
- 修改购买数量
- 结算金额
①架构搭建
需求:模拟购物车模块的功能,需要实现添加商品到购物车中去,同时需要提供修改商品的购买数量,结算商品价格功能(使用面向对象面向对象编程来解决)
分析:
- 购物车中的每个商品都是一个对象,需要定义一个商品类
- 购物车本身也是一个对象:可以使用数组对象代表它。
- 完成界面架构,让用户选择操作的功能
②添加商品到购物车,查看购物车信息
需求:让用户输入商品信息,并加入到购物车中去,且可立即查看购物车信息
分析:
- 需要让用户录入商品信息,创建商品对象封装商品信息
- 并把商品对象加入到购物车数组中去
- 查询购物车信息,就是遍历购物车数组中的每个商品对象
③修改购买数量
需求:让用户输入商品id,找出对应的商品修改其购买数量
分析:
- 定义方法能够根据用户输入的id去购物车数组中查看是否存在该商品对象
- 存在返回该商品对象的地址,不存在返回null
- 判断返回的对象地址是否存在,存在修改其购买数量,不存在就继续
④结算支付金额
需求:当用户输入了pay命令后,需要展示全部购买的商品信息和总金额。
分析:定义求和变量,遍历购物车数组中的全部商品,累加其单价*购买数量
package com.itheima.creat;
import java.util.Scanner;
public class ShopCarTest {
public static void main(String[] args) {
//1.定义商品类,用于后期创建商品对象
//2.定义购物车对象,使用一个数组对象表示
Goods[] shopCar = new Goods[100];//[null,null······]
//3.搭建操作架构
while (true) {
System.out.println("请您选择如下命令进行操作:");
System.out.println("添加商品到购物车:add");
System.out.println("查询购物车商品展示:query");
System.out.println("修改商品购买数量:update");
System.out.println("结算购买商品的金额:pay");
Scanner sc = new Scanner(System.in);
System.out.println("请您输入命令:");
String command = sc.next(); //调用口令
//用一个switch循环
switch (command) {
case "add":
//添加商品到购物车
addGoods(shopCar, sc);
break;
case "query":
//查询购物车商品展示
queryGoods(shopCar);
break;
case "update":
//修改商品购买数量
updateGoods(shopCar, sc);
break;
case "pay":
//结算金额
pay(shopCar);
break;
default:
System.out.println("没有该功能!");
}
}
}
public static void pay(Goods[] shopCar) {
queryGoods(shopCar);//查一下数据
//1.定义一个求和变量累加金额
double money=0;
//2.遍历购物车数组中的全部商品对象,累加单价*数量
//[g1,g2,g3,null]
for (int i = 0; i < shopCar.length; i++) {
Goods g=shopCar[i];
if(g!=null){
money+=(g.price*g.buyNumber);
}else {
break;
}
}
System.out.println("订单金额:"+money);
}
public static void updateGoods(Goods[] shopCar,Scanner sc) {
//让用户输入要修改商品的id,根据id查询出要修改的商品金额. //此功能不能写在此方法内,要新创建一个方法,以便后面还会用到此功能
while (true) {
System.out.println("请您输入要修改的商品id:");
int id = sc.nextInt();
Goods g = getGoodsById(shopCar, id);
if (g == null) {
//没有商品
System.out.println("对不起,没有购买商品!");
} else {
//说明存在商品对象,可以修改它了
System.out.println("请您输入:"+g.name+"商品最新购买数量:");
int buyNumber= sc.nextInt();
g.buyNumber=buyNumber;
System.out.println("修改完成!");
queryGoods(shopCar);
break;
}
}
}
public static Goods getGoodsById(Goods[] shopCar,int id){
//shopCar=[g1.g2,g3,null,null]
for (int i = 0; i < shopCar.length; i++) {
Goods g=shopCar[i];
if(g!=null){
//判断这个商品对象的id是否我们要找的
if(g.id==id){
return g;
}
}else {
return null;//找完了全面存在的商品,都没有找到!
}
}
return null;//代表找完了100个商品都没有找到id一样的商品
}
//查询购物车中的商品对象信息,并展示出来
public static void queryGoods(Goods[] shopCar) {
System.out.println("=============查询购物车信息如下============");
System.out.println("编号\t\t名称\t\t\t价格\t\t\t购买数量");
//shopCar =[g1,g2,g3,null,null,······]
//遍历
for (int i = 0; i < shopCar.length; i++) {
Goods g=shopCar[i];
if(g!=null){
//展示这个商品对象
System.out.println(g.id+"\t\t"+g.name+"\t\t\t"+g.price+"\t\t\t"+g.buyNumber);
}else {
//遍历结束
break;
}
}
}
//用这个方法来增加购物车的添加商品功能
public static void addGoods(Goods[] shopCar,Scanner sc) {
//1.录入用户输入的购买商品的信息
System.out.println("请您输入购买商品的编号(不重复):");
int id=sc.nextInt();
System.out.println("请您输入购买商品的名称:");
String name=sc.next();
System.out.println("请您输入购买商品的数量:");
int buyNumber=sc.nextInt();
System.out.println("请您输入购买商品的价格:");
double price = sc.nextDouble();
//2.把这个购买商品的信息封装成一个商品对象
Goods g=new Goods();
g.id=id;
g.name=name;
g.buyNumber=buyNumber;
g.price=price;
//3.把这个商品对象添加到购物车数组中去。
//shopCar={a,a2,null,·····}
// i
for (int i = 0; i < shopCar.length; i++) {
if(shopCar[i]==null){
//说明此位置没有元素存入,把我们购买的商品添加到此处即可
shopCar[i]=g;
break;//结束,因为商品已经成功存入了,不需要继续找位置了
}
}
System.out.println("您的商品:"+g.name+"添加到购物车完成");
}
}
运行结果
2.构造器,this,封装,javabean
标准javabean须满足如下需求:
- 成员变量使用private修饰
- 提供每一个成员变量对应的setXxx()或getXxx()
- 必须提供一个无参构造器
package com.itheima.creat;
public class User {
//1.成员变量私有
private String name;
private double height;
private double salary;
//3.必须有无参数构造器(默认的)
public User() {
}
//4.有参数构造器(不是必须的,可以选择)
public User(String name, double height, double salary) {
this.name = name;
this.height = height;
this.salary = salary;
}
//2.必须提供成套的getter和setter方法暴漏成员变量的取值和赋值
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
package com.itheima.creat;
public class Test {
public static void main(String[] args) {
//1.调用无参数构造器创建对象
User u=new User();
u.setName("黑马李喆");
u.setHeight(177);
u.setSalary(20000);
System.out.println(u.getName());
System.out.println(u.getHeight());
System.out.println(u.getSalary());
//2.调用有参数构造器创建对象
User u2=new User("黑马程序员",188,10000);
System.out.println(u2.getName());
System.out.println(u2.getHeight());
System.out.println(u2.getSalary());
}
}
3.String类常用api(账号登陆密码案例)
package com.itheima;
import java.sql.SQLOutput;
import java.util.Scanner;
public class StringEqualsDemo {
public static void main(String[] args) {
//1.目标:正确登录名和密码
String okname = "itheima";
String okPassword = "123456";
//2.请您输入登录用户名和密码
Scanner sc = new Scanner(System.in);
System.out.println("登录名称");
String name = sc.next();
System.out.println("登录密码");
String password = sc.next();
//3.判断用户输入的登录名和密码是否与正确的内容相等
if (okname.equals(name) && okPassword.equals(password)) {
System.out.println("登陆成功");
} else {
System.out.println("用户名或密码错误!");
}
//4.忽略大小写比较内容的APi:一般用于比较验证码这样的业务逻辑
String sysCode="23AdFh";
String code1="23aDfH";
System.out.println(sysCode.equals(code1));//false 考虑验证码的大小写
System.out.println(sysCode.equalsIgnoreCase(code1));//true 不考虑验证码大小写
}
}
4.模拟登录
需求:模拟用户登录功能,最多只给三次机会
分析:
- 系统后台定义好正确的登录名称,密码
- 使用循环控制三次,让用户输入正确的登录名和密码,判断是否登录成功,登录成功则不再进行登录;登录失败给出提示,并让用户继续登录
package com.itheima;
import java.util.Scanner;
public class StringExec1 {
//目标:模拟用户登录
public static void main(String[] args) {
//1.定义正确的登录名称和密码
String okLoginName="admin";
String okPassword="itheima";
//2.定义一个循环,循环3次,让用户登录
Scanner sc=new Scanner(System.in);
for (int i = 0; i < 3; i++) {
System.out.println("请您输入登录名称");
String loginName= sc.next();
System.out.println("请您输入登陆密码");
String password=sc.next();
//3.判断登录是否成功
if(okLoginName.equals(loginName)){
//判断密码是否正确
if(okPassword.equals(password)){
System.out.println("登陆成功!");
break;
}else {
System.out.println("您的登陆密码不正确!您还剩"+(3-i)+"次机会登录");
}
}else {
//密码错误了
System.out.println("您的用户名不正确!您还剩"+(3-i)+"次机会登录");
}
}
}
}
5.验证码
需求:随机产生一个5位的验证码,每位可能是数字、大写字母、小写字母
分析:
- 定义一个string类型的变量存储验a-ZA-Z0-9之间的全部字符。
0 - 循环5次,随机一个范围内的索引,获取对应字符连接起来即可。
package com.itheima;
import java.util.Random;
public class StringExec {
//目标:使用String完成随机生成5位的验证码
public static void main(String[] args) {
//1.定义一个可能出现的字符信息
String dates="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
//2.循环5次,每生成一个随机的索引,提取对应的字符连接起来即可
String code="";
Random r=new Random();
for (int i = 0; i < 5; i++) {
//随机一个索引
int index=r.nextInt(dates.length());
char c=dates.charAt(index);
code +=c;
}
//3.输出字符变量即可
System.out.println(code);
}
}
6.手机号屏蔽
需求:以字符串的形式从键盘接受一个手机号,将中间四位号码屏蔽,最终效果为:
158****7839
分析:
- 键盘录入一个字符串,用Scanner 实现。
- 截取字符串前三位,截取字符串后四位。
- 将截取后的两个字符串,中间加上****进行拼接,输出结果即可
package com.itheima;
import java.util.Scanner;
public class StringExec2 {
//手机号屏蔽
public static void main(String[] args) {
//1.键盘录入一个手机号
Scanner sc= new Scanner(System.in);
System.out.println("请您输入您的手机号码:");
String tel=sc.next();
//2./截取号码的前三位,后四位
String before =tel.substring(0,3);//0,1,2
String after=tel.substring(7);//索取7开始截取到手机号的末尾
String s=before+"****"+after;
System.out.println(s);
}
}
7.ArrayList的使用
集合是与数组类似,也是一种容器,用于封装数据的。
数组的特点:
- 数组定义完成并启动后,类型确定,长度固定。
- 问题:在个数不能确定,且要进行增删数据操作的时候,数组是不太合适的。
集合的特点:
- 集合的大小不固定,启动后可以动态变化,类型也可以选择不固定。
- 集合非常适合元素个数不确定,且要进行增删操作的业务场景。
- 集合的提供了许多丰富,好用的功能,而数组的功能很单一。
ArrayList集合
- ArrayList是集合中的一种,它支持索引。
ArrayList集合的对象获取
构造器:public ArrayList() 说明:创建一个空的集合对象
ArryaList集合添加元素的方法
方法名:public boolean add(E e) 说明:将指定的元素追到此集合的末尾
方法名:public void add(int index,E element)说明:在此集合中的指定位置插入指定的元素
泛型概述
- ArrayList:其实就是一个反类型,可以在编译阶段约束集合对象之只能操作某种数据类型。
举例: - ArrayList;此集合只能操作字符串类型的元素
- ArrayList:此集合只能操作整数类型的元素
注意:集合中只能存储引用类型,不支持基本数据类型。
8.ArrayList常用方法
9.遍历删除元素值
需求:
- 某个班级的考试在系统上进行,成绩大致为:98,77,66,89,79.50.100
- 现在需要先把成绩低于80分以下的数据去掉
分析:
- 定义ArrayList集合存储多名学员的成绩
- 遍历集合每个元素,如果元素值低于80分,去掉
package com.itheima;
import java.util.ArrayList;
public class ArrayListTest {
public static void main(String[] args) {
ArrayList<Integer>scores=new ArrayList<>();
//1.创建集合对象:存入学生成绩(98,77,66,89,79.50.100)
scores.add(98);
scores.add(77);
scores.add(66);
scores.add(89);
scores.add(79);
scores.add(60);
scores.add(100);
System.out.println(scores);
//[98,77,66,89,79.50.100]
// i
//2.遍历集合中的每个元素
// for (int i = 0; i < scores.size(); i++) {
// int score=scores.get(i);
// //3.判断这个分数是否低于80,如果低于则从集合中删除
// if(score<80){
// scores.remove(i);
// }
// }
// System.out.println(scores);
for (int i = scores.size()-1; i >=0; i--) {
int score=scores.get(i);
//判断分数
if(score<80){
scores.remove(i);
}
}
System.out.println(scores);
}
}
10.存对象(影片信息在程序中的添加展示)
需求:某影院系统需要在后台存储上述三部电影,然后依次展示出来
分析:
- 三部电影是3个对象,定义一个电影类,定义一个集合存储电影对象。
- 创建3个电影对象,封装相关数据,把3个对象存入到集合中去
package com.itheima;
public class Move {
private String name;
private double score;
private String actor;
public Move() {
}
public Move(String name, double score, String actor) {
this.name = name;
this.score = score;
this.actor = actor;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public String getActor() {
return actor;
}
public void setActor(String actor) {
this.actor = actor;
}
}
package com.itheima;
import java.util.ArrayList;
/**
* 案例:集合存储自定义元素并遍历
* 《肖生客的救赎》 9.7,罗宾斯
* 《霸王别姬》 9.6 张国荣,张丰毅
* 《阿甘正传》 0.5 汤姆,汉克斯
*/
public class ArrayTest1 {
public static void main(String[] args) {
//1.定义一个电影类:Move
//2/定义一个ArrayList集合存储对象
ArrayList<Move>moves=new ArrayList<>();
//3.创建影片对象封装电影数据,把对象加入到集合中
moves.add(new Move("《肖生客的救赎》",9.7,"罗斯宾"));
moves.add(new Move("《霸王别姬》",9.6,"张国荣,张丰毅"));
moves.add(new Move("《阿甘正传》",9.5,"汤姆,汉克斯"));
System.out.println(moves);
//4.遍历并展示
for (int i = 0; i < moves.size(); i++) {
Move move=moves.get(i);
System.out.println("片名:"+move.getName());
System.out.println("评分:"+move.getScore());
System.out.println("主演:"+move.getActor());
}
}
}
11.元素搜索(学生信息系统的数据搜索)
需求:后台程序需要存储如上学生信息并展示,然后要提供按照学号搜索学生信息的功能
分析:
- 定义学生类,定义数组列表集合存储如上学生对象信息,并遍历展示出来
- 提供一个方法,可以接收数组集合,和要搜索的学号,返回搜索到的学生对象信息,并展示。
- 使用死循环,让用户可以不停的搜索
package com.itheima;
public class Student {
private String studgId;
private String name;
private int age;
private String className;
public Student() {
}
public Student(String studgId, String name, int age, String className) {
this.studgId = studgId;
this.name = name;
this.age = age;
this.className = className;
}
public String getStudgId() {
return studgId;
}
public void setStudgId(String studgId) {
this.studgId = studgId;
}
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 getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
}
package com.itheima;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Scanner;
/*
学生类信息(学号,姓名,性别。班级)
测试数据:
"20180302","张三",23,"网络一班"
"20180303","张四",23,"网络二班"
"20180304","李一",26,"网络三班"
"20180305","李四",26,"网络三班"
*/
public class ArrayList2 {
public static void main(String[] args) {
//1.定义一个学生类,后期用于创建对象封装学生数据
//2.定义一个集合对象用于封装学生对象
AbstractList<Student> students=new ArrayList<>();
students.add(new Student("20180302","张三",23,"网络一班"));
students.add(new Student("20180303","张四",23,"网络二班"));
students.add(new Student("20180304","李一",26,"网络三班"));
students.add(new Student("20180305","李四",26,"网络四班"));
//3。遍历
for (int i = 0; i < students.size(); i++) {
Student s=students.get(i);
System.out.println(s.getStudgId()+"\t\t"+s.getName()+"\t\t"+s.getAge()+"\t\t"+s.getClassName());
}
//4.让用户不断的输入学号,可以搜索出该学生对象信息并展示出来(独立方法)
Scanner sc=new Scanner(System.in);
while (true) {
System.out.println("请您输入要查询的学生的学号");
String id= sc.next();
Student s=getStudentByStudyId((ArrayList<Student>) students,id);
//判断学号是否存在
if(s==null){
System.out.println("查无此人");
}else{
System.out.println(s.getStudgId()+"\t\t"+s.getName()+"\t\t"+s.getAge()+"\t\t"+s.getClassName());
}
}
}
public static Student getStudentByStudyId(ArrayList<Student>students,String studyId){
for (int i = 0; i < students.size(); i++) {
Student s=students.get(i);
if(s.getStudgId().equals(studyId)){
return s;
}
}
return null;//查无此学号
}
}
十.ATM案例
- 系统准备、首页设计
- 用户开户功能实现
- 用户登录功能实现
- 用户操作页设计、查询账户、退出账户功能实现
- 用户存款功能实现
- 用户取款功能实现
- 用户转账功能实现
- 用户密码修改、销户功能实现
账户类,首页设计
系统准备内容:
1.每个用户的账户信息都是一个对象,需要提供账户类。
2.需要准备一个容器,用于存储系统全部账户对象信息。
3.首页只需要包含:登录和注册2个功能。
实现步骤:
1.定义账户类,用于后期创建账户对象封装用户的账户信息。
2.账户类中的信息至少需要包含 (卡号、姓名、密码、余额、取现额度)
用户开户功能
分析:开户功能其实就是就是往系统的集合容器中存入一个新的账户对象的信息。
实现步骤:
1.定义方法完成开户:
public static void register(ArrayList accounts){…}
2.键盘录入姓名、密码、确认密码(需保证两次密码一致
3.生成账户卡号,卡号必须由系统自动生成8位数字(必须保证卡号的唯一)
4.创建Account账户类对象用于封装账户信息(姓名、密码、卡号)
5.把Account账户类对象存入到集合accounts
用户登录功能实现
分析:
1.定义方法
public static void login(ArrayList accounts) (…}
2.让用户键盘录入卡号,根据卡号查询账户对象
3.如果没有找到了账户对象,说明卡号不存在,提示继续输入卡号
4.如果找到了账户对象,说明卡号存在,继续输入密码
5.如果密码不正确,提示继续输入密码
用户操作页设计、查询账户、退出账户功能实现
分析:
1.用户登录成功后,需要进入用户操作页
2.查询就是直接展示当前登录成功的账户对象的信息
3.退出账户是需要回到首页的。
用户存款功能实现
分析:
1.存款就是拿到当前账户对象
2.然后让用户输入存款的金额
3.调用账户对象的setMoney方法将账户余额修改成存钱后的余额
4.存钱后需要查询一下账户信息,确认是否存钱成功了!
用户取款功能实现
分析:
1.取款需要先判断账户是否有钱
2.有钱则拿到自己账户对象
3.然后让用户输入取款金额
4.判断取款金额是否超过了当次限额,以及余额是否足够
5.满足要求则调用账户对象的setMoney方法完成金额的修改。
用户转账功能实现
分析:
1.转账功能需要判断系统中是否有2个账户对象及以上.
2.同时还要判断自己账户是否有钱
3.接下来需要输入对方卡号,判断对方账户是否存在
4.对方账户存在还需要认证对方户主的姓氏
5.满足要求则可以把自己账户对象的金额修改到对方账户对象中去
用户密码修改、销户功能实现
分析:
1.修改密码就是把当前对象的密码属性使用set方法进行更新
2.销户是从集合对象中删除当前对象,并回到首页
类
package com.itheima;
public class Account {
private String cardId;// 卡号
private String userName;//客户名称
private String passWord;//密码
private double money;//余额
private double quotaMoney;//当次取款限额
public Account() {
}
public Account(String cardId, String userName, String passWord,double quotaMoney) {
this.cardId = cardId;
this.userName = userName;
this.passWord = passWord;
this.money = money;
this.quotaMoney = quotaMoney;
}
public String getCardId() {
return cardId;
}
public void setCardId(String cardId) {
this.cardId = cardId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
public double getQuotaMoney() {
return quotaMoney;
}
public void setQuotaMoney(double quotaMoney) {
this.quotaMoney = quotaMoney;
}
}
代码
package com.itheima;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
public class ATMSystem {
public static void main(String[] args) {
//1.准备系统需要的容器对象,用于存储账户对象
ArrayList<Account>accounts=new ArrayList<>();
//2.准备系统的首页:登录,开户
showMain(accounts);
}
public static void showMain(ArrayList<Account>accounts){
Scanner sc=new Scanner(System.in);
while (true) {
System.out.println("请您输入想做的操作:");
System.out.println("1.登录");
System.out.println("2.开户");
int command=sc.nextInt();
switch (command){
case 1:
//登录
login(accounts,sc);
break;
case 2:
//开户
register(accounts,sc);
break;
default:
System.out.println("您当前输入的操作命令不被支持!");
}
}
}
/**
*
* @param accounts
*/
private static void login(ArrayList<Account> accounts,Scanner sc) {
//必须系统中存在卡号才可以登录
if(accounts.size()==0){
//没有账户
System.out.println("您还未注册!");
return;//直接结束方法的执行
}
//2.让用户键盘录入卡号
while (true) {
System.out.println("请您输入登陆的卡号:");
String cardId=sc.next();
//根据卡号查询账户对象
Account acc=getAccountBycardId(cardId,accounts);
//3.判断账户对象是否存在,存在说明卡号没问题
if(acc!=null){
//4.让用户继续输入密码
while (true) {
System.out.println("请您输入登陆的密码:");
String password= sc.next();
//5.判断密码是否正确
if(acc.getPassWord().equals(password)){
//密码正确,登陆成功
//展示系统登录后的操作界面
System.out.println("恭喜您,"+acc.getUserName()+"先生/女士成功进入系统,您的卡号是:"+acc.getCardId());
//展示操作页面
showUserCommand(sc,acc,accounts);
return;//继续结束登录方法
}else{
System.out.println("您的密码有误,请确认!");
}
}
}else{
System.out.println("对不起,不存在该卡号的账户!");
}
}
}
private static void showUserCommand(Scanner sc,Account acc,ArrayList<Account>accounts ){
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("6.退出");
System.out.println("7.注销账户");
System.out.println("请您输入操作命令:");
int command=sc.nextInt();
switch (command){
case 1:
//查询账户
showAccount(acc);
break;
case 2:
//存款
depositMnoey(acc,sc);
break;
case 3:
//取款
drawMoney(acc,sc);
break;
case 4:
//转账
transferMoney(accounts,acc,sc);
break;
case 5:
//修改密码
updatePassword(acc,sc);
return;
case 6:
//退出
System.out.println("欢迎下次光临!");
return;//结束当前操作方法
case 7:
//注销账户
//从当前集合中抹去当前账户对象即可
accounts.remove(acc);
System.out.println("销户成功");
return;
default:
System.out.println("您输入的命令有误!");
}
}
}
private static void updatePassword(Account acc,Scanner sc) {
System.out.println("=================修改密码==================");
while (true) {
System.out.println("请您输入正确的密码:");
String okPassWord=sc.next();
//判断密码是否正确
if(acc.getPassWord().equals(okPassWord)){
while (true) {
//可以输入新密码
System.out.println("请您输入新密码:");
String newPassWord=sc.next();
System.out.println("请您输入确认密码:");
String okNewPassWord= sc.next();
if (newPassWord.equals(okNewPassWord)) {
//修改账户对象的密码为新密码
acc.setPassWord(newPassWord);
return;//结束修改
}else{
System.out.println("您两次输入密码不一致");
}
}
}else{
System.out.println("当前输入的密码不正确");
}
}
}
/**
* 转账
* @param accounts
* @param acc
* @param sc
*/
private static void transferMoney(ArrayList<Account> accounts, Account acc, Scanner sc) {
//1.判断系统中是否有2个账户及以上
if(accounts.size()<2){
System.out.println("对不起,系统中无其他账户,您不可以转账!");
return;
}
//2.判断自己的账户对象中是否有钱
if(acc.getMoney()==0){
System.out.println("对不起,您自己都没钱,就别转了");
return;
}
//3.开始转账逻辑
while (true) {
System.out.println("请您输入对方账户的卡号:");
String cardId=sc.next();
Account account=getAccountBycardId(cardId,accounts);
//判断这个账户对象是否存在,存在说明对方卡号输入正确
if(account!=null) {
//判断这个账户对象是否当前登陆的自己账户
if (account.getCardId().equals(acc.getCardId())) {
//正在给自己转账
System.out.println("您不可以给自己转账!");
} else {
//确认对方的姓氏
String name = "*" + account.getUserName().substring(1);
System.out.println("请您确认[" + name + "]的姓氏:");
String perName = sc.next();
//判断
if (account.getUserName().startsWith(perName)) {
//真正开始转账
System.out.println("请您输入的转账金额:");
double money = sc.nextDouble();
//判断这个金额是否超过自己的余额
if (money > acc.getMoney()) {
System.out.println("对不起,你要转账的金额太多,你最多可以转账:" + acc.getMoney());
} else {
//真的可以转了
acc.setMoney(acc.getMoney() - money);
account.setMoney(account.getMoney() + money);
System.out.println("恭喜您,转账成功,已经为" + account.getUserName() + "转账多少:" + money);
showAccount(acc);
return;
}
}else {
System.out.println("对不起,您认证的信息有误!");
}
}
}else {
System.out.println("对不起,您输入的转账账号有问题!");
}
}
}
/**
* 取款
* @param acc
* @param sc
*/
private static void drawMoney(Account acc, Scanner sc) {
System.out.println("====================取款操作===================");
//1.判断他的账户是否足够100元
if(acc.getMoney()>=100){
while (true) {
System.out.println("请您输入取款的金额:");
double money=sc.nextDouble();
//2.判断这个金额有没有超过当次限额
if(money>=acc.getQuotaMoney()){
System.out.println("您当次取款金额超过每次限额,无法取出,每次最多可以取:"+acc.getQuotaMoney());
}else{
//3.判断当前余额是否大于取钱余额
if(acc.getMoney()>=money){
//钱够,可以取
acc.setMoney(acc.getMoney()-money);
System.out.println("恭喜您,取钱"+money+"成功了!当前账户还剩:"+acc.getMoney());
return;//取完钱后干掉取钱方法
}else{
System.out.println("余额不足!");
}
}
}
}else{
System.out.println("您自己的金额没有超过100元,就别取了");
}
}
/**
* 存钱操作
* @param acc
* @param sc
*/
private static void depositMnoey(Account acc, Scanner sc) {
System.out.println("==================存钱操作===============");
System.out.println("请您输入存钱的金额");
double money= sc.nextDouble();
//直接把金额修改到账户对象的money属性中去
acc.setMoney(acc.getMoney()+money);
}
private static void showAccount(Account acc) {
System.out.println("==================当前账户==================");
System.out.println("卡号"+acc.getCardId());
System.out.println("姓名"+acc.getUserName());
System.out.println("余额"+acc.getMoney());
System.out.println("当次限额"+acc.getQuotaMoney());
}
/**
* 用户开户功能
* @param accounts
*/
private static void register(ArrayList<Account> accounts,Scanner sc) {
System.out.println("===============用户开户功能==============");
//2.键盘录入 姓名 密码 确认密码
System.out.println("请您输入开户名称:");
String name=sc.next();
String password="";
while (true) {
System.out.println("请您输入开户密码:");
password=sc.next();
System.out.println("请您输入确认密码:");
String okpsaaword=sc.next();
//判断两次输入密码是否一致
if(okpsaaword.equals(password)){
break;
}else{
System.out.println("两次密码必须一致!");
}
}
System.out.println("请您输入当次限额");
double quotaMoney= sc.nextDouble();
//3.生成账户的卡号,卡号是8位,而且不能与其他账户卡号重复
String cardId=createCardId(accounts);
//4.创建一个账户对象封装账户的信息
//public Account(String cardId, String userName, String passWord, double money, double quotaMoney)
Account account=new Account(cardId,name,password,quotaMoney);
//5.把账户对象添加到集合中去
accounts.add(account);
System.out.println("恭喜您,您开户成功,您的卡号是:"+account.getCardId());
}
public static String createCardId(ArrayList<Account>accounts) {
//生成8位随机卡号
while (true) {
String cardId = "";
Random r = new Random();
for (int i = 0; i < 8; i++) {
cardId += r.nextInt(10);//生成0~9的随机数字
}
//判断卡号是否重乎了
Account acc = getAccountBycardId(cardId, accounts);
if (acc == null) {
//说明没有重复
return cardId;
}
}
}
public static Account getAccountBycardId(String cardId,ArrayList<Account>accounts){
//根据卡号查询账户对象
for (int i = 0; i < accounts.size(); i++) {
Account acc=accounts.get(i);
if(acc.getCardId().equals(cardId)){
return acc;
}
}
return null;//查无此账户,说明卡号没有重复
}
}
十一.面向对象进阶
1.权限修饰符
用来控制一个成员能够被访问的范围
2.final
3.常量
4.抽象类
-
在java中abstract是抽象类的意思,可以修饰类,成员方法。
-
abstract修饰类,这个类就是抽象类;修饰方法,这个方法就是抽象方法。
1.抽象类,抽象方法是什么样的? -
都是用abstract修饰的;抽象方法只有方法签名,不能写方法体。
-
一个类中定义了抽象方法,这个类必须声明抽象类。
2.抽象类基本作用是啥?
- 作为父类,用来被继承的。
3.继承抽象类有哪些需要注意的?
- 一个类如果继承了抽象类,那么这个类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。
特征和注意事项:
- 类有的成员(成员变量,方法,构造器)抽象类都具备
- 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
- 一个类继承了抽象类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类
- 不能用abstract修饰变量,代码块,构造器
- 最重要的特征:得到了抽象方法,失去了创建对象的能力(有得有失)
final和abstract是什么关系?
- 互斥关系
- abstract定义的抽象类作为模板让子类继承,final定义的类不能被继承。
- 抽象方法定义通用功能让子类重写,final定义得方法子类不能重写。
1.抽象类案例
2.模板方法(及案例)
什么时候使用模板方法模式?
- 当系统中出现同一个功能多处在开发,而该功能中大部分代码是一样的,只有其中部分可能不同的时候(例如:写作文,两个人写作文开头和结尾要求一样,中间正文自由发挥才华)
模板方法模式实现步骤:
- 把功能定义成一个所谓的模板方法,放在抽象类中,模板方法中只能定义通用能确定的代码。
- 模板方法中不能决定的功能定义成抽象方法让具体子类去实现。
模板方法我们是建议使用final修饰的,这样会更专业,那么为什么呢?
答:模板方法是给与子类直接使用的,不是让子类重写的,一旦子类重写了模板方法,则模板方法就失效了,因此,加上final可以防止子类重写了模板方法,这样更安全,专业。
1.模板方法模式解决了什么问题?
- 提高了代码的复用性
- 模板方法已经定义了通用结构,模式方法不能确定的部分定义成抽象方法,交给子类实现,因此,使用者只需关心自己需要实现的功能即可。
5.接口
从上面可以看出,接口可以被类单实现,也可以被类多实现。
接口实现的注意事项:
- 一个类实现接口,必须重写完全部接口的全部抽象方法,否则这个类需要定义成抽象类。
基本小结:
- 类和类的关系:单继承
- 类和接口的关系:多实现
- 接口和接口的关系:多继承,一个接口可以同时继承多个接口
接口的注意事项:
1.接口不能创建对象
2.一个类实现多个接口,多个接口中有同样的静态方法不冲突
3.一个类继承了父类,同时又实现了接口,父类中和接口中有同名方法,默认用父类的
4.一个类实现了多个接口,多个接口中存在同名的默认方法,不冲突,这个类重写该方法即可
5.一个接口继承多个接口,是没有问题的,如果多个接口中存在规范冲突则不能多继承
6.多态
多态是同一个行为具有多个不同表现形式或形态的能力。
多态的前提:
- 有继承/实现关系;有父类引用指向子类对象;有方法重写
优点:
1.消除类型之间的耦合关系
2.可替换性
3.可扩充性
4.接口性
5.灵活性
6.简化性
劣势:多态下不能使用子类的独有功能
7.多态案例
需求:
- 使用面向对象编程模拟:设计一个电脑对象,可以安装2个USB设备
- 鼠标:被安装时可以完成接入,调用点击功能,拔出功能
- 键盘:被安装时可以完成接入,调用打字功能,拔出功能
分析:
- 定义一个USB的接口(申明USB设备的规范必须是:可以接入和拔出)
- 提供2个USB实现代表鼠标和键盘,让其实现USB接口,并分别定义独有功能
- 创建电脑对象,创建2个USB实现类对象,分别安装到电脑中并触发功能的执行。
USB接口
package d1.duotai.test;
public interface USB {
void connect();
void unconnect();
}
鼠标类
package d1.duotai.test;
/**
* 实现类(子类)
*/
public class Mouse implements USB {
private String name;
public Mouse(String name) {
this.name = name;
}
@Override
public void connect() {
System.out.println(name+"成功的接入了设备····");
}
@Override
public void unconnect() {
System.out.println(name+"成功的从设备弹出了····");
}
/**
* 独有功能
*/
public void click(){
System.out.println(name+"双击点亮了小红心····");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
键盘类
package d1.duotai.test;
/**
* 实现类(子类)
*/
public class KeyBoard implements USB {
private String name;
public KeyBoard(String name) {
this.name = name;
}
@Override
public void connect() {
System.out.println(name+"成功的接入了设备····");
}
@Override
public void unconnect() {
System.out.println(name+"成功的从设备弹出了····");
}
/**
* 独有功能
*/
public void keyDown(){
System.out.println(name+"写下了老铁666····");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
电脑类
package d1.duotai.test;
public class Computer {
/**
提供一个安装的入口:行为
*/
public void installUSB(USB u){
u.connect();
//独有功能
if(u instanceof Mouse){
Mouse m=(Mouse) u;
m.click();
} else if (u instanceof KeyBoard) {
KeyBoard k=(KeyBoard) u;
k.keyDown();
}
u.unconnect();
}
}
测试
package d1.duotai.test;
/**
目标:USB设备模拟
1.定义USB接口:接入 拔出
2.定义2个USB的实现类:鼠标 键盘
3.创建一个电脑对象,创建USB设备对象,安装启动
*/
public class Test {
public static void main(String[] args) {
//a.创建电脑对象
Computer c=new Computer();
//b.创建USB设备对象
USB u=new Mouse("罗技鼠标");
c.installUSB(u);
USB k=new KeyBoard("双飞燕键盘");
c.installUSB(k);
}
}
8.常用API(Object,Objects,StringBuilder,Math,Systemm,BigDecimal)
- API(Application Programming interface)应用程序编程接口
- 简单来说:就是java帮我们已经写好了的一些方法,我们直接拿过来用就可以了
Object类的作用:
- 一个类要么默认继承了Object类,要么间接继承了Object类,object类是java中的祖宗类。
- Object类的方法是一切子类都可以直接使用的,所以我们要学习Object类的方法。
Object类的常用方法:
方法名 | 说明 |
---|---|
public String toString() | 默认是返回当前对象在堆内存中的地址信息:类的全限名@内存地址 |
public Boolean equals(Object o) | 默认是比较当前对象与另一个对象的地址是否相同,相同返回true,不同返回false |
Object的to String方法的作用是什么? |
- 默认是打印当前对象的地址
- 让子类重写,以便返回子类对象的内容
toString方法
Student类
package d2.api.test;
public class Student {
private String name;
private char sex;
private int age;
public Student() {
}
public Student(String name, char sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex=" + sex +
", age=" + age +
'}';
}
}
测试
package d2.api.test;
public class Tset2 {
public static void main(String[] args) {
Student s=new Student("周雄",'男',19);
System.out.println(s);
}
}
equals方法
Student类
package d2.api.test;
import java.util.Objects;
public class Student {
private String name;
private char sex;
private int age;
public Student() {
}
public Student(String name, char sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//重写的equals比较方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return sex == student.sex && age == student.age && Objects.equals(name, student.name);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex=" + sex +
", age=" + age +
'}';
}
}
测试
package d2.api.test;
public class Tset2 {
public static void main(String[] args) {
Student s1=new Student("周雄",'男',19);
Student s2=new Student("周雄",'男',19);
System.out.println(s1.equals(s2));//用来比较内容是否相同,需要重写方法,否则默认是比较地址
System.out.println(s1==s2);//用来比较地址是否相同
}
}
Object的equals方法的作用是什么?
- 默认是与另一个对象比较地址是否一样
- 让子类重写后,以便比较2个子类对象的内容是否相同
Objects的常见方法:
方法名 | 说明 |
---|---|
public static boolean equals(Object a,Object b) | 比较两个对象的,底层会先进行非空判断,从而可以避免空指针异常,再进行equals比较 |
public static boolean isNull(Object obj) | 判断变量是否为null,为null返回true,反之 |
package d3.objects.tset;
import java.util.Objects;
public class Test {
public static void main(String[] args) {
String s1=null;
String s2=new String("itheima");
System.out.println(Objects.equals(s1, s2));
System.out.println(Objects.isNull(s1));//true
System.out.println(s1==null);//true
System.out.println(Objects.isNull(s2));//false
System.out.println(s2==null);//false
}
}
对象进行内容比较的时候建议使用什么?为什么?
- 建议使用Objects提供的equals方法
- 比较的结果是一样的,但是更安全
StringBuilder概述
- StringBuilder是一个可变的字符串类,我们可以把它看成一个对象容器
- 作用:提高字符串的操作效率,如拼接,修改等
StringBuilder构造器
名称 | 说明 |
---|---|
public StringBuild() | 创建一个空白的可变的字符串对象,不包含任何内容 |
public StringBuilder(String str) | 创建一个指定字符串内容的可变字符串对象 |
StringBuilder常用方法
方法名称 | 说明 |
---|---|
public StringBuilder append(任意类型) | 添加数据并返回StringBuilder对象本身 |
public StringBuilder reverse() | 将对象的内容反转 |
public int length() | 返回对象内容长度 |
public String toString() | 通过toString()就可以实现把StringBuilder转换为String |
package d4.stringbuilder.test;
public class StringBuilderDemo1 {
public static void main(String[] args) {
StringBuilder sb=new StringBuilder();
sb.append("a");
sb.append("b");
sb.append("c");
sb.append(1);
sb.append(false);
sb.append(3.3);
sb.append("abc");
System.out.println(sb);
StringBuilder sb1=new StringBuilder();
//支持链式编程
sb1.append("a").append("b").append("c").append("我爱你中国");
System.out.println(sb1);
//反转
sb1.reverse().append("110");
System.out.println(sb1);
System.out.println(sb1.length());
//注意:StringBuilder只是拼接字符串的手段,效率好
//最终的目的还是要恢复成String类型
StringBuilder sb2=new StringBuilder();
sb2.append("123").append("456");
//恢复成String类型
String rs= sb2.toString();
check(rs);
}
public static void check(String date){
System.out.println(date);
}
}
为什么拼接,反转字符串建议使用StringBuilder?
- String:内容是不变的,拼接字符串性能差
- StringBuilder:内容是可变的,拼接字符串性能好,代码优雅
- 定义字符串使用String
- 拼接,修改等操作字符串使用StringBuilder
package d4.stringbuilder.test;
public class StringBuilDemo2 {
public static void main(String[] args) {
int[]arr1=null;
System.out.println(toString(arr1));
int[]arr2={10,88,99};
System.out.println(toString(arr2));
}
public static String toString(int[]arr){
if(arr!=null){
StringBuilder sb=new StringBuilder("[");
for (int i = 0; i < arr.length; i++) {
sb.append(arr[i]).append(i== arr.length-1?"":",");
}
sb.append("]");
return sb.toString();
}else{
return null;
}
}
}
Math类
- 包含执行基本数字运算的方法,Math类没有提供公开的构造器
- 如何使用类中的成员呢?看类的成员是否都是静态的,如果是,通过类名就可以直接调用
在这里插入代码片
```package d5.math;
public class MathDemo {
public static void main(String[] args) {
//1.取绝对值:返回正数
System.out.println(Math.abs(10));//10
System.out.println(Math.abs(-10.3));//10.3
//2.向上取整
System.out.println(Math.ceil(4.000001));//5.0
System.out.println(Math.ceil(4.0));//4.0
//3.向下取整
System.out.println(Math.floor(4.9999999));//4.0
System.out.println(Math.floor(4.0));//4.0
//4.求指数次方
System.out.println(Math.pow(2, 3));//2^3=8.0
//5.四舍五入
System.out.println(Math.round(4.49999));//4
System.out.println(Math.round(4.588));//5
System.out.println(Math.random());//0.0~1.0(包前不包后)
//拓展:3~9之间的随机数 (0-6)+3
//[0-6]+3
int date=(int)(Math.random()*7)+3;
System.out.println(date);
}
}
System类
BigDecima类
1.BigDecimal的作用是什么?
解决浮点型运算精度失真问题
2.BigDecimal的对象如何获取?
BigDecimal b1=BigDecimal.valueof(0.1);
9.Date类,SimpDateFormat类,Calendar类
Date类的对象在java中代表的是当前所在系统的此刻日期时间。
Date的构造器
名称 | 说明 |
---|---|
public Date() | 创造一个Date对象,代表的是系统当前此刻日期的时间 |
Date的常用方法
名称 | 说明 |
---|---|
public long getTime() | 获取时间对象的毫秒值 |
构造器 | 说明 |
---|---|
public Date(long time) | 把时间毫秒值转换成Date日期对象 |
Date方法 | 说明 |
---|---|
public void setTime(long time) | 设置日期对象的时间为当前时间毫秒值对应的时间 |
package com.itheima;
import java.util.Date;
public class Date1 {
public static void main(String[] args) {
//1.创建一个Date类的对象,代表系统此刻日期时间对象
Date d=new Date();
System.out.println(d);
//2.获取时间毫秒值
long time= d.getTime();
System.out.println(time);
System.out.println("`````````````````");
//计算当前时间往后走1小时 121秒的时间
//1.得到当前时间
Date d1=new Date();
System.out.println(d1);
//2.当前时间安=往后走1小时 121秒
long time2=System.currentTimeMillis();
time2+=(60*60+121)*1000;
Date d3=new Date();
d3.setTime(time2);
System.out.println(d3);
}
}
SimpDateFormat类作用
- 可以对Date对象或时间毫秒值格式化成我们喜欢的时间形式
- 也可以把字符串的时间形式解析成日期对象
SimpDateFormat的构造器
构造器 | 说明 |
---|---|
public SimpDateFormat() | 构造一个SimpDateFormat,使用默认格式 |
public SimpDateFormat(String pattern) | 构造一个SimpDateFormat,使用指定的格式 |
SimpDateFormat的格式化方法
格式化方法 | 说明 |
---|---|
public final String format(Date date) | 将日期格式化成日期/时间字符串 |
public final String format(Object time) | 将时间毫秒值格化成日期/时间字符串 |
package com.itheima;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Date2 {
public static void main(String[] args) {
//1.日期对象
Date d=new Date();
System.out.println(d);
//2.格式化这个日期对象(指定最终格式化的形式)
SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd月 HH:mm:ss EEE a");
//3.开始格式化日期对象成为喜欢的字符串形式
String rs=sdf.format(d);
System.out.println(rs);
System.out.println("```````````````````");
//4.格式化时间毫秒值
//需求:请问121秒后的时间是多少
long time1=System.currentTimeMillis()+121*1000;
String rs2= sdf.format(time1);
System.out.println(rs2);
}
}
SimpleDateFormat解析字符串时间成为日期对象
解析方法 | 说明 |
---|---|
public Date parse(String source) | 从给定字符串的开始解析文本以生成日期 |
package com.itheima;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Date3 {
public static void main(String[] args) throws ParseException {
//有一个时间2021年8月06日 11:11:11往后2天14小时49分06秒后的时间是多少
//1.把字符串时间拿到程序来
String dateStr="2021年08月06日 11:11:11";
//2.把字符串时间解析成日期对象;形式必须与被解析时间的形式完全一样,否则运行时解析报错!
SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date d=sdf.parse(dateStr);
//3.往后走2天14小时49分06秒
long time =d.getTime()+(2L*24*60*60+14*60*60+49*60+6)*1000;
//4.格式化这个时间毫秒值就是结果
System.out.println(sdf.format(time));
}
}
package com.itheima;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Date4 {
public static void main(String[] args) throws ParseException {
String starTime="2021-11-11 00:00:00";
String endTime="2021-11-11 00:10:00";
String xiaojia="2021-11-11 00:03:47";
String xiaopi="2021-11-11 00:10:11";
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d1=sdf.parse(starTime);
Date d2=sdf.parse(endTime);
Date d3=sdf.parse(xiaojia);
Date d4=sdf.parse(xiaopi);
if(d3.after(d1)&& d3.before(d2)){
System.out.println("小贾秒杀成功");
}else{
System.out.println("小贾秒杀失败");
}
if(d4.after(d1)&&d4.before(d2)){
System.out.println("小皮秒杀成功");
}else {
System.out.println("小皮秒杀失败");
}
}
}
Calendar概述
- Calendar代表了系统此刻日期对应的日历对象
- Calendar是一个抽象类,不能直接创建对象
Calendar常用方法
方法名 | 说明 |
---|---|
public int get(int field) | 取日期中的某个字段信息 |
public void set(int field,int value) | 修改日历的某个字段信息 |
public void add(int field,int amount) | 为某个字段增加/减少指定的值 |
public final Date getTime() | 拿到此刻日期对象 |
public long getTimeMillis() | 拿到此刻时间毫秒值 |
package com.itheima;
import java.sql.SQLOutput;
import java.util.Calendar;
import java.util.Date;
public class Date5 {
public static void main(String[] args) {
//1.拿到系统此刻日历对象
Calendar cal=Calendar.getInstance();
System.out.println(cal);
//2.获取日历的信息:public int get (int field):取日期中的某个字段信息
int year= cal.get(Calendar.YEAR);
System.out.println(year);
int mm= cal.get(Calendar.MONTH)+1;
System.out.println(mm);
int days= cal.get(Calendar.DAY_OF_YEAR);
System.out.println(days);
//3.public void set(int field,int value):修改日历的某个字段信息
cal.set(Calendar.HOUR,12);
System.out.println(cal);
//4.public void add(int field,int amount):为某个字段增加/减少指定的值
//请问64天后是什么时间
cal.add(Calendar.DAY_OF_YEAR,64);
cal.add(Calendar.MINUTE,59);
//5.public final Date getTime():拿到此刻日期对象
Date d=cal.getTime();
System.out.println(d);
//6.public long getTimeMillis():拿到此刻时间毫秒值
long time= cal.getTimeInMillis();
System.out.println(time);
}
}
10.JDK8后新增的日期类
LocalDate:不包含具体时间的日期
LocalTime:不包含日期的时间
LocalDateTime:包含了日期及时间
Instant:代表的是时间戳
DateTimeFormatter:用于做时间的格式化和解析的
Duration:用于计算两个“时间”间隔
Period:用于计算两个“日期”间隔
LocalDate:
package com.itheima;
import java.time.LocalDate;
public class Demo1LocalDate {
public static void main(String[] args) {
//1.获取本地日期对象
LocalDate nowDate= LocalDate.now();
System.out.println("今天的日期:"+nowDate);
int year= nowDate.getYear();
System.out.println("今年是"+year+"年");
int month=nowDate.getMonthValue();
System.out.println("month:"+month);
int day= nowDate.getDayOfMonth();
System.out.println("day:"+day);
//2.当年的第几天
int day0fYear= nowDate.getDayOfYear();
System.out.println("day0fYer"+day0fYear);
//3.星期
System.out.println(nowDate.getDayOfWeek());
System.out.println(nowDate.getDayOfWeek().getValue());
//4.月份
System.out.println(nowDate.getMonth());
System.out.println(nowDate.getMonth().getValue());
//5.输出年月日
LocalDate bt=LocalDate.of(2023,12,3);
System.out.println(bt);
}
}
LocalTime:
package com.itheima;
import java.time.LocalDate;
import java.time.LocalTime;
public class Demo2LocalTime {
public static void main(String[] args) {
//1.获取本地时间
LocalTime nowTime= LocalTime.now();
System.out.println("现在是"+nowTime);
int hour= nowTime.getHour();
System.out.println("hour:"+hour);
int mintue= nowTime.getMinute();
System.out.println("mintue:"+mintue);
int second= nowTime.getSecond();
System.out.println("second:"+second);
int nano= nowTime.getNano();
System.out.println("nano:"+nano);
System.out.println(LocalTime.of(20, 33, 30));
}
}
LocalDateTime:
package com.itheima;
import java.time.LocalDateTime;
public class Demo3LocalDateTime {
public static void main(String[] args) {
//日期 时间
LocalDateTime nowDateTime=LocalDateTime.now();
System.out.println("今天是:"+nowDateTime);
System.out.println(nowDateTime.getYear());//年
System.out.println(nowDateTime.getMonthValue());//月
System.out.println(nowDateTime.getDayOfMonth());//日
System.out.println(nowDateTime.getHour());//时
System.out.println(nowDateTime.getMinute());//分
System.out.println(nowDateTime.getSecond());//秒
System.out.println(nowDateTime.getNano());//纳秒
//日:当年的第几天
System.out.println("day0fYear"+nowDateTime.getDayOfYear());
}
}
package com.itheima;
import java.time.LocalDate;
import java.time.LocalTime;
public class Demo4UpdateTime {
public static void main(String[] args) {
LocalTime nowTime=LocalTime.now();
System.out.println(nowTime);//当前时间
System.out.println(nowTime.minusHours(1));//1小时前
System.out.println(nowTime.minusMinutes(1));//1分钟前
System.out.println(nowTime.minusSeconds(1));//1秒前
System.out.println(nowTime.minusNanos(1));//1纳秒前
System.out.println(nowTime.plusHours(1));//1小时后
System.out.println(nowTime.plusMinutes(1));//1分钟后
System.out.println(nowTime.plusSeconds(1));//1秒后
System.out.println(nowTime.plusNanos(1));//1纳秒后
System.out.println("```````````````````");
LocalDate myDate=LocalDate.of(2004,8,5);
LocalDate nowDate=LocalDate.now();
System.out.println("今天是2004-8-5吗?"+nowDate.equals(myDate));//false
System.out.println(myDate+"是否在"+nowDate+"之前"+myDate.equals(nowDate));
//判断生日
System.out.println("````````````");
LocalDate birDate=LocalDate.of(2004,8,5);
LocalDate nowDate1=LocalDate.now();
System.out.println("今天是你的生日吗"+birDate.equals(nowDate1));
}
}
Instant
package com.itheima;
import java.time.Instant;
import java.time.ZoneId;
import java.util.Date;
public class Demo5Instant {
public static void main(String[] args) {
//1.得到一个时间戳对象 世界时间
Instant instant=Instant.now();
System.out.println(instant);
//2.系统此时时间
Instant instant1=Instant .now();
System.out.println(instant1.atZone(ZoneId.systemDefault()));
//3.返回日期对象
Date date=Date.from(instant);
System.out.println(date);
Instant i2=date.toInstant();
System.out.println(i2);
}
}
DateTimeFormat:
package com.itheima;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class DateTimeFormata {
public static void main(String[] args) {
//本地的时间
LocalDateTime ldt=LocalDateTime.now();
System.out.println(ldt);
//解析/格式化器
DateTimeFormatter dtf=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss EEE a");
//正向格式化
System.out.println(dtf.format(ldt));
//逆向格式化
System.out.println(ldt.format(dtf));
//解析字符串时间
DateTimeFormatter dtf1=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//解析当前字符串时间成为本地日期时间对象
LocalDateTime ldt1=LocalDateTime.parse("2023-12-03 11:11:11",dtf1);
System.out.println(ldt1);
System.out.println(ldt1.getDayOfYear());
}
}
Period用于计算时间间隔多少
package com.itheima;
import java.time.LocalDate;
import java.time.Period;
public class Demo6Period {
public static void main(String[] args) {
//当前本地年月日
LocalDate today=LocalDate.now();
System.out.println(today);
//生日的年月日
LocalDate birthDate=LocalDate.of(2004,8,5);
System.out.println(birthDate);
Period period=Period.between(birthDate,today);
System.out.println(period.getYears());
System.out.println(period.getMonths());
System.out.println(period.getDays());
}
}
Duration也用来计算时间隔
package com.itheima;
import java.time.Duration;
import java.time.LocalDateTime;
public class Demo8Duration {
public static void main(String[] args) {
//本地日期时间对象
LocalDateTime today=LocalDateTime.now();
System.out.println(today);
//出生日期
LocalDateTime birthDate=LocalDateTime.of(2004,8,5,8,8,8);
System.out.println(birthDate);
Duration duration=Duration.between(birthDate,today);//第二个参数-第一个
System.out.println(duration.toDays());
System.out.println(duration.toHours());
System.out.println(duration.toMinutes());
System.out.println(duration.toMillis());
System.out.println(duration.toNanos());
}
}
ChronoUnit:最全的类
package com.itheima;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
public class Demo9ChronoUnit {
public static void main(String[] args) {
//本地日期时间对象:此刻的
LocalDateTime today=LocalDateTime.now();
System.out.println(today);
//生日时间
LocalDateTime brithDate=LocalDateTime.of(2004,8,5,8,8,8);
System.out.println(brithDate);
System.out.println("相差的年数:"+ ChronoUnit.YEARS.between(brithDate,today));
System.out.println("相差的月数:"+ChronoUnit.MONTHS.between(brithDate,today));
}
}
11.包装类(字符串类型转成基本数据类型)
package com.itheima;
public class Test {
public static void main(String[] args) {
//转成整数
String number="23";
int age=Integer.valueOf(number);
System.out.println(age+1);
//转成小数
String number1="99.9";
double score=Double.valueOf(number1);
System.out.println(score+0.1);
}
}
12.正则表示
正则表达式可以用一些规定的字符来制定规则,并用来校验数据格式的合法性
了解正则表达式之前我们来用之前学过的知识做一个功能:
package com.itheima;
public class ZhengZe {
public static void main(String[] args) {
//1.判断8~20位的qq号是否输入正确
System.out.println(checkQQ("22222222"));
System.out.println(checkQQ("222"));
System.out.println(checkQQ("222a2222"));
System.out.println(checkQQ("222222222222222222222222222222222222"));
}
public static boolean checkQQ(String qq){
if(qq==null ||qq.length()<8||qq.length()>20){
return false;
}
//遍历查询判断是否全为数字
for (int i = 0; i < qq.length(); i++) {
//获取每位字符
char ch=qq.charAt(i);
if(ch<'0'||ch>'9'){
return false;
}
}
return true;
}
}
正则表达式法
package com.itheima;
public class ZhengZe2 {
public static void main(String[] args) {
System.out.println(checkQQ2("222222222"));
System.out.println(checkQQ2("2222a"));
System.out.println(checkQQ2(null));
System.out.println(checkQQ2("2222222222222222222222222"));
}
public static boolean checkQQ2(String qq){
return qq!=null&&qq.matches("\\d{8,20}"); // \\d表示全是数字
}
}
正则表达式规则:
利用正则表达式验证手机号,邮箱,电话号码是否正确:
package com.itheima;
import java.util.Scanner;
public class Test2 {
public static void main(String[] args) {
checkPhone();
checkEmail();
checkTel();
}
public static void checkPhone(){
while (true) {
Scanner sc=new Scanner(System.in);
System.out.println("请您输入您的注册手机号码:");
String phone= sc.next();
//判断手机号码格式是否正确
if(phone.matches("1[3-9]\\d{9}")){
System.out.println("手机号码格式正确,注册成功!");
break; //注册成功结束死循环
}else {
System.out.println("格式有误!");
}
}
}
public static void checkEmail(){
while (true) {
Scanner sc=new Scanner(System.in);
System.out.println("请您输入您的注册邮箱:");
String email= sc.next();
//判断邮箱格式是否正确
//1111111111@qq.com
//1111111asd111@163.com
//1111111adf111@pci.com.cn
if(email.matches("\\w{1,30}@[a-zA-Z0-9]{2,20}(\\.[a-zA-Z0-9]{2,20}){1,2}")){
System.out.println("邮箱格式正确,注册成功!");
break;
}else {
System.out.println("格式错误!");
}
}
}
public static void checkTel(){
while (true) {
Scanner sc=new Scanner(System.in);
System.out.println("请您输入您的电话号码:");
String tel= sc.next();
//判断格式是否正确
//027-2132456
//0274561238
if(tel.matches("0\\d{2,6}-?\\d{5,20}")){
System.out.println("格式正确,注册成功!");
break;
}else {
System.out.println("格式有误!");
}
}
}
}
利用正则对内容进行分割:
package com.itheima;
public class FenGe {
public static void main(String[] args) {
//利用正则对内容进行分割
String names="小李asdfg1a容儿asdfgb5果儿";
String[]arrs=names.split("\\w+");
for (int i = 0; i < arrs.length; i++) {
System.out.println(arrs[i]);
}
String name2=names.replaceAll("\\w+"," ");//优化输出格式
System.out.println(name2);
}
}
正则表达式支持爬取信息:
13.Arrays类的API
package com.itheima;
import java.util.Arrays;
public class ArraysDemo1 {
public static void main(String[] args) {
//目标:学会使用arrays类的常用API,并理解原理
int []arr={10,2,55,23,24,100};
System.out.println(arr);//会输出地址
//String rs= Arrays.toString(arr);
//System.out.println(rs); //输出内容
System.out.println(Arrays.toString(arr));//输出内容
//排序
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
//二分法搜索(前提数组必须排好序才支持,否则出bug)
System.out.println(Arrays.binarySearch(arr, 55));//返回的是索引,如果未排好序输出的索引将是负数
}
}
自定义排序规则:
设置Comparator接口对应的比较器对象,来定制比较规则。
官方定义的默认升序规则:
如果认为左边数据 大于 右边数据 返回正整数
如果认为左边数据 小于 右边数据 返回负整数
如果认为左边数据 等于 右边数据 返回0
降序规则相反即可
类
package com.itheima;
public class Student {
private String name;
private int age;
private double height;
public Student() {
}
public Student(String name, int age, double height) {
this.name = name;
this.age = age;
this.height = height;
}
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 double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", height=" + height +
'}';
}
}
package com.itheima;
import java.util.Arrays;
import java.util.Comparator;
public class ArrarsDemo2 {
public static void main(String[] args) {
//目标:自定义数组的排序规则:Comparator比较器对象
//1.Arrarys的sort方法对于有值特性的数组是默认升序排序
int[]ages={34,12,42,23};
Arrays.sort(ages);
System.out.println(Arrays.toString(ages));
//需求:降序排序(自定义比较器对象,只能支持引用类型的排序!!)
Integer[]ages1={34,12,42,23};
/**
* 参数一:被排序的数组,必须是引用类型的元素
* 参数一:匿名内部类对象:代表了一个比较器对象
*/
Arrays.sort(ages1, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
//自己指定规则
/** if(o1>o2){
return 1;
}else if(o1<o2){
return -1;
}
return 0; */
// return o1-o2;//默认升序
return o2-o1;//降序
}
});
System.out.println(Arrays.toString(ages1));
System.out.println("``````````````````````````````````");
Student[]students=new Student[3];
students[0]=new Student("吴磊",23,175.5);
students[1]=new Student("小李",18,185.5);
students[2]=new Student("王亮",20,195.5);
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// return o1.getAge()- o2.getAge();
//比较身高不能这样写,因为小数
return Double.compare(o2.getHeight(), o1.getHeight());
}
});
System.out.println(Arrays.toString(students));
}
}
14.二分法查找
- 二分查找性能好,二分查找的前提是必须是排好序的数据
- 二分查找相当于每次去掉一半的查找范围
结论:二分查找正常的检索条件应该是开始位置min<=结束位置max
数组的二分查找的实现步骤是什么样的?
- 定义变量记录左边和右边位置
- 使用while循环控制查询(条件是左边位置<=右边位置)
- 循环内部获取中间元素索引
- 判断当前要找的元素如果大于中间元素,左边位置=中间索引+1;
- 判断当前要找的元素如果小于中间元素,右边位置=中间索引-1;
- 判断当前要找的元素如果等于中间元素,返回当前中间元素索引。
package com.itheima;
public class Test3 {
public static void main(String[] args) {
//1.定义数组
int []arr={10,14,16,25,28,30,35,88,100};
System.out.println(binarySearch(arr,35));
}
/**
* 二分查找算法的实现
* @param arr 排序的数组
* @param date 要找的数据
* @return 索引,如果元素不存在,直接返回-1
*/
public static int binarySearch(int[]arr,int date){
//1.定义左边位置 和 右边位置
int left=0;
int right=arr.length-1;
//2.开始循环,折半查询
while (left<=right){
//取中间索引
int middleIndex=(left+right)/2;
//判断当前中间位置的元素和要查找的元素大小情况
if(date>arr[middleIndex]){
//往右边查找,左位置更新为=中间索引+1
left=middleIndex+1;
}else if(date<arr[middleIndex]){
//往左边查找,右位置=中间索引-1
right=middleIndex-1;
}else {
return middleIndex;
}
}
return -1;//查无此元素
}
}
15.Lambda