J面向对象程序设计第三次博客
面向对象程序设计第三次博客
一:前言
(1):知识点
JavaFX的安装与基本使用
抽象类的作用以及使用
容器ArrayList的增删改查
迭代器的查找
(1):JavaFX的安装与基本使用
一:概况
窗口(stage):窗口里面可以设置场景,但是一次只能显示一个场景。
场景(scene):场景可以添加UI组件图的树形结构。
根节点(parent):根节点设置为一个布局,放置不同的节点(组件)。可以在根节点嵌套放置根节点。
二:基本类
On Drag Detected:当你从一个Node上进行拖动的时候,会检测到拖动操作,将会执行这个EventHandler。
On Drag Done:当你拖动并松手的时候,执行Drag完成操作。
On Drag Dropped:当你拖动到目标并松开鼠标的时候,执行这个DragDropped事件。
On Drag Entered:当你拖动到目标控件的时候,会执行这个事件回调。
On Drag Exited:当你拖动移出目标控件的时候,执行这个操作。
On Drag Over: 当某被拖动的对象在另一对象容器范围内拖动时触发此事件,会不停的执行。
On Mouse Drag Entered:定义当完全按下并释放手势进入节点Node时要触发的事件。
On Mouse Drag Exited:定义当完全按下并释放手势离开节点Node时要触发的事件。
On Mouse Drag Over:定义在节点Node中完全按下并释放手势时要触发的事件。
On Mouse Drag Released:定义在节点Node中完全按下并释放的手势(通过释放鼠标按钮)结束时要触发的事件。
On Key Pressed:当键盘按键被按下的时候触发事件。
On Key Released:当键盘按键按下后被释放的时候触发事件。
On Key Typed:只会响应文字输入键,如字母、数字和标点符号等,它不会响应CTRL/ENTER/F1等功能键。
参考文献:
(1条消息) JavaFX之Scene Builder详细使用说明之设置篇(4)——代码Code_二木成林的博客-CSDN博客
(2)抽象类的作用以及使用
一:抽象类的作用
1、在面向对象方法中,抽象类主要用来进行类型隐藏。构造出一个固定的一组行为的抽象描述,但是这组行为却能够有任意个可能的具体实现方式。这个抽象描述就是抽象类,而这一组
任意个可能的具体实现则表现为所有可能的派生类。模块可以操作一个抽象体。由于模块依赖于一个固定的抽象体,因此它可以是不允许修改的。
2、通过从这个抽象体派生,也可扩展此模块的行为功能。为了能够实现面向对象设计的一个最核心的原则OCP(Open-Closed Principle),抽象类是其中的关键所在。
3、抽象类往往用来表征对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。
抽象类往往用来表征对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。
通常在编程语句中用 abstract 修饰的类是抽象类。在C++中,含有纯虚拟函数的类称为抽象类,它不能生成对象;在java中,含有抽象方法的类称为抽象类,同样不能生成对象。
抽象类是不完整的,它只能用作基类。在面向对象方法中,抽象类主要用来进行类型隐藏和充当全局变量的角色。
抽象类和一般类没有太大的不同。
该如何描述事物,就如何描述事物,只不过,该事物出现了一些看不懂的东西。
这些不确定的部分,也是该事物的功能,需要明确出现。但是无法定义主体。
通过抽象方法来表示。
抽象类比一般类多个了抽象函数。就是在类中可以定义抽象方法。
抽象类不可以实例化。
特殊:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象
二:抽象类的使用
1.抽象类和抽象方法的格式
抽象的关键字是abstract
抽象类: 加上abstract关键字修饰
抽象方法: 加上abstract关键字修饰,去掉大括号
2.抽象类和抽象方法的使用
要想使用抽象类和抽象方法必须具备继承关系
3.抽象类的注意事项
1.抽象类可以具有所有普通类具拥有的东西
2.抽象方法没有大括号
3.抽象类不能创建对象
4.抽象类中不一定有抽象方法
,但有抽象方法的类一定是抽象类
5.抽象类的子类必须重写父类的所有的抽象方法(子类是抽象类除外
)
6.抽象类的构造方法是提供给子类初始化父类成员使用的
参考文献
(1条消息) Java 抽象类的使用介绍_二师兄想吃肉的博客-CSDN博客_java抽象类的使用
三:容器ArrayLIst的增删改查
ArrayList不是多线程版本的容器,因此不需要做同步操作synchronized,保证了操作的效率,如果我们需要对单个ArrayList容器做多线程操作,可以在外部进行同步控制。而List家族
另一个古老的容器类Vector则是多线程版本的,现在使用不多。
1.增
①add()方法在数组实际存储的最后一个元素后面添加一个元素
②add(int, E) 在指定位置放上一个元素。
③addAll(Collection<>) 将给定容器中的所有元素都加入到本容器的尾部
2.删
①remove(int) 删除指定位置上的元素。
②remove(Object) 删除容器数组中的一个具体元素,该元素equals传入的参数,只删除第一次出现位置上的元素。
③removeAll(Collection<>) 从本容器中批量删除与给定容器中所有元素相同的元素。
④removeIf(Predicate<>, int, int) 给定一个检测器Predicate,从本容器数组的i位置开始查找,一直到end为止,如果满足条件,则删除该位置上的元素。
3.改
①set(int, E)方法将给定索引位置上的元素值修改为其他元素值,最后返回索引位置的旧值。
4.查
①get(int) 获取到给定索引位置的元素。
②indexOf(Object) 方法获取容器数组中,与给定元素相等的第一个元素所在的索引位置。
四:迭代器的使用
迭代器 it 的两个基本操作是 next 、hasNext 和 remove。
调用 it.next() 会返回迭代器的下一个元素,并且更新迭代器的状态。
调用 it.hasNext() 用于检测集合中是否还有元素。
调用 it.remove() 将迭代器返回的元素删除。
删除元素
要删除集合中的元素可以使用 remove() 方法。
参考文献
(1条消息) JDK源码阅读(六) : 容器——ArrayList_リュウセイリョウ的博客-CSDN博客
二:设计与分析
一:电信计费
(1):座机用户打电话
获取用户通话电话号码以及打电话人所在区域,接电话人所在区域,通话时长,针对不同区域进行不同计费类型,最后输出打电话费用以及剩余电话费用。
(2):手机与座机同时计费
要获取是手机还是座机,如果是手机还得单独获取手机所在区域,手机增加了一个计费类型,就是当手机在省外区域时,需要考虑漫游计费;
(3):短信计费
短信来说,就不需要考虑出现的位置,只需要考虑信息长度,整个代码思路还是清晰的;
(4):设计
电话号码的获取,最开始以为输入的电话号码位数是固定的,直接采用CharAt获取后面的字符串,但是最后才意识到不对,之后是采用spilt分割,将数组第一位处理,储存在电话号码
中,如果是座机,第二位便是接电话,如果不是,判断数组长度,如果是六位,那就是都是座机,如果是七位,就是一个座机一个手机,如果是八位,那就是两个都是手机,所以数据处理
起来还是很好的。
时间的获取以及输入时间段的格式是否正确,采用simpledataformate,这个可以判断时间格式是否正确,还能够获取时间长度
import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner; import java.util.regex.Pattern; public class Main { public static void main(String[] args) { // Scanner input = new Scanner(System.in); // String str = input.nextLine(); String[] ss = new String[20]; getinput in = new getinput(); ss = in.getit(); people[] p = new people[20]; people[] pc = new people[20]; people[] pa = new people[20]; people pp = new people(" "); pp.getpeople(p, ss); pc = pp.getcallpeople(ss); pa = pp.getanswerpeople(ss); pp.dealmeassage(pc); pp.dealmeassage(pa); pp.getcallmoney(pc); pp.getanswermoney(pa); p = pp.getrealpeople(p, pc, pa); in.output(p); // input.close(); } } //获取输入并处理 class getinput { public String[] getit() { Scanner input = new Scanner(System.in); String[] ss = new String[20]; sum a = new sum(); int i; i = 0; boolean flag; while(true) { String line = input.nextLine(); ss[i] = line; if(ss[i].equals("end")) break; flag = a.isright(line); if(flag) { ss[i] = line; i++; } } a.cutit(ss); return ss; } //输出 public void output(people[] pp) { int i,j,m,n,f; people p = new people(); // for(i=0;i<pp.length&&!(pp[i]==null);i++) // { // for(j = i;j<pp.length&&!(pp[j]==null);i++) { // if() // } // } for(i = 0;i<pp.length&&!(pp[i]==null);i++) { System.out.printf(pp[i].call+" %.1f %.1f",pp[i].cost,pp[i].balance-pp[i].cost); System.out.println(""); } } } class sum { //获取电话天数 public int day(String str) { int i,j,k,g,f; g=j =f= 0; j=1; for(i=0;i<str.length();i+=j) { if(str.charAt(i)=='.') g++; if(g==2) { for(j = j-1;!(str.charAt(j+i)==' ');j++) { f =f*10+(int)(str.charAt(j+i)-48); } } } return f; } //计算打电话人电话位数 public int getnumberlog(String str) { int i,j; j = 0; for(i = 2;!(str.charAt(i)==' ');i++) { j++; } return j; } //计算座机通话费用 public double free1(int area,int time) { double money; money = 0; if(area==1) money = 0.1*time; if(area==2) money = 0.3*time; if(area==3) money = 0.6*time; return money; } //初步判断格式是否正确 public boolean isright(String str) { sum s =new sum(); String pattern,time1,time2; String[] ss; int i; boolean f1,f2; ss = str.split(" "); for(i = 0;i<ss.length;i++) { } pattern = "^[ut]-[0-9]{11,12}.+"; if(!str.matches(pattern)) return false; if(str.length()>20) { time1 = ss[i-4]+" "+ss[i-3]; time2 = ss[i-2]+" "+ss[i-1]; f1 = s.validDateTimeSimple(time1); f2 = s.validDateTimeSimple(time2); if(!(f1&&f2)) return false; boolean flag1,flag2; flag1 = true; flag2 = true; pattern = "^t-[0-9]{10,12}\\s([0-9]{3,4}\\s)?[0-9]{10,12}\\s([0-9]{3,4}\\s)?[0-9]{4}\\.[0-9]{1,2}\\.[0-9]{1,2}\\s[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}\\s[0-9]{4}\\.[0-9]{1,2}\\.[0-9]{1,2}\\s[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}"; if(!str.matches(pattern)) return false; } return true; } public boolean validDateTimeSimple(String dateTime) { if(dateTime == null ) { return false; } DateFormat df = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); df.setLenient(false);//表示严格验证 try { df.parse(dateTime); } catch (ParseException e) { return false; } return true; } //输入出现重复 public void cutit(String[] s) { int i,j,k; for(i = 0;!(s[i]==null);i++) { for(j = i+1;!(s[j]==null);j++) { if(s[i].equals(s[j])) { for(k = j;!(s[k]==null);k++) s[k] = s[k+1]; } } } } } class people { String s;//输入的代码 String call,callphone,answerphone,calldata,answerdata;//输入电话号码 int numbersum;//输入电话号码长度 int carea,area,time,type1,type2;//呼叫电话区域 接入电话区域,通话时长,计费类型 double cost,free,where,balance;//花费金额,剩余金额 public people() { } public people(String str) { this.balance = 100; this.call = str; int i; i = (int)(str.charAt(0)-48); if(i==0) this.balance-= 20; else this.balance -= 15; } //获取打电话人电话号码 输入电话号码 public String getcallphone(String str) { // String num; // String[] ss; // ss = str.split(" "); // num = ss[0].substring(2); this.type1 = (int)(str.charAt(0)-48); return str; } //获取接电话人电话号码和电话类型 输入为电话号码 public String getanswerphone(String str) { this.type2 = (int)(str.charAt(0)-48); this.answerphone = str; return str; } //获取接电话人区域 输入为电话号码 public void getanswerarea(String str) { this.area = this.thaarea(str); } //获取打电话人区域 输入为电话号码 public void getcallarea(String str) { this.carea = this.thaarea(str); } //获取输入打电话时间 public void getcalldata(String str1,String str2) { this.calldata = str1+" "+str2; } //获取接电话时间 public void getanswerdata(String str1,String str2) { this.answerdata = str1+" "+str2; } //计算座机电话费 public void getmoney11() { if(this.area==1) this.cost += this.time*0.1; else if(this.area==2) this.cost += this.time*0.3; else this.cost += this.time*0.6; } //计算手机打电话计费 public void getmoney12() { if(this.carea==1) { if(this.area==1) this.cost+=this.time*0.1; else if(this.area==2) this.cost+=this.time*0.2; else this.cost+=this.time*0.3; } else if(this.carea==2) this.cost+=this.time*0.3; else this.cost+=this.time*0.6; } //手机接电话计费 public void getmoney22() { if(this.area==3) this.cost+=this.time*0.3; } //获取通话时长 public void gettime() { SimpleDateFormat df = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); this.time = 0; try { Date d1 = df.parse(this.calldata); Date d2 = df.parse(this.answerdata); long diff = d2.getTime() - d1.getTime();//这样得到的差值是微秒级别 long days = diff / (1000 * 60 * 60 * 24); long hours = (diff-days*(1000 * 60 * 60 * 24))/(1000* 60 * 60); long minutes = (diff-days*(1000 * 60 * 60 * 24)-hours*(1000* 60 * 60))/(1000* 60); int sec = (int)((diff-days*(1000 * 60 * 60 * 24)-hours*(1000* 60 * 60)-minutes*(1000*60))/(1000)); this.time =(int) (days*24*60+hours*60+minutes); if(sec>0) this.time+=1; }catch (Exception e) { } } //获取电话人电话区域1:市内 2:省内 3:省外 public int thaarea(String str) { int i,area,n; area = 0; for(i = 0;i<4&&i<str.length();i++) { n = (int)((str.charAt(i)-48)); area = area*10+n; } //南昌市内 if(area==791) return 1; //江西省内 if(area<=799&&area>=790||area==701) return 2; return 3; } //开户 public void getpeople(people[] p,String[] s) { int i,j; j = 0; String[] ss; for(i = 0;!(s[i+1]==null);i++) { if(s[i].length()<20) { //开户,创建新的对象 ss = s[i].split(" "); people pp = new people(ss[0].substring(2)); pp.type1 =(int)(ss[0].substring(2).charAt(0)-48); p[j] = pp; j++; } } } //获取打电话名单 public people[] getcallpeople(String[] s) { int i,j=0; String num; people[] ps = new people[20]; people p = new people(); for(i = 0;!(s[i]==null);i++) { if(s[i].length()>20) { num = p.getcallphone(s[i]); people pp = new people(num); pp.s = s[i]; ps[j] = pp;j++; } } return ps; } //获取接电话名单 public people[] getanswerpeople(String[] s) { people[] ps = new people[20]; String num; people p = new people(); int i,j=0; for(i = 0;!(s[i]==null);i++) { if(s[i].length()>20) { num = p.getanswerphone(s[i]); people pp = new people(num); pp.s = s[i]; ps[j] = pp;j++; } } return ps; } //处理信息 public void dealmeassage(people[] pp) { String[] ss; int i,j=1; for(i = 0;!(pp[i]==null);i++) { j=1; ss = pp[i].s.split(" "); pp[i].callphone = pp[i].getcallphone(ss[0].substring(2)); if(ss.length==6) { pp[i].answerphone=pp[i].getanswerphone(ss[j]);j++; pp[i].carea = pp[i].thaarea(ss[0].substring(2)); pp[i].area = pp[i].thaarea(ss[1]); } else if(ss.length==7) { if(pp[i].type1==0) { pp[i].answerphone=pp[i].getanswerphone(ss[j]);j+=2; pp[i].carea = pp[i].thaarea(ss[0].substring(2)); pp[i].area = pp[i].thaarea(ss[2]); } else { pp[i].answerphone=pp[i].getanswerphone(ss[j+1]);j+=2; pp[i].carea = pp[i].thaarea(ss[1]); pp[i].area = pp[i].thaarea(ss[2]); } } else { pp[i].answerphone=pp[i].getanswerphone(ss[j+1]);j+=3; pp[i].carea = pp[i].thaarea(ss[1]); pp[i].area = pp[i].thaarea(ss[3]); } pp[i].getcalldata(ss[j], ss[j+1]);j+=2; pp[i].getanswerdata(ss[j],ss[j+1]); pp[i].gettime(); } } //计算打电话费用 public void getcallmoney(people[] pp) { int i; for(i = 0;!(pp[i]==null);i++) { if(pp[i].type1==0) pp[i].getmoney11(); else pp[i].getmoney12(); } } //计算接电话费用 public void getanswermoney(people[] pp) { int i; for(i = 0;!(pp[i]==null);i++) { if(pp[i].type2==1) pp[i].getmoney22(); } } //两个电话处理 public people[] getrealpeople(people[] pp,people[] p1,people[] p2) { int i,j,k; people p =new people(" "); for(i = 0;!(pp[i]==null);i++) { for(j = 0;!(p1[j]==null);j++) { if(pp[i].call.equals(p1[j].callphone)) { pp[i].cost+=p1[j].cost; } } for(j = 0;!(p2[j]==null);j++) { if(pp[i].call.equals(p2[j].answerphone)) { pp[i].cost+=p2[j].cost; } } } p.getsetposition(pp); p.orderset(pp); p.orderphone(pp); return pp; } //将座机全部移动到前面来 public void getsetposition(people[] pp) { int i,j; people p = new people(" "); for(i = 0;!(pp[i]==null);i++) { for(j = i+1;!(pp[j]==null);j++) { if(pp[i].type1==1&&pp[j].type1==0) { p = pp[i];pp[i]=pp[j];pp[j]=p; j--; } } } } //将座机中电话排序 仅仅排尾号 public void orderset(people[] pp) { int i,j,k,n; people p = new people(" "); int f1=0,f2=0; for(i = 0;!(pp[i]==null);i++) { if(pp[i].type1==0) { for(j = i+1;!(pp[j]==null);j++) { for(k = 9;k<pp[i].call.length()-1;k++) { } f1 = (int)(pp[i].call.charAt(k)-48); for(n = 9;n<pp[j].call.length()-1;n++) { } f2 =(int)(pp[j].call.charAt(n)-48); if(f1>f2) { p = pp[i];pp[i]=pp[j];pp[j]=p;j--; } } } } } //将手机电话排序 仅仅排尾号 public void orderphone(people[] pp) { int i,j,k,n; people p = new people(" "); int f1=0,f2=0; for(i = 0;!(pp[i]==null);i++) { if(pp[i].type1==1) { for(j = i+1;!(pp[j]==null);j++) { for(k = 9;k<pp[i].call.length()-1;k++) { } f1 = (int)(pp[i].call.charAt(k)-48); for(n = 9;n<pp[j].call.length()-1;n++) { } f2 =(int)(pp[j].call.charAt(n)-48); if(f1>f2) { p = pp[i];pp[i]=pp[j];pp[j]=p;j--; } } } } } }
三:踩坑心得
1:最开始对于题目信息获取采用固定的获取方法,代码复用性不强,而且代码全是大面积相同的,而且职责划分不明显,数据传入传出很乱,两个相似的代码,一个传入是整行代码,一
个是只传入部分代码,搞的每次都要看看要传入的是啥,让脑子更糊了。
2.除了要认真写注释,还要在么一次动笔之前认真理清楚题目的意思,实现大致过程,以便于之后代码的动笔
3.虽然说作业要自主完成,但是由于对于Java里面一些函数不太了解,有时候可以借鉴借鉴同学的代码,知道一些用得着的函数,会比自己漫无目的去写高效很多,当然,不是抄同学的思
路以及代码哈,利用好网上的资源,多去看看同类型的题目,或者搜索你想要的功能,可能软件里已经有了
四:改进建议
1.注释可以多加一点,方便自己之后看得懂
2.可以多去看看优秀的代码,方便自己知道一些有用的方法,不至于用起来啥都不知道
3.可能整个代码还是比较面向过程的,之后有点改动,但是自己觉得可能还是没有完全体会面向对象的精髓,还要加强
五:总结
1.这几次比之前好多了,也是题目比较简单的原因吧,然后也知道去问问同学老师,老师指出我面向过程还是太严重,之后自己有简单改进,虽然没有那么好,但是也差不多了
同学则是获取了一些自己之前不知道的方法,自己代码效率变高,也比自己去敲代码准确度更高
2.还是那些错误,只不过在一次又一次的过程中改进了一些罢了