java day 11
综合小项目
现在情况就是做个家电系统;
1.肯定有家电那你就得想到有哪些家电,创建好实体类,比如用继承吧;你创建好一个父类,叫家电;然后什么灯啊什么的都继承他;
2.继承好了里面的属性之后,记住我们很多操作直接就在父类里面建立,包括方法,因为这个一写,子类全部继承了
3.现在属性都创建完毕了;我们可以来写功能,毕竟我们要开关
4.我们一看到功能就要想到写接口;接口就非常方便呀,你写的不太行,别人拿到你代码直接重写接口方法就可以拉
5.我们接口里面就定义一个按压的方法;一被调用,我们就按下,按下状态就改变,现在接口写好了,我们让父类实现一下接口implements
6.实现之后,我们重写,记得加注释哦;重写里面直接写一个status=!status;为什么呢,因为我们本来就是布尔类型的值,如果是true我们直接取反,意思就是你一按就取反;非常方便!一句话就写完了;
7.写完接口拉,我们功能可以实现了;我们现在应该有个操作系统,让我们去看到,比如去输入一个数字,然后定位到对应的家电然后去操作,就得有个这种操作系统呀;所以我们还得写一个类;遇事不决就建立新类!
8.操作系统类里面我们主要要写:就比如先打印所有家电目前的状态吧:那是不是定义好第一个方法,就取名叫打印方法:里面要循环遍历一下数组吧;访问到所有的值是不是;然后打印出来就完了,那我们这个方法写完,去测试类里面要建立一个对象吧去访问,然后调这个方法的时候,我们把我们的数组以传参的方式直接传送过去就好了;那边就遍历打印输出拉,这个类似于我们之前的操作实体类;
9.那我们来写第二个方法;第二个方法我们是不是要选择好家电,然后调用按压方法来开关,那我们就直接再测试类里面先把选定目标搞定;比如我们先写一个命令,然后自己输吧,然后把这个命令去用switch比较;提示一下空调是1,灯是2,电视机是3,4退出吗;
然后比如case1:的时候我们就是传输给操作类第一个数组,也就是空调内个数组,我们还是用对象调用方法的形式,参数是jd[0]传给;
那我们操作类里面的第二个方法,写的接收参数肯定就是JD jd 然后接收到了,我们直接先打印,现在的状态是: ,然后jd.press()一下这个方法;然后我们输出按下后的状态;就成功完成啦;
10.但是我们肯定经常想要一次性操作两个家电或者三个吧;这次循环一次只有一下怎么办?我们再外面套一个while(true)给他全部包裹起来,这样我们就可以循环利用啦;就可以一直一直操作了;记得4退出的时候我们写个return;这个是经典退出循环的方式;至此逻辑就理清楚了;小项目不是很难;现在没数据库所以都是数组;然后就是类与类之间的调用;
11.再细节一点,比如你输入别的数字;记得报说输入错误
这是家电的代码 我的lombok的依赖没搞好,还是直接生成的构造函数和getter setter;0.0
package com.example.demo2.project;import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class JD implements Switch{private int id;private String name;private boolean status;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public boolean isStatus() {return status;}public void setStatus(boolean status) {this.status = status;}public JD(int id, String name, boolean status) {this.id = id;this.name = name;this.status = status;}@Overridepublic void press(){status=!status;}
}
这是测试类的代码
package com.example.demo2.project;import java.util.Scanner;public class Test {public static void main(String[] args) {
//建立好所有家电之后,咱们开始给数据;JD[] jd = new JD[3];jd[0] = new Air(1, "空调", true);jd[1] = new Deng(2, "灯", false);jd[2] = new TV(3, "电视机", false);//数据准备好之后,开始写功能拉,你要做开关那你就得给每个设备设置一个开关的功能//这时候的思路就可以是,定义一个接口让jd父类继承,然后就能每个人都能访问到这个接口的功能了//接口的方法一定是抽象的,所以我们可以直接定义Switch,然后让别的类去重写;//然后就是写控制系统;控制每个开关打开与否,要先接收对象,然后对对象进行操作//就是现在创建一个名字叫控制的类;里面去定义操作这些实体类的方法就叫c1吧;//然后我们用对象去掉这个方法;方法里面就写对这些家电的操作;里面的参数就给这些家电就行;while (true) {control c = new control();//输出全部的状态c.printStatus(jd);//开始控制;System.out.println("开始你的操作,选择你要控制的设备(输入编号,输入4退出系统):");Scanner scanner = new Scanner(System.in);int command = scanner.nextInt();switch (command) {case 1://如果是0就传入第一个是空调 调用第二个操作的方法c.controlJD(jd[0]);break;case 2:c.controlJD(jd[1]);break;case 3:c.controlJD(jd[2]);break;case 4:return;default:System.out.println("输入有误,请重新输入");}//但是我们肯定想有一次性操作两个的时候;但这个系统只可以一次性操作一个,怎么办?让他进入循环//比如直接让他进入一个while(true)里面//如果想要退出的话,就直接比如输入exit就直接退出了;}}
}
别的类就是直接建立之后继承就行了,记得生成构造函数;接口那就直接里面就是一个void press的抽象方法就没啥代码的;具体就是黑马网课;
注意一点:
就比如吧;你在这个项目里面;你只用到了单例类啊;你只有一个对象,你没别的了;防止错乱,你可以把这个对象设置成一个单例类;
确保全局只有一个对象;代码可能好维护些;
类中的成分
代码块
静态代码块
写是直接由static{}就完毕了,他是和类一起加载,可以加载一些类的初始值;
里面的东西都只执行一次而且也只有一个;
在外面声明的变量可以在这赋值;在主类输出就好了;
实例代码块
是直接{}就完毕了;他是在创建对象的时候才调用;注意,这里是只创建本类的对象;不是创别的类的对象;
内部类
内部类主要是,在类的内部再定义一个类;
成员内部类
他基本上就是再类的内部再定义一个类然后里面该有的都有,但创建对象需要原类点到内部类,再创建对象,然后new分配空间的时候需要再点到具体的内部类,以此类推;类具有的都有。他可以直接访问到外部类的静态成员还有实例方法
从这就能看出来很偏了 定义好的内部类吧;你里面定义了变量里面再有方法,输出当前值就直接输出,输出内部类的值就this,意思是给这个内部类速度创建一个对象;然后去点访问;如果要外部类,那就外部类名.this.变量,就是一个逐级逐层的一个过程;再一个,如果调用内部类的方法,也是需要给内部类先创建对象;那就得先找到内部类用外部的类名点访问然后创建对象以此类推;
自己用这个比较小,主要是理解别人的程序
静态内部类
再着重强调一点;静态这个东西你一加;你就必须只访问一次了;这个东西就是只限制一次的;所以静态内部类吧,也只加载一次:他是属于外部类本身持有,和成员内部类差不多,但是他new的时候就不用这样new了;他直接用类名点访问就行了;基本上任何地方只要权限足够都可以访问静态成员
其实一定主要就是要分清楚:静态成员他主要就是属于类的,很多时候可以直接类.访问的:而实例成员这个必须是对象的
你在类中定义的实例成员,他最终最终都是必须用创建对象的方式去访问;所以:静态内部类他无法访问外部类的实例成员
匿名内部类
在内部类中比较重要的就是匿名内部类:比较重要,用的很多
简单认识 就是他有名字,但是咱们不用去声明,他有个隐藏的名字:然后呢格式就是直接new父类或者/接口就行了;所以一看他就是作为一个子类存在,然后他会立即创建出来一个子类对象,所以创建子类和对象立马就完成了,这种就非常非常方便;
他的内容体呢主要就是对父类方法的重写
场景理解;原本继承的时候吧你必须父类是抽象类吗,里面所有的抽象方法都得重写;但是,抽象类是没有对象的!无法直接在抽象类上创建并调用其内部的方法;但是这个匿名内部类可以!他直接让抽象类分配创建一个匿名内部子类然后,直接重写就行;这样既创建了对象;又创建了子类。一般的写法是直接new+类名(参数){方法重写};
但是最快的写法就是直接创建一个对象,去接受这个匿名内部类;然后直接对象和子类都创建完毕了;
使用场景
他这个使用场景就非常特殊了;比如哈;
他立马就能创建好一个对象是吧;他可以被这个对象接受吗;那他就可以作为这个对象给别人当参数;给到一些方法中去用;
这里就是比如一个接口他要看学生老师分别是什么游泳,本来应该接口写出来之后,让他们自己各自创建类去重写方法;但是现在吧:你可以直接用这个接口创建一个匿名内部类,用一个对象接收,则方法里面直接传这个对象就行,效果一样;咱们匿名内部类里面就直接把这个方法重写就行了,再一个,老师怎么办,再创建一个匿名内部类就行;同理的,这个也称之为对象回调
在这里可以看到,匿名内部类直接作为参数传下去了;start是调用方法,里面直接跟了一个匿名内部类,重写方法则可;上面也同,意思就是不用费劲写一个s1作为中转站了;你本来要去用s1先接收匿名内部类;完了之后还得把这个变量传参给下面的方法;
再一个使用场景
他这个就是写了个登录窗口;然后呢你点击登录肯定要有反应吧:你点击之后要上个事件监听器吧;监听器要看到是否点击吧;然后呢,用对象调这个方法;这个方法里面要一个参数;就理解成我们点击之后要干什么,书写的地方;然后我们点击之后吧;你参数直接可以设置成内个匿名内部类;里面直接重写方法就好了,对象也自动创建了,直接还是用btn就行,然后我们点击事件就设置好了;
一般都是要求才写;基本上就是用别人写好的api的时候吧;点进去发现人家就是一个接口让你重写方法罢了;这时候其实立马想到用匿名内部类是最快的;因为你省去了创建别的类的时间;再一个是什么;你省掉了创建对象的时间;一次性直接new 类名(){在里面重写是最快的}再一个就是你的参数要注意,这时候匿名内部类就作为一个对象,一个参数给到人家的api了,可以重写人家的方法;自己定义了;
这时候不得不回忆一下接口的相关知识;人家本来一个人一个功能你一个个写非常非常麻烦;而且你们俩有很多相似的功能你还得写一遍,所以我们定义一个接口,把同样的功能就直接定义好再接口里边是默认方法吗;大家实现之后直接都用;’然后不同的功能你就重写接口的抽象方法,非常的方便了;匿名内部类不也是重写人家的api里面的某个抽象方法吗;
在开发中,比如给数组排序吧;比如按年龄排序吧;数据结构里面可能是插排,冒泡排序,快排,堆排什么的各种;但是吧这边人家都是写好的api,你可以直接就是调用人家写好的排序方法
直接array.sort()这个方法直接就帮忙拍好了;但是需要你传参啊,不然不知道排哪个
欸,这时候右边的意思是要需要你制定排序规则,这不就是重写方法吗!那是不是又是匿名内部类;我们直接New起手写好;至于这里的格式不一样,后面还会再说;
咱们制定就是里面的方法吧,重写,01 02这个直接比较,因为sort默认拿两个数进来比;如果咱们相减为正数;那就代表o1>o2,直接就是升序排;如果为负数,意思就是降序排;等于就写0;
然后这个代码可以简化。
函数式编程
用函数替代内部类的对象,让代码简洁
这里的函数不是c语言的方法;因为语言不同,java中的函数主要就是类似于api,但是都有很多不同的要求,还有比如这个lambda函数简化版,他很多时候就是为了简化内部类的书写的
很类似箭头函数了;非常,因为他简化了函数体和返回;在java里面称他为lambda函数式;
他唯一有个点就是
他只能简化函数式接口的匿名内部类;,就是匿名内部类他必须是继承的是函数式接口才行;不能是别的;
看我写的这个例子
这个就是用抽象类,匿名内部类纯用的抽象类
他必须是实现接口,所以他报错了;
所以lambda函数必须是继承函数式接口才行
接口也有很多,本来接口里面就可以写默认方法抽象方法等;但是我们把只有一个抽象方法的接口称之为函数式接口;
在接口处加上这个注解,就保障你不会写错;
lambda函数简化代码
注意,java里面报灰色的一般都可以直接简化掉,不确定的可以按住alt直接进去看源码;一般看到有函数式接口的这个注解哈;就肯定可以简化了,肯定是用来匿名内部类的;
简化一般就是()->{函数体};
而且简化完毕之后还能简化
看这个例子的简化步骤;非常离谱啊也是;里面先是内部类,内部类变成lambda函数吧;直接就说()->{}本以为是标准;
然后参数类型可以不写,去掉参数类型
继续;如果只有一个返回语句就省略;和大括号变成最后一句;
如果想要彻底简化,不如写出最初的样子,我们最后检查代码的时候来看;慢慢养成一步到位在脑子里面构思好的状态;
方法引用
就是在特定场景下,简化lambda函数;
妈呀听到这已经感觉很偏了,就是极致的省略
本来函数里面就是在掉方法,你直接封装成一个唯一的静态方法;然后卸载右边变成规则调用的其中一个写出来第二行代码
然后,只调用一个静态方法;又可以终极省略成为一个双冒号的终极形式;还有,前后参数要一致;这都是有特定场景的;还得是静态
和静态引用很像了哈;就是条件场景不一样
因为你是实例方法,你还得先创建个对象调用;人家静态的还可以直接用类名
行吧,这里我就过一遍脑子,先跳过了;以后看到双冒号大概是理解了就是一个终极的简化匿名内部类的过程
再一个记得每次打对象类型的东西的时候用Array.toString方法去打,免遍历了,直接打内容
这里的例子是按首字母排序,我们需要知道A的码是65,a是97
这里直接用sort这个方法是默认按首字母编号大小排序的;我们需要在后面加一个比较器,制定一些java官方不能制定的规则
他就是匿名内部类了
我们想一个个字符串去对比;数据结构可能是有学过,每一个字符串去对比吧;
但是实际开发也是非常的麻烦了如果是那些;所以;我们会调用也是欧克了,够用直接返回这个对象调用的这个方法就行;我们可能需要去记住;
让我深深感觉,很多的人其实还是敲的很表面,所以程序员35失业;如果真的能敲到这个底层逻辑,去给软件平台写这个最底层的代码;写别人封装调用的代码,写好给别人用;或许这样才能不被淘汰;
这个场景就非常的刁钻了,真的很刁钻;1你得是特定的方法;2,得是实例的要对象去调的;3第一个参还得是方法的主调;满足很多才可以简化成最终的双冒号形态
构造器引用
好,到这我感觉这个方法引用的课吧,我觉得我直接就是只需要记住函数式接口的匿名内部类可以快速创建对象和子类;而且可以被lambda函数简化就行了;…
常用API
String字符串,很重要,比如浏览器搜索你标红的,还有每次给你提示记忆的,都是把你上次搜索的关键字记下来的;再一个像这种替换敏感词的;等等等等都是
首先用字符串封装数据
我大致的理解就是,以前把他看作一种类型吗;现在看作是一个类;
给一个很好的解释例子
直接“" 的他比的是内容;但是如果是new的话是分配一个新空间,他当然比的是两个不同的地址;所以;他们不一样;
所以我们常用第一种
常用的方法
这些几乎都是常用;非常的重要;就比如判断相等啥的;判断字符串的内容就是equal,判断地址是==
登录也是
预设一个登录名字吗;你自己输入,然后if else判断就完了,用比较字符串内容是否相等;用到这个方法则可
还有截取;这个可以不暴露隐私信息;
用一个案例
就比如登录验证随机生成验证码
可以问ai,不管是帮忙实现还是提供思路,都是一个很不错的选择;
小功能,提供一个随机验证码
思路就是,先创建String的对象;然后里面写好我所有该写的该生成的数字字母大小写啥的;
然后命名一个空对象,作为随机数;
然后遍历一些索引,从索引里面随机挑n个出来;索引就强转int里面是调用了一个生成随机数的方法;然后乘以长度;假设现在有50个长度吧;那就从0-49全部遍历完毕;然后随机获取的4个用刚刚的空对象拼接起来;调用字符串的chatat方法获取对应的字符;就是对应的索引下的那个字符;然后让code累加,注意;字符串的累加就是拼接;
然后,返回验证码就行了;
Arraylist
集合
光数组的长度是固定的,而且增删改,还是比较麻烦,所以定义了很多不同类型的集合。
其中其实set map arraylist用的最多
这里是集合的常用方法;以及和集合的构造器
咱们开始创建一个空集合出来,然后对象是list这个尖括号里面一般是泛型;这个东西呢;他要规定一些标准,比如
你往集合里面添加的东西必须是字符串类型吧;那就再尖括号里面加个String;
还可以是别的;然后就可以根据规则来用对象调集合的方法比如添加啊;就增删改查;
根据方法来实现还是比较简单的
集合也是主要用来存储数据的;
用集合做项目更快,比数组更快,数组大小长度限制太死
GUI编程
简单来说就是先让咱们的代码有个简单的也页面,方便给用户操作;也更直观
他就是一个类里面有很多方法,一运行有个界面图
布局管理器 ;
水平流线布局啊等等等等等等;4种布局方式,有附带文档,最后一个是盒子布局,也就是按坐标;很类似前端了;X是横着Y是竖着控制间距等等;盒子模型布局还是常用于前端的;
这种GUI编程很适合做桌面的小游戏;
这些GUI很多界面设计就找AI做则可,他的组件主要就是用swing
但是他现在主要是就是个组件和界面;但是;光做组件界面,点击不了,点击事件的原理就是;你点击了要形成什么?
要干什么?
感觉以前的java开发小游戏主要就是GUI编程了;现在都得是前后端分离做非常完美的项目和页面;上线一个漂亮好看的app,还有什么别的;太多了;
好绑定监听事件;比如点击事件;好又来了;你每次调用别人 的API的时候;就是又又点进去发现是个函数式接口了;欸;那就很合适;咱们就可以重写,第一个就要想到匿名内部类;然后直接重写;里面写点击事件点击之后要干嘛,是输出还是跳转等等;这思路就可以和前端结合了;比如点击之后咱们获取到数据吧;或者是累加?或者是发送请求?可多;
比如调用点击事件监听对象的方法吧;里面咱们重新写了一个匿名内部类
给自己注意一下;匿名内部类没有名字,他new后面的这个完全就是类名!!!!!!
这个是按键的监听;可以监听到用户到底按下了那个地方;而且遇到了一个问题,因为我们不停的往上覆盖,导致按钮变成了第一个触发对象所以没办法成功,我们还得设置最底层面板为最上;然后进行点击;他通过ADDKEYLISTENER这个方法吧去监听到我鼠标的动静;然后重写的匿名内部类里面咱们就是直接给点击之后的操作就行;
这个很适合做游戏
GUI我就直接跳过了,现在基本上没人用,都是前后端发请求,直接转战前端完成;
小项目实战
AI加GUI的人事管理系统
首先,先写我的思路;
人事管理系统;他得有所有人吧。然后人员的各个职位,该有的属性都得有吧
再一个;他得有每个职位所对应的能力吧;谁管谁,谁不能管谁;对应职能
然后还得有个操作他们的系统吧
1.一个父类;定义所有人员的名字,身份证,ID工号,然后别的继承,假设简单点;一个公司得有普通员工吧;然后就是经理,老板,先简单点;他们自己去继承然后添加自己的东西;
2.然后就是对应职能,写个接口吧;写两个方法吧先;想想人事管理系统;那肯定就是来新人;和辞退这种吧,最基础的;来一个新人;就是添加人的方法;走一个人就是删除的方法。先这么想着;
3.那我得去实现吧,写几个接口的实现类;比如第一个人员调度的操作类;我去实现这个接口;重写;第一个添加人;如果这个人符合标准给个if else,我们就添加;第二个方法,我们直接如果员工不符合标准,我们就删除;天,这套项目感觉就在删除我自己0.0;
4.好,第一个实现的功能完成了,那还得有第二个实现的功能?比如人事管理系统还得考勤和发工资吧;我称之为工作日常操作类;然后第一个重写的方法就是直接比如到日期,每个人该发多少,比如判断这个是员工还是经理;员工发4k,经理5k吧;第二个重写的方法emmm考勤;那考勤得怎么办?每日监督打卡?这个打卡如何监督呢?设置每个员工的状态?员工得点击操作?先不设置考勤?这个想不出来;先写一个基本的人员吧;
这里发现用数组不好做删减,最好的就是写一个集合用Arraylist的很多方法才行;
我先写了查询和打印所有人,然后显示未打卡的人和人数,其实就是判断一下状态;
添加人和删除人我写了个接口我不会重写,一到功能就头疼;盗版idea下载不了Lingma呜呜
好了,看讲解;
可以说老师的逻辑是非常清晰的了
从用户登入的逻辑上来思考吧;咱们先创建好模块吧;然后就是分析业务需求;
1.先提供登陆页面;登录,注册都得有;
2.进来要显示所有的员工界面吧,管理界面吧;展示信息吧;然后有查询按键,点击之后就能查吧;
3.然后就是增删改查了;基本功能是这些;其实类似毕设的什么留言啊还有什么别的等等都主要是做这些
开始分析角色;其实基本上也是人事部门的人才登录
登录的人;用户的名字和密码;
员工信息;各种属性
分析界面:
登录界面,管理界面,就两界面
差不多的需求就在这里了;
然后结合通义千问;
老师用ai生成了关于swing组件的gui 的一个界面,然后吧密码,名字,按钮,这几个东西提到最前面去了;变成了私有的成员变量,创建对象即可访问;这样方便我们以后拿取值
这里了解到企业级基本上就是;拿到别人的代码去改
用ai开发一个GUI的编程是非常非常快的;
用ai生成了两个假页面,一个是登录,一个是管理的各种的表格吗;
但是其实业务逻辑没有到位的;很多功能是没实现的;现在才来做真功能,只有刚刚的话;系统一重启,所有的东西直接就清零为空了;就理解成前端做好了就行;毕竟vscod等很多工具他也不过就是GUI的一类吧,(个人理解);
起手先创建用户类和员工类吧,基本上就给他丢在bean包下;有的人也叫POJO,就是很多成员
现在基本的东西好了;需要开发登录功能了
其实理解就三步;1.前端界面;2.实体类,数据库设计;3.去开发功能
好,现在开发功能吧:第一个登录界面来看
那我们就需要登录和注册的功能
但是,我们登录要校验啊;就是后台得本身先有点数据才行;就比如基本管理员什么的;不过我也可以直接给;直接给一些数据;
然后校验则可;直接给的数据在where?我们基本上就是存在DB里面;但是需要学数据库吗;我们现在没数据库我们只能先放到系统里面;
那我们想放数据;那我们得准备集合容器吧?数组不好增删的吗;
而且细节的一点就是我们最好就把他定义成静态的;因为这个随着类加载之后他也是顺带加载的;所以说初始数据一并就加载出来了;
其实到这都还好理解;因为吧上面就是成员变量,然后咱们创建了一个静态的集合吧;然后里面我们直接用对象调集合自己写好的方法;里面就直接给数据就行了;当然这样已更新,比如项目重启肯定是又没了;所以这就是数据库的重要性;
好,继续;
对于登录功能的实现
理论上;应该是绑定点击事件‘然后点击之后就可以进行对应操作;然后拿到用户名和密码;再一个,获取到之后;开始校验,去咱们的数据库里面,或者是你存的集合和数组里面看有没有这个用户对象;名字和密码是否匹配;完了之后如果完全匹配;就跳转到登录页面;不能完全匹配就说失败,然后提示;
登录逻辑呢;就是比如吧:这个是获取登录的方法;,登录之后该干什么?写的功能在这;他可以获取到用户名和密码;一点击就能获得到这个用户名和密码;然后去根据登录名字查询我们存的用户对象并进行返回;直接判断用户名是否相等;相等就找到了然后通过;返回这个对象数据就行
然后继续完善;再写个方法;如果返回的对象user等于null,就登录失败;如果等于数据库里面的相等匹配了;那就返回登录成功;直接在方法体里面写跳转到管理页面;
完善登录的逻辑;
在下一个就是完成信息管理界面的核心开发;
1.登录成功之后;返回用户名;
2.现在就是完善功能:先准备静态集合;存储信息;点击事件;点击之后完善逻辑;这里的构思是弹出一个添加框;让你添加对象;对里面的数据一一录入到数据库;或者现在就是集合里面也欧克
下一章继续;