• Java 第四周总结


    1. 本周学习总结

    2. 书面作业

    注释的应用:
    (1)源文件注释采用 /** …… */,在每个源文件的头部要有必要的注释信息,包括:文件名;文件编号;版本号;作者;创建时间;文件描述包括本文件历史修改记录等。中文注释模版:

    (2)类(模块)注释采用 /** …… */,在每个类(模块)的头部要有必要的注释信息,包括:工程名;类(模块)编号;命名空间;类可以运行的JDK版本;版本号;作者;创建时间;类(模块)功能描述(如功能、主要算法、内部各部分之间的关系、该类与其类的关系等,必要时还要有一些如特别的软硬件要求等说明);主要函数或过程清单及本类(模块)历史修改记录等。

    使用类的注释与方法的注释为前面编写的类与方法进行注释,并在Eclipse中查看。(截图) ![](http://images2015.cnblogs.com/blog/1109779/201703/1109779-20170318125736823-1420589250.jpg)

    2.1 将在网上商城购物或者在班级博客进行学习这一过程,描述成一个故事。(不得少于50字,参考QQ群中PPT的范例)

    想描述一下关于手机听歌的一个过程,因为科研立项就是做的这个类似的,正好理一下思路。
    • (1)首先搜索想听的歌曲,因为有同名歌曲,所以还要再看看歌手名字
    • (2)然后选择歌曲到播放列表,喜欢这首歌可以把他放到“喜爱”分区里
    • (3)听歌过程中随时可以暂停播放,因为有播放列表,所以可以上一曲下一曲切换。看看进度条好像快听完了,想再听一遍。点击单曲循环。
    • (4)想看看刚才的歌词,把进度条拉回之前的位置

    2.2 通过这个故事我们能发现谁在用这个系统,系统中包含的类及其属性方法,类与类之间的关系。尝试找到这些类与属性,并使用思维导图描述类、属性、方法及类与类之间的关系。

    2.3 尝试使用Java代码实现故事中描述的这一过程(不必很完善),将来要在这个基础上逐渐完善、扩展成一个完整的面向对象的系统。(可选:加分)

    3.分析ManagerTest.zip中的代码,回答几个问题:

    3.1 在本例中哪里体现了使用继承实现代码复用?回答时要具体到哪个方法、哪个属性。

    class Manager extends Employee
    {
       /**
        * @param n the employee's name
        * @param s the salary
        * @param year the hire year
        * @param month the hire month
        * @param day the hire day
        */
       public Manager(String n, double s, int year, int month, int day)
       {
          super(n, s, year, month, day);
          bonus = 0;
       }
    
    • 这一部分使用了继承。Manager类继承了Employee类。属性包括姓名,基础薪水,年月日。继承的方法是计算工作日方法。

    3.2 Employee类及其子类Manager都有getSalary方法,那怎么区分这两个方法呢?

    • 当子类和父类都有相同的字段,子类的字段就会代替或者隐藏父类的字段,子类方法中访问的是子类中的字段,父类方法中访问的是父类的字段。
    • 如果子类方法想访问父类中的同名字段,可以通过super关键字访问。
    • 但是:A x=new B();调用方法的时候,因为实际类型是B,所以永远调用子类B的方法。

    3.3 文件第26行e.getSalary(),到底是调用Manager类的getSalary方法还是Employee类的getSalary方法。

    • for (Employee e : staff) e是Employee类的,因为是父类,所以调用的是Employee的getSalary方法
    • staff[0]=boss;e.getSalary()调用的是Manager类的方法。同一操作,e作用于不同的对象,产生不同的结果,多态的定义。
    • 动态绑定:程序运行的时候,我们程序的行为,特别是内存行为,可以按照需求改变,这种就叫动态绑定。这种改变对应到代码上就是不同的对象行为,不同的对象,对应的是不同代码,不同的代码对应又是不同的内存操作,不同的代码会有不同的名字。

    3.4 Manager类的构造函数使用super调用父类的构造函数实现了代码复用,你觉得这样的有什么好处?为什么不把父类构造函数中的相关代码复制粘贴到Manager的构造函数中,这样看起来不是更直观吗?

    • 首先是简洁。代码太过繁杂,即使更直观,也会使代码整体冗余。重复代码太多,没有什么意义。反而是清晰简介的代码,让人一目了然,且不会因为长度而混乱。
    • 同时也方便子类重写方法中调用父类同名方法

    4.Object类

    4.1 编写一个Fruit类及属性String name,如没有extends自任何类。使用System.out.println(new Fruit());是调用Fruit的什么方法呢?该方法的代码是从哪来的?尝试分析这些代码实现了什么功能?

    • 输出Fruit的地址信息,如图

    • 因为Fruit类是自定义类,什么方法都没有。也没有定义构造函数,因为没有显式继承,所以默认继承Object类,系统默认一个Object类的无参构造函数。这个构造函数只能给对象开辟地址空间,不会完成初始化。由于Object的toString的返回值 return getClass().getName() + "@" + Integer.toHexString(hashCode());所以代码运行结果是一个地址。

    4.2 如果为Fruit类添加了toString()方法,那么使用System.out.println(new Fruit());调用了新增的toString方法。那么其父类中的toString方法的代码就没有了吗?如果同时想要复用其父类的toString方法,要怎么操作?(使用代码演示)

    • 添加了toString()方法之后,代码运行结果```Fruit [name=null]````
    • 父类中的toString还是存在的,只是因为我们重写toString,父类的就被隐藏了。如果同时想要复用父类的,可以用super。
    class Fruit11{
    	private String name;
    
    	@Override
    public String toString() {
    return "Fruit [name=" + name + "]"+super.toString();
    
    }
    }
    

    4.3 Fruit类还继承了Object类的equals方法。尝试分析其功能?自己编写一个equals方法覆盖父类的相应方法,功能为当两个Fruit对象name相同时(忽略大小写),那么返回true。(使用代码证明你自己覆盖的eqauls方法是正确的)

    • equals方法源代码
    public boolean equals(Object anObject) {
            if (this == anObject) {
                return true;
            }
            if (anObject instanceof String) {
                String anotherString = (String)anObject;
                int n = value.length;
                if (n == anotherString.value.length) {
                    char v1[] = value;
                    char v2[] = anotherString.value;
                    int i = 0;
                    while (n-- != 0) {
                        if (v1[i] != v2[i])
                            return false;
                        i++;
                    }
                    return true;
                }
            }
            return false;
        }
    
    • 如果两个相等地址,返回true(比较的是对象的地址,所以在实际使用中,基本没什么太大用处。尤其是在对两个对象的比较时,基本都要重写equals)
    • instanceof(它的作用是判断其左边对象是否为其右边类的实例),如果传入的是字符串,则一个个字符进行比较判断,相同返回true。
    public class Test{
        		public static void main(String[] arge){
        		
        		System.out.println(new Fruit(""));
        		Scanner in=new Scanner(System.in);
        		Fruit str=new Fruit(in.next());
        		Fruit str1=new Fruit(in.next());
        		if(str1.equals(str)){
        			System.out.println("相等");
        		}
        		else System.out.println("不相等");
        		
        		}	
        		}
        
        	class Fruit{
        	private String name;
        	
        	@Override
        	public String toString() {
        		return "Fruit [name=" + name + "]";
        	}
        	public String getName() {
        		return name;
        	}
        
        	public void setName(String name) {
        		 this.name=name;
        	}
        
        	public Fruit(String name){
        		 this.name=name;
        	}
        
        
        	@Override
        	public int hashCode() {//重写equals方法的时候,一定要重写hashCode方法
        		final int prime = 31;
        		int result = 1;
        		result = prime * result + ((name == null) ? 0 : name.hashCode());
        		return result;
        	}
        	
        	
        	@Override
        	public boolean equals(Object obj){		
        		if(this==obj)
        			return true;
        		if(obj==null)
        			return false;
        		if(getClass()!=((Fruit) obj).getClass())
        			return false;
        		Fruit other=(Fruit) obj;
        		if(name==null){
        			if(other.name!=null)
        				return false;
        		}
        		else if(!name.equalsIgnoreCase(other.name))//这句一直没想到怎么办,虽然找到了equalsIgnoreCase的方法,但是之前一直不知道该在哪里用,感谢大佬
        			return false;
        		return true;
        	}	
        }
    
    

    4.4 在4.3的基础上使用ArrayList<Fruit> fruitList存储多个fruit,要求如果fruitList中已有的fruit就不再添加,没有的就添加进去。请编写相关测试代码。并分析ArrayList的contatins方法是如何实现其功能的?

    • 关于这个,首先不允许重复。从查到的资料上来看,List是一个有序的,允许重复的列表。
    • HashSet比较是根据HashCode的值来比较的,HashCode值是根据内存地址换算出来的。因为我们在重写equals的时候也对hashCode进行了重写,所以对于相同的对象,就不插入了。
    • 综上,用HashSet可能更好点......但是既然题目要求,使用ArrayList,fruitList.contains())也是可以的,用来查找某个对象在不在列表之中。
    • 代码实现
    public static void main(String[] arge){
    		
    		System.out.println(new Fruit(""));
    		Scanner in=new Scanner(System.in);
    		Fruit str=new Fruit("");
    		Fruit str1=new Fruit(in.next());
    		if(str1.equals(str)){
    			System.out.println("相等");
    		}
    		else System.out.println("不相等");
    		ArrayList<Fruit> fruitList=new ArrayList<Fruit>();
    		//HashSet<Fruit> fruitList1=new HashSet<Fruit>();	
    		for(int i=0;i<5;i++){//因为题目其他要求,为了方便检测,就设置成了只读5个
    				Fruit a=new Fruit(in.next());
    				//System.out.println(a.hashCode());
    				if(!fruitList.contains(a))
    					fruitList.add(a);	
    		}
    		System.out.println(fruitList);//测试
    		//System.out.println(fruitList1);
    	}	
    }
    
    • 只粘贴了main函数部分,Fruit类跟前面相同。注释地方是使用HashSet的情况,实测也可以使用
    • 运行结果如下图

    5.代码阅读:PersonTest.java(abstract、多态)

    5.1 画出类的继承关系

    5.2 读懂main函数,将自己推测的出代码运行结果与真正运行结果进行比较。尝试分析原因

    • main里面对年龄进行排序,之后用了一个增强for循环顺序输出。
    • 输出的时候,toString()一起输出,方便看出继承的关系。因为调用的是super,所以都会输出自己父类的toString()。但是只会到上一级的父类,而不会调用到父类的父类。

    5.3 子类中里面使用了super构造函数,作用是什么?如果将子类中的super构造函数去掉,行不行?

    • 子类使用super构造函数,是为了调用父类的构造函数,对变量初始化。如果去掉子类的super构造函数,那子类的构造函数没法完成初始化。
    • 报错信息:隐式的super构造函数person()是未定义的。必须显式调用另一构造函数

    5.4 PersonTest.java中的代码哪里体现了多态?你觉得多态有什么好处?多态和继承有什么关系吗?

    • 继承是多态的基础,继承是子类使用父类的方法,而多态则是父类使用子类的方法
    • 继承就是一种由已有的类创建新类的机制,是指在已有类的基础上扩展功能。继承中分为子类和父类,类可以有两种重要的成员:成员变量和方法。子类的成员中有一部分是子类自己声明定义的,另一部分是从它的父类继承的。
    • 多态的好处:运行时,根据实际创建的对象类型动态决定使用哪个方法。
    	for (Person person : peoples) {//person
    			System.out.println(person);
    
    • person 虽然是定义为Person类,但是这只是代码中所有类的父类,给persond的类型选择提供一个接口但是不代表person一定是Person类。他会在运行时,根据实际创建的对象类型,动态决定是Student,Manager,Programmer,还是Employee。

    3. 码云代码提交记录

    4. 实验总结

    (1)boolean equals(Object anObject) 比较此字符串与指定的对象;
    (2) boolean equalsIgnoreCase(String anotherString) 将此 String 与另一个 String 进行比较,不考虑大小写,是String自己定义的方法;
    (3)==这个是用来比较两个对象是否引用同一个对象
    (4)CharSequence就是字符序列,String, StringBuilder和StringBuffer本质上都是通过字符数组实现的
    (5)ArrayList.Contains方法可以用来查找某个对象在不在列表之中,不在!
    (6)ArrayList.Add方法用于添加一个元素到当前列表的末尾
    (7) 关于ArrayList的一些使用
    (8)当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。 如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了, 就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。 所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。
    (9)抽象类前使用abstract关键字修饰,则该类为抽象类。抽象类不能实例化。
  • 相关阅读:
    自己实现迭代器
    Python基础教程(入门教程),30分钟玩转Python编程!!
    centos7安装python 与卸载python
    docker 批量导入本地 tar 镜像包的 sao 操作
    无线路由器信道怎么设置 无线路由器信道选择哪个好
    关于打包压缩几种格式(gzip,bzip2,xz)的试验对比
    linux 长期运行程序的 四种方法
    win10快捷键大全 win10常用快捷键
    linux bg和fg命令
    Apache htpasswd命令用法详解
  • 原文地址:https://www.cnblogs.com/ycll/p/6561359.html
Copyright © 2020-2023  润新知