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

20145333 《Java程序设计》第4周学习总结

教材学习内容总结

本周学习了第六及第七章的内容,主要讲了关于代码继承和接口语法方面的知识。

第六章

继承与多态

  • 面向对象中,子类继承父类避免重复的行为定义,不过并不是为了避免重复定义行为就使用继承。继承基本上就是避免多个类间重复定义共同行为。

当两个代码之间有许多相同的部分时,我们就可以把这样的代码提取出来提升为父类。(以158页及159页代码为例,提升为父类代码如下)

 public class Role{

     private String name;
     private int level;
     private int blood;

     public int getBlood(){
         return blood;
     }

     public void setBlood(int blood){
         this.blood = blood;
     }

     public int getLevel(){
         return level;       
     }

     public void setLevel(int level){
         this.level = level;
     }

     public String getName(){
         return name;
     }

     public void setName(String name){
         this.name = name;
     }

 }

这是将SwordsMan与Magician中重复的程序代码复制过来。

SwordsMan可以继承Role的行为,在扩充Role原本没有的fight()行为。

public class SwordsMan extends Role{
    public void fight(){
        System.out.println("挥剑攻击"); 
    }
}

从以下代码可以看出确实有所继承:

public class PRG{
public static void main (String[] args) {
    demoSwordsMan();
    demoMagician();
}

static void demoSwordsMan() {
    SwordsMan swordsMan = new SwordsMan();
    SwordsMan.setName("Justin");
    SwordsMan.setLevel(1);
    SwordsMan.setBlood(200);
    System.out.printf("剑士:(%s.%d,%d)%n",swordsMan.getName(),
            swordsMan.getLevel(),swordsMan.getBlood());
}

static void demoMagician() {
    Magician magician = new Magician();
    magician.setName("Moinca");
    magician.setLevel(1);
    magician.setBlood(100);
    System.out.printf("魔法师:(%s,%d,%d)%n",magician.getName(),
            magician.getLevel(),magician.getBlood());
    
}
}
  • 在Java中,子类只能继承一个父类,继承除了可避免类间重复的行为定义外,还有子类与父类之间会有is-a的关系。

  • 多态就是通过单一接口操作多种类型的对象。

以167页为例,在SwordsMan继承Role之后,再对fight()的行为进行定义:

public class SwordsMan extends Role{
public void fight()
{
    System.out.println("挥剑攻击");
}
}

在继承父类之后,定义与父类中相同的方法部署,但执行内容不同,这称为重新定义(Overide)。由于Role现在定义了fight()方法,所以编译程序不会找不到Role的fight(),因此可以如下撰写:

public class RPG{
public static void main(String[] args) {
    SwordsMan swordsMan = new SwordsMan();
    swordsMan.setName("Justin");
    swordsMan.setLevel(1);
    swordsMan.setBlood(200);
    
    Magician magician = new Magician();
    magician.setName("Monica");
    magician.setLevel(1);
    magician.setBlood(100);
    
    drawFight(swordsMan);
    drawFight(magician);
    
}

static void drawFight(Role role) {
    System.out.print(role.getName());
    role.fight();
}
}

在重新定义父类中某个方法时,子类必须撰写与父类方法中相同的签署。

  • 如果某方法区块中真的没有任何代码程序操作,可以使用abstract标示该方法为抽象方法,该方法不用撰写{}区块,直接“;”结束即可。

  • protected成员

若只想让子类可以直接存取name、level、public,可以定义其为protect。

 public abstract class Role5
 {
  protected String name;
  protected int level;
  protected int blood;
  ...
 }
  • 重新定义的细节

如果想取得父类中的方法定义,可以在调用方法前,加上super关键字,但不能定义为private(因为这就限定只能在类内使用)。重新定义方法需要注意,对于父类中的方法权限,只能扩大但不能缩小。若原来成员public,子类中重新定义时不可为private或protected。

  • final可以指定变量值不再改变,在class前加上final,意思是这个类是最后一个类,不会再有子类,即不能被继承。限定方法为final表示最后一次定义该方法,子类不能重新定义。

  • 在Java中子类只能继承一个父类,没有使用extends关键字指定继承的类时,继承java.lang.Object。

因为数组长度有限,使用数组来收集对象不是那么方便,以下定义ArrayList类,可以不限长度地收集对象:

