201521123038 《Java程序设计》 第四周学习总结

201521123038 《Java程序设计》 第四周学习总结


1. 本周学习总结

1.1 尝试使用思维导图总结有关继承的知识点。

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

1.通过 instanceof 可以判断父类引用所引用的对象实例的实际类型
2.abstract用来修饰抽象方法

2. 书面作业

1.注释的应用

使用类的注释与方法的注释为前面编写的类与方法进行注释,并在Eclipse中查看。(截图)

类注释:

方法注释:

2.面向对象设计(大作业1,非常重要)

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

看烦了电子书突然想买纸质书的我今天心血来潮打开了亚马逊,在首页的搜索框中输入了“三体”,回车,跳转至包含“三体”关键词的商品页面,点击商品查看详情,选择数量点击“加入购物车”。在选择完毕后进入购物车,进入结算中心完成这次购物。

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

3.ManagerTest.zip代码分析

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

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

   public Employee(String n, double s, int year, int month, int day)

   {

      name = n;

      salary = s;

      GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);

      hireDay = calendar.getTime();

   }

   public Manager(String n, double s, int year, int month, int day)

   {

      super(n, s, year, month, day);//步骤1

      bonus = 0;

   }

方法②中的Manager类继承了方法①中的Employee类,步骤1用super语句调用了父类的方法①。在Manager类中并没有定义name,salary,hireday变量,是因为Manager是Employee的子类,已经复用了和这些变量相关的代码,不需要重新定义。

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

如果想在子类中调用父类的方法,可以使用super.getSalary()来实现。

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

      for (Employee e : staff)

         System.out.println("name=" + e.getName() + ",salary=" + e.getSalary());

源代码中的staff有两个属性,分别为boss和Employee。所以调用的具体方法由当前的staff类型决定。

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

使用super调用父类的构造函数可以事代码简洁化,可以方便看清子类从父类继承的属性和子类特有的属性。

如果把父类构造函数中的相关代码复制粘贴到Manager的构造函数中,首先碍于美观,其次占用了多余的空间,而且没有意义。

DRY原则(Don't repeat yourself)
字面意思来看:"不要重复自己"。强调的意思就是在进行编程时相同的代码不要重复写,最好只写一次,然后可以在其他地方直接引用。如此一来,可以提高代码重用率,缩减代码量,同时也有助于提高代码的可读性和可维护性。当需要做出更改时,只需要更改一个地方即可。

4.Object类

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

运行结果:Fruit@15db9742

因为在Fruit类中没有对toString进行重写,所以在输出的时候调用的是系统自带的Object.toString方法

    public String toString() {

        return getClass().getName() + "@" + Integer.toHexString(hashCode());

    }

由代码可以看出输出格式是:类名+"@"+该对象的哈希码的无符号十六进制

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

在Fruit中添加toString方法:

class Fruit

{

	private String name;

	@Override

	public String toString() {

		return "Fruit [name=" + name + "]";

	}
	
}

子类重写toString代码,父类Object中的toString依然存在,但是在执行System.out.println(new Fruit())时调用的是子类Fruit中的toString方法。

运行结果:Fruit [name=null]

如果想要复用父类中的toString,可以用super实现:

class Fruit

{

	private String name;

	@Override

	public String toString() {

		return super.toString();

	}

	
}

输出结果:Fruit@15db9742

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

Object类的equals方法:

    public boolean equals(Object obj) {

        return (this == obj);

    }

Object类的equals方法通过对比当前引用是否相同来返回boolean值,相同返回true,不同返回false。

Fruit类中覆盖equals:

    public boolean equals(Fruit fruit) {

    	Fruit otherfruit=(Fruit) fruit;
    	if(name==null)

    	{

    		if(otherfruit!=null)

    			return false;

    	}
    	if(!name.equalsIgnoreCase(otherfruit.name)) return false;

		return true;

    }

main函数中检测及输出结果:

但是这个代码不是完善的,在下一题进行解释。

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

测试代码:

	public static void main(String[] args) {

		Scanner input=new Scanner(System.in);
		
		ArrayList<Fruit> fruitList=new ArrayList<Fruit>();

	    while (true) {

			String name=input.next();

			Fruit fruit=new Fruit(name);

			if(name.equals("end")) break;

			if(!fruitList.contains(fruit))

			{	

				fruitList.add(fruit);

			}

		}

		    System.out.println(fruitList);
	
	}

但是在测试过程中出现了问题,无论输入的fruit是什么,都会被添加到fruitList中,也就是说并没有调用重写的equals类型。查看contains方法的源代码:

contains方法中调用了查找方法indexOf。indexOf中调用的是父类的equals方法,也就是说明在4.3中的equals方法没有覆盖父类的方法。在写的equals方法上添加@Override,会提示错误:The method equals(Fruit) of type Fruit must override or implement a supertype method。所以要对4.3的代码进行重写:

    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))

            return false;

        return true;

    }   

运行结果:

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

5.1 画出类的继承关系

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

推测:

这个代码将peoples按年龄的由小到大将信息输出。

运行结果:

Manager [bonus=12000.3, toString()=Employee [salary=90000.1, toString()=Person [name=Clark, adress=GE, phonenumber=111, email=111@mail.com, age=10, gender=mail]]]

Student [status=1, toString()=Person [name=wang, adress=110, phonenumber=15959, email=15959@163.com, age=18, gender=male]]

Employee [salary=1000.0, toString()=Person [name=zhang, adress=136, phonenumber=1360, email=1360@mail.com, age=21, gender=female]]

Programmer [allowance=50000.0, toString()=Employee [salary=100000.0, toString()=Person [name=Gates, adress=usa, phonenumber=911, email=911@com, age=59, gender=male]]]

分析:

通过分析toString函数,发现所有的子类在输出自己特有的变量值外都包含了super.toString(),执行父类的toString方法。因为Manager和Programer都是Employee的子类,而Employee是Person的子类,所以Manager和Programer的toString方法最终会执行Person的toString方法。

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

作用是调用父类的构造函数。

不能去掉。因为如果去掉了,会提示错误:Implicit super constructor Person() is undefined. Must explicitly invoke another constructor。大致意思是父类的无参构造函数是未定义的。而且如果去掉了,对应的信息无法被赋予相应的对象,程序的用途就不明显。

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

在执行下列代码的时候能体现多态:

		for (Person person : peoples) {

			System.out.println(person);

		}

而peoples中包含了四个类型:Employee,Student,Programmer,Manager。在输出的时候,系统会通过判断当前对象的类型来执行相应对象的toString方法。可以看出多态可以使代码更加简洁灵活,可以使方法间的关系更明了。

由上面的分析来看,多态可以体现在父对象根据当前赋值给它的子对象的特性执行相应子对象的方法,这和继承操作是分不开的。

*(附)继承与多态的区别

3. 码云代码提交记录

4. PTA实验

1.当有涉及到动态数组的时候要善用ArrayList,自带的方法会节省很多代码空间。

2.使用DecimalFormat df = new DecimalFormat("#.##")保留两位小数。

3.编写equals覆盖函数的时候要考虑一下Null的情况
原文地址:https://www.cnblogs.com/sakurai3104/p/6574320.html