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

教材学习内容总结

第六章

6.1 何谓继承
继承基本上就是避免多个类间重复定义共同行为

package cc.openhome;
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;
    }
}
package cc.openhome;
public class SwordsMan extends Role {
    public void fight(){
        System.out.println("挥剑攻击");
    }
}

在这里看到了新的关键字extends,这表示SwordsMan会扩充Role的行为,也就是继承Role的行为,再扩充Role原本没有的fight()行为。
private成员会被继承,只不过子类无法直接存取,必须通过父类提供的方法来存取。
在Java中,子类只能继承一个父类,继承除了可避免类间重复的行为定义外,还有个重要的关系,那就是子类与父类间会有is-a的关系,中文称为“是一种”的关系。
编译程序会检查父子类间的“是一种”关系,如果你不想要编译程序啰嗦,可以叫它住嘴:

Role role1 = new SwordsMan();
SwordsMan swordsMan = (SwordsMan) role1;

使用是一种原则,就可以判断何时编译成功,何时编译失败,以及将扮演看做叫编译程序住嘴语法,并留意参考的对象实际类型,就可以判断何时扮演成功,何时会抛出ClassCastException.
什么叫多态?以抽象讲法解释,就是使用单一接口操作多种类型的对象。
在继承父类之后,定义与父类中相同的方法部署,但执行内容不同,这称为重新定义。
疏忽打错字的情况:

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

在JDK5之后支持标注,其中一个内建的标准标注就是@Override。如果在子类中某个方法前标注@Override,表示要求编译程序检查,该方法是不是真的重新定义了父类中某个方法,如果不是的话,就会引发编译错误。如果要重新定义某方法,加上@Override,就不用担心打错字的问题了。
如果某方法区块中真的没有任何程序代码操作,可以使用abstract标示该方法为抽象方法,该方法不用撰写{}区块,直接“;”结束即可。

package cc.openhome;
public abstract class Role{
    ...略
    public abstract void fight();
}

类中若有方法没有操作,并且标示为abstract,表示这个类定义不完整,定义不完整的类就不能用来生成实例。Java中规定内含抽象方法的类,一定要在class前标示abstract。如果尝试用抽象类创建实例,就会引发编译错误。
子类如果继承抽象类,对于抽象方法有两种做法,一种做法是继续标示该方法为abstract;另一种做法就是操作抽象方法。如果两种方法都没有实施,就会引发编译错误。
6.2继承语法细节

package cc.openhome;
public abstract class Role{
    protected String name;
    protected int level;
}

被声明为protected的成员,相同包中的类可以直接存取,不同包中的类可以在继承后的子类直接存取。
3个权限关键字:public、protected与private。虽然只有3个权限关键字,但实际上有4个权限范围,因为没有定义权限关键字,默认就是包范围。
依权限小至大来区分,就是private、无关键字、protected与public.
在Java中,如果想取得父类中的方法定义,可以在调用方法前,加上super关键字:

package cc.openhome;
public class SwordsMan extends Role{
    ...
    @Override
    public String toString(){
        return "剑士"+super.toString();
    }
}

可以使用super关键字调用的父类方法,不能定义为private.重新定义方法要注意,对于父类中的方法权限,只能扩大但不能缩小。
在JDK5之前,重新定义方法时除了可以定义权限较大的关键字外,其他部分必须与父类中方法签署完全一致。
创建子类实例后,会先执行父类构造函数定义的流程,再执行子类构造函数定义的流程。
构造函数可以重载,父类中可重载多个构造函数,如果子类构造函数中没有指定执行父类中哪个构造函数,默认会调用父类中无参数构造函数。
this()与super()只能择一调用,而且一定要在构造函数第一行执行。
class前也可以加上final关键字,如果class前使用了final关键字定义,那么表示这个类是最后一个了,不会再有子类,也就是不能被继承,String在定义时就限定为final了。
定义方法时,也可以限定该方法为final,这表示最后一次定义方法了,也就是子类不可以重新定义final方法。
如果尝试在继承父类后,重新定义final方法,则会发生编译错误。
在Java中。子类只能继承一个父类,如果定义类时没有使用extends关键字指定继承任何类,那一定是继承java.lang.Object.因此在Java中,任何类追溯至最上层父类,一定就是java.lang.Object,也就是Java中所有对象,一定“是一种”Object.
以下定义的ArrayList类,可以不限长度地收集对象:

