20172319 《Java程序设计教程》第7周学习总结
20172319 2018.04.11-16
《Java程序设计教程》第7周学习总结
目录
- 教材学习内容总结
- 教材学习中的问题和解决过程
- 代码调试中的问题和解决过程
- 代码托管
- 上周考试错题总结
- 结对及互评
点评过的同学博客和代码 - 其他(感悟、思考等,可选)
- 学习进度条
- 参考资料
教材学习内容总结
第九章 继承:
-
创建子类:
父类(超类、基类):人;
子类(亚类、派生类):黄种人,黑种人、白种人;
父类提供大体框架,子类基于此框架又包含不同特点(eg: 不同人种的颜色);
用extends
指明新类由现有类派生,相当于“是”;
子类继承父类中的方法定义及变量声明 == 这些方法和变量都在子类中声明;(注: 子类可另定义方法和变量以凸显其特征; 继承具有单向性),类不允许多重继承。
(1)protected修饰符:
半公开,在不破坏其封装特性的条件下允许子类及同一包内的其他类引用类中的方法和变量。
注:能引用的方法及变量前必须有protected修饰符 ,子类不会继承父类的构造方法。
在UML类图中 方法和变量前加 # 号表示应用protected修饰符;
子类不能按名引用父类的private成员。
(2)super引用:
调用父类的构造方法,super(需要访问的变量)
(一般情况会在子类构造方法的第一行)——确保父类初始化自身变量在子类执行构造方法之前;
优点: 当父类中使用构造方法改变了设置变量的方式,无需再去子类的构造方法中对其进行修改。
(3)多继承:
当需要使用两种或以上的类来描述对象时使用;
弊端: 遇到父类中成员同名时不知道该继承哪一个。 -
重写方法:
在子类中可以根据需要对从基类继承来的方法进行重写;
重写方法必须和被重写方法具有相同的方法名称、参数列表和返回类型;
重写方法不能使用比被重写方法更严格的访问权限
eg:父类成员权限为private时,方法无法被重写;
注: final修饰符修饰的方法子类也无法重写
优点: 保证子类使用一个特定的方法。
影子变量:
子类中定义与父类名字相同的变量,定义合法,原则上避免。
缺点: 不便于理解代码。 -
类层次结构:
父类派生子类,子类又可派生其它一个或多个子类(子类个数及层数无限制);
同胞: 同一父类的两个子类;
继承具有传递性;应更合理的将公共特征置于更高层的类层级。
(1)Object类:在类的层级中处于最顶层,如果一个类定义中没有extends
指出其父类,则默认其父类为Object;程序中的任何对象都可调用Object中的public方法;
Object类常用的方法:
equals()
等价于==;toString()
返回代表对象的字符串。
(2)抽象类:
使用了关键词abstract声明的类,可以不包含操作方法;在UML类图中,用斜体表示抽象类名;
如果一个类里包含了一个或多个抽象方法,类就必须指定成abstract(抽象);
不能对抽象方法用final
和static
修饰符:
子类无法重写final
方法,static
无需实例化就能用,但方法中无方法体,该方法无意义。
(3)接口层次结构:
接口继承接口,子类继承父类抽象方法及常量。 -
可见性:
父类的私有成员能被子类间接地访问。 -
类间继承关系的设计:
(1)继承关系小结:
1.梳理好每次派生时“是”的关系,一次比一次更具体;
2.设计结构有利于类的复用及未来潜在软件复用;
3.应尽可能使公共属性置于较高类层次;
4.依据需求适当重写方法;
5.依据需求增加新变量(尽量避免出现影子变量);
6.类自己管理自己,进行适当super引用及重写方法;
7.接口模拟多继承;
8.考虑结构前瞻性;
9.子类中应适当重写通用方法;
10.用抽象类为低层类定义公共类接口;
11.慎用修饰符。
(2)继承的限制:
final
修饰符: 用于方法——限制重写;
用于类——限制继承。
教材学习中的问题和解决过程
- 问题1: 类不支持多重继承?
- 解决:自己说的多重继承有好处,然后又明确不支持。
自相矛盾???冲突点: 碰到两个父类中同名成员不知道该继承哪个。简单啊,改方法名不就好咯!合适的名字有利于对代码的理解,许久之后,单独翻出变了名的代码,倘若对其毫无印象,在认知上会变得很困难,所以说这是行不通的;(A是父类,BC是子类,D继承BC)先Cextends
B之后D再extends
C,emmmmm,好像有点道理,其实完全没用BC继承了A的,并在一定基础发展自己的特征,C继承了B,同名的方法会被重写,最后只是D仅仅继承了C。(B=黄种人,C=白种人,预想的D=混血;按上述操作D=白种人)怎么办呢?java能实现多个接口,接口中的方法是抽象的,它没有方法体,因此不能简单通过创建对象调用方法去实现。但这并不能说接口实现是最完美的方案;它有着不能共享实现的缺点。 -
本来只是为了跨越继承层次来共享代码,现在却需要另外生成一个独立对象,而且每次方法调用都要委派给这个对象,这实在是不太合理,而且执行的效率也不高。
——《松本行弘的程序世界》 - 问题2: 关于影子变量
- 解决:书上简单地说了这玩意儿和重写方法差不多,讲得有点玄。自己查了点资料看到这东西。
public class ParentClass
{
public int i = 10;
}
public class SubClass extends ParentClass
{
public int i = 30;
}
public static void main(String[] args)
{
ParentClass parentClass = new SubClass();
SubClass subClass = new SubClass();
System.out.println(parentClass.i + subClass.i);
}
???创建对象里是什么鬼??? 自己去玩了一波
public class h1
{
protected int i = 10;
}
public class h2 extends h1
{
public int i = 20;
}
public static void main(String [] args)
{
h1 a = new h2();
h2 b = new h2();
System.out.println(a.i+b.i);
}
结果输出是30,影子变量并不像是重写数据,它是属于子类的一个变量,名字与父类继承的重合,相当于子类有两个变量i1=10;i2=20,所以说要尽量避免使用, 这对代码的理解增加了难度。
a即是一个h1的对象,也是一个h2的对象,
那么调用方法时,是根据对象的实际类型调用的,
实际类型是h2,所以调用子类的方法,即i。
而访问成员变量就不同了,它是h1时,访问的是父类的成员变量i=10,
转型为h2的话,访问的就是子类的成员变量了i=20。
影子变量!=重写,而是并存,相互隐藏。
-
问题3:关于抽象类与接口
-
解决:抽象类好像除了可以含非抽象方法,除常量外还可声明数据 这两点外与接口并无其他区别,额外地去定义这么一个类是不是有点多余。看似是这样,实则不然:
接口实际上可以算是一个特殊的抽象类,抽象类可以说是对“本质”的定义,这样可以使得子类无需再去重新定义质的公有方法(动物类派生下的猫、狗,无需再去定义它们是动物);接口可以理解为一种“行为”,猫狗发出的“叫”是不同的,为了实现它们不同的行为,可以通过接口来定义“叫”的方法。 -
问题4:接口的派生——有用?
-
解决:实现接口需要实现其定义里的所有方法,如果接口使用继承的话。比如说: 每个接口都定义了一个方法,而需要实现的是经过100多次继承后的接口,要实现它就要翻开所有的父类去查看接口定义的成员名字。
怕不是要累死哦!, 与其这样不如直接将100多个方法定义在一个接口里,这样编程才更有效率。
其实这与其是抽象类有关: 假如所有方法放同一接口中,规定的行为难免会让人感觉有点多了;
1.一个集合,既要定义有序集合的行为,又要定义无序集合的行为,既要定义有重复元素的集合的行为,又要定义无重复元素的集合的行为,假设只有一个方法来定义集合的行为,请问这个方法该怎么实现。千万不要说加上一大堆if else 的判断语句,如果这时候有新的集合类型加入了,难道再加一个if else语句么?这无疑这是一种糟糕极了的方法。
2.而通过接口继承产生的层级接口,层次分析,职责分明,Set就是Set,List就是List,想要实现哪种结构直接实现对应的接口即可。换个角度看,通过接口继承,可以重新定义上层已经定义的行为,也不会影响到同一层级的其他接口中的行为。
代码调试中的问题和解决过程
- 问题1:super引用时出现错误
- 解决:在引用父类的构造方法时,
发现super()l里面是红色的,
后面将鼠标置于括号里,idea提示要输入访问的变量,输入变量后...
然后,idea又提示了,后面还要写入4个需访问的变量,
嗯,问题解决,但又产生了疑问,为什么super的()中需要键入所有的访问变量?
然后去查了下资料,get到了:如果父类的构造方法中包括参数,则参数列表为必选项,用于指定父类构造方法的入口参数.
因为前面的父类构造方法包含了参数列表,所以引用时需要键入所有的访问变量以此来指定父类构造方法中的参数.
代码托管
上周考试错题总结
- 问题1:
- 理解:在Java中,数组是作为对象实现的。该变量是存储整个数组的内存块的引用变量。
- 问题2:
- 理解:数组初始化为= new type [x],其中x是数组的大小。但是,该数组的合法索引为0到x-1,而程序员总是尝试编写代码来尝试访问索引1到x。
- 问题3:
- 理解:语句if(list [j] <temp)c ++; 将列表中的每个元素与temp进行比较,并且只在元素小于temp时将其添加到c中,因此它将列表中的元素数量小于temp,并将此结果存储在c中。
- 问题4:
- 理解:该参数的定义与变量最初声明的一样,类型参数名称。这里的类型是int [],参数是a。
- 问题5:
- 理解:数组索引必须是一个int值,因此如果x不是int,那么通常values [x]会导致语法错误,但如果可以强制转换,Java编译器会自动将x转换为int。通过将char值转换为其等效的ASCII值来将字符转换为整数。所以,如果x是'a',它将被转换为int 97,所以values [x]将存取值[97]。
- 问题6:
- 理解:第一个声明声明a和b都是int数组。第二个声明声明c和d是整数,但是在d的情况下是一个int数组。所以,a,b和d都是int数组。
- 问题7:
- 理解:“=”是一个赋值运算符。如果这两个变量都是基元,那么左边的变量会得到右边变量的副本(所以如果a和b是int值并且b = 5,那么a就变成5)。但是,由于a和b是数组,所以引用变量a被设置为引用变量b,导致a和b引用内存中的同一个数组,或者它们现在是彼此的别名。
- 问题8:
- 理解:如果使用new存储的值的列表实例化数组,则不必使用new来实例化数组。所以,名称= {“Huey”,“Duey”,“Louie”}; 将创建一个包含3个元素的String数组,其中三个值已经初始化。在其他答案中,A没有指定名称是一个字符串数组,C不应该有保留字new,D不应该在名称后面有[3],在String之后省略[],并且E不会将数组实例化为String [3],因此,这四个其他答案在语法上是无效的。
- 问题9:
- 理解:主要方法需要参数,以防程序员希望允许用户提供命令行参数。然后,将在命令行输入的任何内容作为命令行参数接受。如果它是由空格分隔的几个单词,那么每个单词存储为一个单独的字符串数组元素。例如,“java foo.class hi there”会将变量[0]中的“hi”和变量[1]中的“there”存储起来以供程序使用。
- 问题10:
- 理解:Java为可变长度参数列表提供了特殊符号。省略号(...)用于指定可变长度参数列表。
结对及互评
点评过的同学博客和代码
- 本周结对学习情况:
- 20172316赵乾宸
- 博客中值得学习的或存在问题:
1.文字与图片的排版有问题
2.教材内容总结简洁明了
3.可以将自己理解就更好的地方写在博客里,或是编一段代码实际应用一下。 - 20172329王文彬
- **博客中值得学习的或存在问题: **
1.在教材学习中的问题和解决过程的栏目里文字排版缩进有误;
2.教材内容总结简洁明了
3.对于解决的方案,如果能有相应例子就更好了(这也许会很难...)。
其他(感悟、思考等,可选)
- 前面关于类的学习,由于进度的原因,并没有很好地掌握,这一章的内容与类相关,通过学习对类的认知加深了许多。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 202/202 | 1/2 | 15/15 | 积极主动敲代码 |
第二周 | 490/692 | 1/3 | 18/33 | 善于思考 |
第三周 | 581/1273 | 1/4 | 15/48 | 善于完善 |
第四周 | 1857/3130 | 1/6 | 33/81 | 累 |
第五周 | 655/3787 | 1/7 | 22/103 | |
第六周 | 531/4318 | 1/8 | 18/121 | |
第七周 | 810/5128 | 1/9 | 23/ 144 |
参考资料
《Java程序设计与数据结构教程(第二版)》
《Java程序设计与数据结构教程(第二版)》学习指导
Java中关于子类成员变量与父类成员变量同名
接口继承接口的意义
Java 抽象类、普通类、接口的区别
返回目录