1.protected使用
protected处理的是继承的概念,如果创建了一个新包,并从另一个包中继承类,可以访问的成员有public和protected。protected 也提供包访问权限。
package com.zhangyue.learn;
import static net.mindview.util.Print.*;
public class Test1 {
protected int n;
public int m;
public static void main(String[] args) {
print("aaaaa");
}
}
package com.zhangyue.learn1;
import com.zhangyue.learn.Test1;
public class LearnProtect extends Test1{
public static void main(String[] args) {
LearnProtect l = new LearnProtect();
l.m = 1;
l.n = 2;
}
}
class Other{
void test(){
Test1 t = new Test1();
t.m = 2;
// t.n = 1;
}
}
2.访问权限控制将权限的边界化在了数据类型的内部的原因
- 第一,设定客户端程序员可以使用和不可以使用的界限,可以在结构中建立自己的内部机制,不必担心客户端程序员把它当做是自己可以使用的接口的一部分。
- 第二,就是接口和具体实现进行分离。如果一个结构是用于程序中,而客户端程序员除了可以向接口发送信息外什么也不可以做的话,就可以随意更改所有不是public的东西而不会破坏客户端代码。
3. 复用类
即可以通过创建新类来复用代码,而不必重头开始编写,可以使用别人已经开发并且调试好的类,有两种方法,组合语法和继承语法。
- 组合语法:新有的类是由现有的类的对象组合而成的,复用了现有代码的功能,而不是它的形式。
- 继承语法:按照现有类的类型来创建新类。无需改变现有类的形式,采用现有类的形式并在其中添加新代码。
5. 继承
当创建一个类时,总是在继承,除了明确指出继承哪个类,都隐式地继承Object类。
package com.zhangyue.learn;
class Cleanser{
private String s = "Cleanser";
public void append(String a){ s += a;}
public void dilute(){ append(" dilute()");}
public void apply(){ append(" apply()");}
public void scrub(){ append(" scrub()");}
public String toString(){return s;}
//可以为每个类创建一个main()方法,方便测试
public static void main(String[] args){
Cleanser c = new Cleanser();
c.dilute();c.apply();c.scrub();
System.out.println(c);
}
}
public class Detergent extends Cleanser{
public void scrub(){
append("Deprecated.scrub()");
super.scrub();//super 表示超类的意思,当前类就是从超类继承过来的
}
public void foam(){
append("foam()");
}
public static void main(String[] args) {
Detergent d = new Detergent();
d.apply();d.dilute();d.scrub();d.foam();
System.out.println(d);
System.out.println("Testing base class");
Cleanser.main(args);
}
}
6.基类初始化
- 构造器不带参数
package com.zhangyue.learn;
class Art{
public Art() {
System.out.println("Art()");
}
}
class Drawing extends Art{
public Drawing() {
System.out.println("Drawing()");
}
}
public class Cartoon extends Drawing{
public Cartoon() {
System.out.println("Cartoon()");
}
public static void main(String[] args) {
Cartoon c = new Cartoon();
}
}
/*output
Art()
Drawing()
Cartoon()
*/
构造过程从基类向外扩散,基类在导出类可以访问它之前就完成了初始化。即使不为Cartoon创建构造器,编译器也会合成默认的构造器调用基类构造器。
- 构造器带参数
package com.zhangyue.learn;
class Game{
public Game(int i) {
System.out.println("Game()");
}
}
class BoardGame extends Game{
public BoardGame(int i) {
super(i); //调用基类构造器
System.out.println("BoardGame()");
}
}
public class Chess extends BoardGame{
public Chess() {
super(11);
System.out.println("Chess()");
}
public static void main(String[] args) {
Chess c = new Chess();
}
}
如果不在BoardGame里调用基类构造器,编译器会抱怨无法找到符合Game()形式的构造器,而且,调用基类构造器必须是在导出类构造器中要做的第一件事。
7. 向上转型
“为新的类提供方法”并不是继承中最重要的一面,其最重要的是用来表现新类和基类的关系,即“新类是现有类的一种类型”。
package com.zhangyue.learn;
class Instruction{
public void paly(){}
public static void tune(Instruction i){
i.paly();
}
}
public class Wing extends Instruction{
public static void main(String[] args) {
Wing w = new Wing();
Instruction.tune(w);
}
}
将Wing引用转换为Instruction引用的动作就是向上转型。是安全的。
8. 选择组合与继承
到底使用组合还是继承,一个最清晰的判断方法就是问问自己是否需要从新类向基类进行向上转型。
9.final关键字
说明
对于基本数据类型,final使数据恒定不变;对于对象引用,final是引用恒定不变。一旦引用指向某个对象,就不能再指向另一个对象,但对象本身是可以修改的,java没提供使对象恒定不变的途径。
典型的常量定义方式:
public static final VALUE_ONE;
public指可用于包之外,static强调只有一份 只在第一次创建对象时初始化一次,final则说明是常量。final方法
将方法锁定,以防任何继承类修改它的定义。在继承中使方法行为保持不变并且不会被覆盖。
*final类
将整个类定义为final时,就表示不打算继承该类,对该类的设计不需要做任何变动。