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.还是那些错误,只不过在一次又一次的过程中改进了一些罢了

 

 

posted @ 2022-06-09 19:31  你郝呀  阅读(33)  评论(0编辑  收藏  举报