package cc.openhome;
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;
    }
}

只要不是被定义为final方法,都可以重新定义。
instanceof运算符,它可以用来判断对象是否由某个类创建,左操作数是对象,右操作数是类,在使用instanceof时,编译程序还会来帮点忙,会检查左操作数类型是否在右操作数类型的继承架构中。只要左操作数类型是右操作数类型的子类型,instanceof也是返回true.
对于不再有用的对象,JVM有垃圾收集机制,收集到的垃圾对象所占的内存空间,会被垃圾收集器释放。执行流程中,无法通过变量参考的对象,就是GC认定的垃圾对象。

第七章

7.1 何谓接口
对于“定义行为”,在Java中可以使用interface关键字定义:

package cc.openhome;
public interface Swimmer{
    public abstract void swim();
}

接口可以用于定义行为但不定义操作。类要操作接口,必须使用implements关键字。操作某接口时,对接口中定义的方法有两种处理方式,一是操作接口中定义的方法,二是再度将该方法标示为abstract.
操作接口则表示“拥有行为”,但不会有“是一种”的关系。

package cc.openhome;
public class Ocean {
    public static void main(String[] args) {
        doSwim(new Anemonefish("尼莫"));
        doSwim(new Shark("兰尼"));
        doSwim(new Human("贾斯汀"));
        doSwim(new Submarine("黄色一号"));
    }
    static void doSwim(Swimmer swimmer){
        swimmer.swim();
    }
}

如果增加新的需求,原有的程序无需修改,只需针对新需求撰写程序,那就是有弹性、具可维护性的程序。
在Java中,类可以操作两个以上的类,也就是拥有两种以上的行为。
在Java中,接口可以继承自另一个接口,也就是继承父接口行为,再在子接口中额外定义行为。
7.2 接口语法细节
在Java中,可使用interface来定义抽象的行为与外观,如接口中的方法可声明为public abstract:

public interface Swimmer{
    public abstract void swim();
}

接口中的方法没有操作时,一定得是公开且抽象为了方便,你也可以省略public abstract.
在interface中,可以定义常数:

package cc.openhome;
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中经常见到在接口中定义这类常数,称为枚举常数。事实上,在interface中,也只能定义public static final的枚举常数。在接口中枚举常数,一定要使用=指定值,否则就会编译错误。
接口可以继承别的接口,也可以同时继承两个以上的接口,同样也是使用extends关键字,这代表了继承父接口的行为。在JDK8之后,如果父接口中定义的方法有操作,也代表了继承父接口的操作。
在撰写Java程序时,经常会有临时继承某个类或操作某个接口并建立实例的需求。由于这类子类或接口操作类只使用一次,不需要为这些类定义名称,这时可以使用匿名内部类来解决这个需求。语法为:

new 父类()|接口(){
    //类本体操作
};

JDK8出现前,如果要在匿名内部类中存取局部变量,则该局部变量必须是final,否则会发生编译错误。
enum定义了特殊的类,继承自java.lang.Enum,不过这是由编译程序处理,直接撰写程序继承Enum类会被编译程序拒绝。

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

这周的两章学习在试着敲代码过程中发现和之前有很大的不一样,刚开始我只是单纯地把书上代码敲上去,但是发现并没有出现理想的运行结果,后来发现书上前后代码之间都是有联系的,不能只敲当前这个代码,也许它是继承了之前的父类,要把之前的代码也敲上才行,于是经过不断调试,终于运行出了结果。

代码调试中的问题和解决过程

在运行P201代码时出现错误

解决办法:发现这个程序跟之前的程序相关联,只敲这个程序的代码当然会运行失败~

本周代码托管截图



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

这周的学习可以感觉到Java这门语言和以前学过的C语言有很大的不同,看书一点点理解作者要表达的东西,过程是缓慢的,但当你慢慢领悟到他所讲的东西时就会觉得自己又多掌握了一点知识,感觉自己还是应该更早一点开始每周的学习任务,这样才会有更多充沛的时间去消化理解,毕竟学习总往后拖还是不好的。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 100/100 1/2 10/15
第二周 100/200 2/4 15/30
第三周 300/500 1/5 30/60
第四周 300/800 1/6 30/90

参考资料

posted on 2016-03-27 22:24  20145206邹京儒  阅读(129)  评论(2编辑  收藏  举报