import java.util.Arrays;

public class ArrayList {
private Object[] list;
private int next;

public ArrayList(int capacity) {
    list=new Object[capacity];
}

public ArrayList() {
    this(16);
}

public void add(Object o) {
    if(next==list.length) {
        list=Arrays.copyOf(list, list.length*2);
    }
    list[next++]=o;
}
public Object get(int index) {
    return list[index];
}

public int size() {
    return next;
}
}
  • 垃圾收集

创建对象会占据内存,如果程序执行流程中已无法再使用某个对象,该对象就只是耗内存的垃圾。JVM有垃圾收集机制,收集到的垃圾对象所占据的内存空间,会被垃圾收集器释放。在执行流程中,无法通过变量参考的对象,就是垃圾对象。

接口与多态

  • 接口定义行为

在java中可以使用interface关键字。

public interface Swimmer
{
public abstract void swim();

}

类要操作接口,必须使用implements关键字,对接口中定义的方法有两种操作方式,一是操作接口中定义的方法,二是再度将该方法表示为abstract。操作接口表示“拥有行为”,不再是“是一种”的关系。

public class Human implements Swimmer{
private String name;
public Human(String name){
this.name =name;
}
public String getName(){
return name;
}
@Override
public void swim(){
System.out.printf("人类 %s 游泳 %n",name);
}
}

Human、Fish、Submarine也有Swimmer行为,以Submarine为例。

public class Submarine implements Swimmer{
 private String name;
 public Submarine(String name)
 {
    this.name=name;
 }
 public String getName()
 {
  return name;
 }


@Override
public void swim();
{
System.out.printf("潜水艇 %s 潜行%n",name);
}
}
  • 行为的多态

Anemonsfish、Shark、Human、Submarine,都拥有Swimmer的行为,都操作了Swimmer接口。

public class Ocean{
public static void main(String[] args)
{
    doSwim(new Anemonsfish("尼莫"));
    doSwim(new Shark("兰尼"));
    doSwim(new Human("贾斯汀"));
    doSwim(new Submarine("黄色一号"));
}

static void doSwim(Swimmer swimmer)
{
    swimmer.swim();
}
}
  • 接口语法细节

在Java中,用interface来定义抽象的行为与外观,方法可声明为public abstract,接口中的方法没有操作时,一定得是公开且抽象,也可以省略public abstract,编译程序会自动补上。

在interface中,可以定义常数。

public interface Action
{
public static final int STOP=0;
public static final int RIGHT=1;
public static final int LEFT=2;
public static final int UP=3;
public static final int DOWN=4;
}
  • 匿名内部类

在撰写java程序时,会有临时继承某个类或操作某个接口并建立实例的需求,由于这类子类或接口操作类只使用一次,不需要为这些类定义名称,这时可以使用匿名内部类来解决这个需求。

教材学习中的问题和解决过程

在书上193页的课后习题中,要求重新定义ArrayList的equals()方法,比较收集的对象个数和比较各索引的对象实质上是否相等,这道题思考了半天也没有思路,反复看了181页和182页的概念和代码也没有解决,希望老师能给点提示和思路,然后我再研究研究。

本周代码托管截图

其他(感悟、思考等,可选)

学习Java已经一个月了,随着每周的学习,我感觉每周要学习知识内容都上一周的更加难理解,更加深奥。这周的学习给我的感觉就是代码好多好多,书上的很多专业术语都不是很理解,就算反复看了书也还是模模糊糊,但是这也让我深切地体会到了对于学习Java动手练习的重要性,很多在教材上看不明白的东西,在把书上的代码敲到电脑上运行以后,感觉一些不懂的地方就理解的多了。在不断地深入学习以后,我觉得每次仅仅只是把书上的代码敲到电脑上练习已经不能很好地去掌握这些知识了,不懂的地方还是有很多,以后我会经常写博客把自己不会的东西问出来,寻求同学和老师的帮助。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 3500行 15篇 400小时
第一周 100/100 2/2 20/20
第二周 150/250 1/3 18/38
第三周 100/350 1/4 22/60
第四周 300/650 1/5 30/90

posted on 2016-03-27 21:44  20145333茹翔  阅读(132)  评论(2编辑  收藏  举报

导航