写在前面:
该学习笔记基于《Head First Java》一书,仅供个人参考备忘使用,可能会存在诸多问题,也会随着学习的推进不断修改,因此请酌情将其当作参考。
文章目录
目录
公有(public)和私有(private)
Java中为区分类内部信息的访问权限设置了一组关键字public、protected、default和private,这也就是为什么当我们学完其他语言时看Java代码的变量和方法声明会感到有些迷惑:
C:
int main(void)
{
int a = 0;
}
python:
a = 1
java:
public static void main(String args[]) {
int a = 1;
}
(当时不太喜欢Java的原因,可能很大程度上来自于这个复杂的main函数定义方式……)
在四种访问权限中,初学者需要掌握的基本上就是public和private了。
public
顾名思义,也就是说对于所有人”公开“,即在任何位置都可以对这一类东西进行调用,相当于类或对象对外的接口形式;
private
与public相对的,private则是”私有“,即只能在类的内部进行调用。private访问权限一般用于封装。
继承
继承是面向对象程序设计的又一大特征。
继承发生于类与类之间,被继承的类称为父类,继承父类的类称为子类。
来看一下继承的基本形式:
class Father {
type variance;
public type method1() {
}
public type method2() {
}
}
class Son extends Father {
public type method1() {
}
public type method3() {
}
}
首先,继承使用extends关键字(一定要注意有个s!!!三人称单数)来表明继承关系,使用extends后,子类将获得父类的所有public方法和实例变量。继承关系一般通过继承树来体现:
上图是异常类型的继承树,可以看到根节点是Throwable类,Exception类和Error类均是其子类。
继承的意义在于,它可以将许多子类的共同特征提取出来,因此在设计子类时,只需要关注子类本身独立于父类的特征;且对父类进行的调整可以反映到所有子类上,很大程度上提升了代码复用的效率。
确定继承关系的“IS-A”测试:
在实际设计中如何判断应该使用继承还是其他形式的关联关系(如之后马上要提到的接口)?可以使用一个称为“IS-A”测试的方法来判断:
“is-a”
体现的是“是”与“不是”的关系,如“米饭”一定是食物,“可乐”一定是饮料,此时便可以将这类关系用继承来表达,如 class 米饭 extends 食物、class 可乐 extends 饮料;
“has-a”
体现的是“拥有”的关系,如汽车里有方向盘、离合器等,此类关系属于包含,宜采用类的实例变量形式进行表达。
继承与扩充
子类不能完全和父类一样,不然便失去了继承的意义。
子类要在父类的基础上进行扩充,可以额外增加实例变量和方法,也可以对父类原本的实例变量和方法进行覆写。因此随着继承树的层级增加,每个子类的内容(变量、方法等)会不断增多。
还是拿上面的示例代码来分析:
class Father {
type variance1 = 1;
type variance2 = 1;
public type method1() {
}
public type method2() {
}
}
class Son extends Father {
type variance2 = 2;
public type method1() {
}
public type method3() {
}
}
上图中,子类Son对父类Father的method1方法和实例变量variance2进行了覆写,同时新增了一个method3方法。
覆写:
在子类中定义与父类同名、同参数的方法,将父类中原有方法进行掩盖。
覆写需要满足的两个条件:
①参数相同,返回值类型要兼容
返回值的兼容性在后面的多态部分会进一步介绍
②不能降低方法存取权限
也就是不能将父类中的public方法覆写为private方法
被覆写过的父类方法还能使用吗?
答案是能。此时需要使用super.method()形式对方法进行调用:
super.method(parameters)
如何阻止继承?
当希望某个类或是类中的某些实例变量或方法不能再被继承或修改,可以使用final关键字进行修饰:
final int a = 1;
final class last {
final last_method()
{
}
}
在类中使用final修饰变量,也可以理解为设置了一个类内部的常量,该变量之后不得进行修改。不过此时final一般会与static连用,形成static final型的常量。
使用final修饰方法和类,一般是为体现方法和类的功能已经完善,不需要再进行修改了。
Object类——所有类的起源
Java中所有的类都直接或间接地继承自Object类,其内部定义了一些关于对象的基本方法:
.equals(Object object)
判断两个类是否“相等”,每个类有不同的判断标准,大多数类会对此方法进行覆写.getClass()
返回对象的具体类型.hashCode()
列出对象的Hash码
大多数Object类的方法在具体的子类中都会被覆写。
多态
多态是继承直接衍生出的一种属性。由于继承会让子类具备父类的所有public类型实例变量与方法,因此可以保证对父类执行的操作一定能够对子类执行。基于这一点,可以做如下两种操作:
Father object = new Son();
即为用父类声明的引用赋上子类对象作为引用对象;
public Father method(Father a) { return new Son(); } method(new Son());
即可以在返回父类的方法中以子类作为返回值,同时父类参数也可以传入子类对象
总而言之,就是一切能够使用父类的地方,都能使用子类进行代替。当然这样做仅仅是能够让程序通过编译。
方法的重载
重载(Overload)是一个独立于多态的概念,重载的形式有时可能与子类对父类的覆写有些相似,但是二者实质上并无太多联系。
“重载”顾名思义,是对于一个东西进行重新载入。方法的重载,即是在一个类中定义多个同名、但不同参数的方法。重载的核心是“参数不同”,即同一个方法可以针对不同的输入信息做个性化的处理,使用重载可以使方法具有更高的扩展性。
另外,重载对返回值类型并无严格要求,同一方法的不同参数版本,返回值可以相同也可以不同。同时,不同版本的存储权限也可以不同。
方法重载在类的构造函数中应用的比较广泛。
class Animal {
private String name;
public Animal() {
System.out.println("this is an animal");
}
public Animal(String theName) {
name = theName;
}
public void setName(String newName) {
name = newName;
}
}
上面的Animal类中,构造函数Animal()便进行了重载,有一个无参数的版本和一个有参数theName的版本。
To be continue……