• 201521123063 《JAVA程序设计》 第5周学习总结


    1. 本周学习总结

    1.1 尝试使用思维导图总结有关多态与接口的知识点。

    1.2 可选:使用常规方法总结其他上课内容。

    • 上周学习了继承和多态,满足is-a条件,但是发现会导致继承的滥用,如果只是但以的想拥有某种行为或变量,不需要一定要继承才能实现,可以使用接口

    • Comparable和Comparator区别:
      Comparable接口只提供了int compareTo(T o)方法,而Comparator接口只提供了int compare(T o1,T o2)方法
      Comparator位于包java.util下,需要导入java.util.Comparator类,而Comparable位于包java.lang下,不需要导包
      排序方法:
      Collections.sort((List list, Comparator<? super T> c)
      Arrays.sort((List list, Comparable<? super T> c)

    • 接口与抽象类
      抽象类表示这个类是什么,接口类表示这个类能做什么
      抽象类和接口都不能直接实例化
      抽象类可以有具体的方法 和属性,接口只能有抽象方法和不可变常量
      一个类只能继承一个抽象类,而一个类却可以实现多个接口
      接口和抽象类区别

    2. 书面作业

    1. 代码阅读:Child压缩包内源代码

    1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误。并分析输出结果。

    在Child类中
     public void getParenti(){
            System.out.println(i);//此处报错:i不可见
        }
    分析:在Child的类中没有i这个属性,则morning会调用父类的i,但是i被private修饰,只允许本类访问,可改为protected,这样就可以允许子类访问了
    
    输出结果:
    1
    2
    2
    1
    1
    2
    1
    分析结果:
    由于子类Child类中没有i,j属性,那么就会使用父类的属性,所以那些输出结果都是用父类的i和j
    
    

    1.2 另外一个包中的OutOfParentPackage.java,能否编译通过?提示什么错误?分析原因。如何更改才能使之正常编译?

    public class OutOfParentPackage{
    	public static void showParentj(Parent p){
    		System.out.println(p.j);     //报错
    		System.out.println(p.geti());//报错
    		p.getj();                    //报错
    	}
    }
    

    答:不能通过编译,根据eclipse提示可以在Parent类中用getter和setter方法,或者将j的属性改为public修饰的,但是不大安全就是了,同理,也将geti和getj方法改为public的

    2. abstract进阶:阅读GuessGame抽象类的设计与使用源代码

    2.1 Guess改造前代码很简单,而改造后的代码使用了抽象类、抽象方法看起来很复杂,那这样的改造到底有什么好处呢?

    改造前:
    import java.util.Scanner;
    
    public class Guess {
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            int number = (int) (Math.random() * 10);
            int guess;
            
            do {
                System.out.print("猜数字(0 ~ 9):");
                guess = scanner.nextInt();
            } while(guess != number);
            
            System.out.println("猜中了...XD");
        }
    }
    
    改造之后:
    public abstract class GuessGame {
        public void go() {
            int number = (int) (Math.random() * 10); 
            int guess;
            do {
                print("输入数字");
                guess = nextInt();
            } while(guess != number);
            println("猜对了");
        }
        
        public abstract void print(String text);
        public abstract void println(String text);
        public abstract int nextInt();
    }
    
    

    分析:改造前的代码比较中规中矩,但只能在控制台输入输出,该造后,用abstract修饰输出输入的方法,使其抽象化,可以在控制台,图形界面或者以其他方式进行

    2.2 如果想将该游戏改造成图形界面,应该进行一些什么操作?

    答:首先肯定是要导入工具包,因为输入输出,还有获取输入都是用抽象方法,具体实现的内容是由继承这些类的子类来重写这些方法来实现
    

    2.3 结合该例子,你觉得什么时候应该使用abstract?

    答: 当一个类中没有充足的信息来描述一个具体的对象时,可以用abstract,以不变应万变
    

    2.4 重要:在这个例子中,变化的是什么,不变的是什么?尝试结合abstract、继承等概念进行说明。

    答:可以变化的是继承GuessGame的子类中复写父类的方法,即输入输出的方式;不变的是父类抽象类方法的定义,这些类不需要有具体的内容,毕竟不知道要干啥,可以随机应变,因为任何继承这个抽象类的子类都必须复写父类的抽象方法,这样想做什么就让子类来做就好了
    
    

    3. Comparable与Comparator

    3.1 描述Comparable接口的用途。为什么某个类实现了Comparable接口就可以直接使用Arrays.sort对其进行排序?
    在API中查找的结果:

    public static void sort(Object[] a)根据元素的自然顺序对指定对象数组按升序进行排序。数组中的所有元素都必须实现 Comparable 接口。此外,数组中的所有元素都必须是可相互比较的(也就是说,对于数组中的任何 e1 和 e2 元素而言,e1.compareTo(e2) 不得抛出 ClassCastException)。
    保证此排序是稳定的:不会因调用 sort 方法而对相等的元素进行重新排序。
    
    该排序算法是一个经过修改的合并排序算法(其中,如果低子列表中的最高元素小于高子列表中的最低元素,则忽略合并)。此算法提供可保证的 n*log(n) 性能。 
    
    
    参数:
    a - 要排序的数组 
    抛出: 
    ClassCastException - 如果数组包含不可相互比较的 的元素(例如,字符串和整数)。
    
    

    简要分析:comparable接口当中含有compareTo比较具体方法,但是只能按一种方式比较

    3.2 有了Comparable接口为什么还需要Comparator接口呢?

    Arrays.sort(T[] a, Comparator<? super T> c) 
              根据指定比较器产生的顺序对指定对象数组进行排序。
    API文档中查找的结果:
    sort
    public static <T> void sort(T[] a,
                                Comparator<? super T> c)根据指定比较器产生的顺序对指定对象数组进行排序。数组中的所有元素都必须是通过指定比较器可相互比较的(也就是说,对于数组中的任何 e1 和 e2 元素而言,c.compare(e1, e2) 不得抛出 ClassCastException)。
    保证此排序是稳定的:不会因调用 sort 方法而对相等的元素进行重新排序。
    
    该排序算法是一个经过修改的合并排序算法(其中,如果低子列表中的最高元素小于高子列表中的最低元素,则忽略合并)。此算法提供可保证的 n*log(n) 性能。 
    
    参数:
    a - 要排序的数组
    c - 确定数组顺序的比较器。null 值指示应该使用元素的自然顺序。 
    抛出: 
    ClassCastException - 如果数组包含使用指定的比较器不可相互比较的 的元素。
    

    简要分析:有了Comparable接口,Arrays.sort实现比较算法进行排序,但是形式比较单一,有了Comparator接口,在集合外定义compare()的方法,可以重写compare方法。传入了两个参数,就可以根据不同的排序要求作出排序,比较灵活,在书上284页也有相应的例子

    3.3 可选:使用匿名内部类、Lambda表达式实现PTA编程5-2。

    匿名内部类:(主要代码)
    
    Comparator<PersonSortable2> n1 = new Comparator<PersonSortable2>() {      //按年龄升序,定义了匿名内部类
    			public int compare(PersonSortable2 o1, PersonSortable2 o2) {
    
    				return o1.getAge() - o2.getAge();
    			}
    		};                                                            //注意此处的分号
    		Arrays.sort(p, n1);
    		System.out.println("NameComparator:sort");
    		for (int i = 0; i < n; i++) {
    			System.out.println(p[i]);
    		}
    		Comparator<PersonSortable2> n2 = new Comparator<PersonSortable2>() {   //按姓名升序排序
    			public int compare(PersonSortable2 o1, PersonSortable2 o2) {
    
    				return o1.getName().compareTo(o2.getName());
    			}
    		};
    		Arrays.sort(p, n2);
    		System.out.println("AgeComparator:sort");
    		for (int i = 0; i < n; i++) {
    			System.out.println(p[i]);
    		}
    		System.out.println(Arrays.toString(n1.getClass().getInterfaces()));
    		System.out.println(Arrays.toString(n2.getClass().getInterfaces()));
    
    
    Lambda表达式:
    	Comparator<PersonSortable2> n1 = (PersonSortable2 o1, PersonSortable2 o2) -> (o1.getName().compareTo(o2.getName()));  
    
            Comparator<PersonSortable2> n2 = (PersonSortable2 o1, PersonSortable2 o2) -> (o1.getAge() - o2.getAge());  
    
    补充格式:
         参数 -> 表达式或程序块{  }
         如果是表达式,则return该表达式的值(无需写return语句)
         如果是程序块{ },可以包含多条语句
    

    截图:

    4. 面向接口案例分析

    阅读Case-StudentDao.zip案例
    4.1 画出类关系图,描述每个类与接口的作用。

    此图由eclipse的UML自动生成


    Student类当中只有name这个属性,有有参的构造函数,还有其对应的setter和getter方法

    StudentDao接口定义了读写学生信息和显示全部学生信息的抽象方法,

    StudenDaoListImpl类实现了StudentDao接口,用列表来存储Student类的对象,readStudent方法是通过遍历列表找到目标,writeStudent是直接通过add添加新的对象

    StudentDaoArrayImpl类也实现了StudentDao接口,不过是默认存储Student对象数组大小为80,与StudenDaoListImpl类有点不同的是读入信息是判断数组元素是否为空,才存入数组,其他大同小异

    Test类就是含有入口函数,测试用的

    4.2 StudenDaoListImpl与StudentDaoArrayImpl有何区别?

    答:顾名思义,前者是用List列表来存储对象,后者是用数组来存储对象,只是实现方式不一样,结果是一样的
    
    

    5. 什么是面向接口编程?面向接口编程的好处是什么?

    结合题目3与4中的Test.java的代码讨论分析。不要百度原封不动照搬!

    答;面向接口编程就是在面向对象的前提下,由于各个对象之间有可能存在协作关系,所以可以采用接口来实现交互,题目3中的Comparable和Comparator接口同样都是用来比较的,但是后者是可以比较一个类生成的两个对象之间属性的比较,同为比较,但是实现的方式不同,题目4的StudenDaoListImpl与StudentDaoArrayImpl同样实现的结果是一样的,面向接口编程,就是在实现的方式不清楚的情况下,定义的一个接口,让其他类实现这个接口,再根据情况来写具体的内容,有了接口可变性比较强,能够解决需求变化。在书上202页第一段就有提到:写程序要有弹性,要有可维护性。
    
    

    6. 结对编程:面向对象设计(大作业2-非常重要)

    6.1内容:使用Java代码完成上周做的面向对象设计大作业,需要有初步界面。实现的功能尽量简单,少而精,只包含必要的功能,不要追求高大全。
    写出:类图(尽量精简,不用太多子类,两个即可)、系统常用功能描述、关键代码与界面
    形式: 两人依托码云合作完成。请在这里贴出你们的学号、姓名与任务分工。
    注意: 再过几次课要讲Java图形界面编程,到时候要将该系统升级为图形界面。系统的业务逻辑部分应该变化不大,变化大的是输入与输出部分。所以编码的时候,输入(Scanner)与输出(System.out)的代码,请不要将其与某个业务处理函数绑死。
    选做加分: 给出两人在码云上同一项目的提交记录截图,额外加分。注:两个人在码云上新建一个项目。
    参考资料:
    结对编程参考资料
    可以使用Processon画图

    参考书面作业第3、4题的做法,使输入输出抽象化
    类图:

    学生L 学生null 项目地址
    https://q.cnblogs.com/u/lyq063/ https://git.oschina.net/jmulyq/ShoppingCart.git

    6.2 常用功能描述框架图

    6.3 关键代码

    输入输出接口:
    public interface shop {
    	//输入输出方式抽象化
    	public void print(String text);
        public abstract void println(String text);
        public abstract int nextInt();
        public abstract Double nextDouble();
        public abstract String next();
    }
    
    菜单类:
    public class Menu implements shop{
    	
    
    	private Scanner scan = new Scanner(System.in);
    	int k=0;
    	
    	public void showmenu(Cart cart){
    		println("**********欢迎光临**********");
    		println("        1.浏览商品");
    		println("        2.查找商品");
    		println("        3.加入购物车");
    		println("        4.我的购物车");
    		println("        0.退出");
    		println("请选择:");
    		int choice=nextInt();
            Iterm[] booklist=Iterm.allproduct();
    		switch(choice){
    		    case 1:{
    		    	for(Iterm i:booklist){
    		    		println(i.toString2());
    		    	}
    		    	break;
    		    }
    			case 2:{
    				boolean flag=false;
    				String prudoct=next();
    				for(k=0;k<booklist.length;k++){
    					if(booklist[k].getName().equals(prudoct)){
    						println(booklist[k].toString2());
    						flag=true;
    						break;
    					}	
    				}
    				if(!flag){
    					println("您所查找的商品未找到,请重新输入");
    				    k=-1;
    				}else 
    					break;
    				
    			}
    			case 3:{
    				
    				if(k>=0){
    					println("请输入数量:");
    					int num=nextInt();
    					booklist[k].setNumber(num);
    					cart.addproduct(booklist[k]);
    					cart.cartmenu(booklist[k]);
    				}
    				else{
    					println("错误操作,还未选择商品!");
    				}
    				break;
    			}
    			case 4:{
    				cart.cartmenu(booklist[k]);
                                    break;
    			}
    			case 0:return;
    		}
    		showmenu(cart);
    	}
    
    	@Override
    	public void print(String text) {
    		
    		System.out.print(text);
    		
    	}
    	
    	@Override
    	public void println(String text) {
    		System.out.println(text);
    		
    	}
    
    	@Override
    	public int nextInt() {
    		return scan.nextInt();
    	}
    
    	@Override
    	public Double nextDouble() {
    		return scan.nextDouble();
    	}
    
    	@Override
    	public String next() {
    		return scan.next();
    	}
    }
    
    商品类:
    public class Iterm{
    	private String name;
    	private double price;
    	public int number;
            ...一堆setter、getter、toString方法(含有两种格式,一种是不需要输出数量的)
    
    }
    
    购物车类:
    public class Cart implements shop {
        ArrayList<Iterm> iterm = new ArrayList<Iterm>();
    	private Scanner scan = new Scanner(System.in);
    	public  void cartmenu(Iterm i) {
    		println("1.删除商品");
    		println("2.结算全部商品");
    		println("3.清空购物车");
    		println("4.显示购物车中所有商品");
    		println("0.返回菜单");
    		println("请选择:");
    		int c = nextInt();
    		switch (c) {
    		case 1: {
    			deleteproduct(i);
    			break;
    		}
    		case 2: {
    			System.out.println(allmoney());
    			break;
    		}
    		case 3: {
    			iterm.clear();
    			break;
    		}
    		case 4:{
    			for(Iterm i1:iterm){
    	    		System.out.println(i1.toString());
                            break;
    	    	}
    		}
    		case 0: {
    			return;
    		}
    		}
    	}
    
    	public void addproduct(Iterm i) {
    		if(iterm.contains(i)){
    			iterm.get(iterm.indexOf(i)).number+=i.number;
    		}
    		else iterm.add(i);
    	}
    
    	public void deleteproduct(Iterm i) {
    		iterm.remove(i);
    	}
    
    	public double allmoney() {
    		double sum = 0;
    		for (Iterm i : iterm) {
    			sum += i.getPrice() * i.getNumber();
    		}
    		return sum;
    	}
    
    	public  void showcartproduct() {
    		for (Iterm i : iterm) {
    			println(i.toString());
    		}
    	}
    
    	...还有复写接口输入输出的方法
    }
    
    测试类:
    public class PersonTest {
    
    	public static void main(String[] args) {
    		Menu menu=new Menu();
                    Cart cart=new Cart();
    		menu.showmenu();
    
    	}
    
    }
    
    

    6.4 运行界面
    主菜单及所有商品:

    在书列表中找不到的情况:

    加入购物车并结算:

    删除当前商品:

    3. 码云上代码提交记录及PTA实验总结

    题目集:jmu-Java-04-面向对象2-进阶-多态接口内部类

    3.1. 码云代码提交记录

    • 在码云的项目中,依次选择“统计-Commits历史-设置时间段”, 然后搜索并截图

    3.2. PTA实验

    • 继续完成前面未完成的实验面向对象1-基础-封装继承
    • 函数(选做:4-1)、编程(5-1, 5-2)
    • 一定要有实验总结

    实验总结:

    • 4-1
      待续

    • 5-1
      这题编写了PersonSortable类,实现了Comparable接口,根据题意来重写compareTo和toString方法
      比较简单,注意Comparable,“< >”内要写比较的对象

    • 5-2
      这题用的是比较器,需要import java.util.Comparator;,应为这题要求是分别对姓名和年龄排序,所以可以重写compare方法,传入两个对象进行属性之间的比较
      注意最后排序时候要Arrays.sort(p,new一个对象)才行,根据要求来创建对象,实现不同的排序方法

  • 相关阅读:
    工作总结系列---【端口被占用,如何取消端口进程】
    封装工具系列---【封装H5页面管理机构和证件类型下拉框数据处理的方法】
    工作总结系列---【vue页面实现导出表格效果】
    vscode---【内网开发下,离线安装vscode插件vsix文件】
    工作总结系列---【IDE深色背景下,鼠标移动也变成黑色,看不清怎么解决???】
    node系列---【为什么要设置镜像源?怎么配置?】
    git系列---【如何在本地修改别人的代码图解】
    git系列---【git如何回退到上一个版本??】
    封装工具系列---【补零操作】
    封装的各类工具系列---【时间格式化为YYYY-MM-DD格式 】
  • 原文地址:https://www.cnblogs.com/lyq063/p/6603408.html
Copyright © 2020-2023  润新知