继续学习:
7.偏头痛杨的Java入门教学系列之进阶面向对象篇
上Java课的时候没弄明白接口,今天终于明白了(但没使用过,还停在理论的程度,可能理解也不准确,以后学通了会回来补充:)如果你刚学Java,对Java的三要素不能理解,强烈推荐看一下这篇文章。
下面是看完偏头痛杨的这篇博客的摘要
继承(Inheritance,也称为泛化)
为什么要继承
- 继承是面向对象编程实现软件复用的重要手段
- 当子类被继承,子类作为一种特殊的父类,将直接获得父类的属性和方法,同时子类也可以增加自己的属性和方法,以及重新定义父类的属性,重写父类的方法以获得和父类方法实现的不同的功能。
- 在类层次结构中,,对父类的改动自动反映在它所有的子类,子类的子类中,不需要修改或重新编译任何低层次的类,那些类通过继承而接收父类中新改变的信息,仅仅需要在层次结构中定义行为和属性一次,那么,以后将自动由所有子类所继承。
- 继承有利于软件的复用,避免重复代码,提高开发效率。
什么时候会用到继承
(这里理解比较浅,以后对Java继承加深理解后再补充)
- 当两个类具有相同的特征(属性)和行为(方法)时,可以将相同的部分抽取出来放到一个类中作为父类,然后这两个类作为这个父类的子类继承父类的属性和方法。
继承的一些注意事项
- 子类无法继承父类的构造方法
- Java只支持单继承(可以用接口变相实现多继承)
- 父类中private的属性和方法无法被继承
- 继承提高了类之间的耦合性
- 所有的类默认继承java.lang.Object
特别的
- 实例化子类对象的时候总会在执行子类构造方法之前去调用父类的构造方法(先实例化父类,再实例化子类,如果继承的类很多则可能影响性能)
- 如果父类中有无参构造,则默认先调用父类的无参构造(子类不用显示的调用super())
- 如果父类没有无参构造,则需显示的在子类构造中用super()来调用父类相应的构造,且必须在第一行调用
- 如果父类中只有有参构造,而子类没有显示的去调用则会报错
- 如果父类中只有有参构造,而子类显示的去调用父类的无参构造则也会报错
this和super关键字
this()与super()必须定在在构造方法中,并且必须在第一行
super()
调用父类的构造方法,只能出现在子类的构造器中,且必须是第一行。
- super()中的参数,决定了调用父类的那个构造方法
- 如果子类的构造方法中没有出现super,那么编译器默认加上super(),即调用父类的无参构造,如果父类没有无参构造,编译器就会报错。
this()
调用本类的构造方法
注意:
- this()和super()不能出现在static的方法与static块中(这个不理解,感觉可能与加载顺序有关,以后回来补充)
- this()调用和super()调用不会同时出现
this. 和super.
- super.指向父类的引用,我们可以通过super关键字来实现对父类成员的访问。
- this.指向本类的引用,我们可以通过this关键字来实现对本类成员的访问。
final关键字
final可以修饰的元素:
- 类:不能被继承,类被定义成final,那么类中所有的方法全部为final
- 方法:不能在子类中被覆盖(private方法除外,因为private方法不能被子类继承),即不能修改
- 变量:被final修饰,也就是常量
包(package)
- 包主要用来对类和接口进行分类
- 与文件夹类似,把Java类文件放到不同包(文件夹)中,不同的报下,文件名可以重复
- 与包相关的语句:1.打包语句package;2.引用包语句import
- package语句必须写在第一行,不写的话,默认放在默认路径下,也就是src根目录
- 使用import访问第三方或者其他包中的类,如果这个类与本类在同一个包中则不需要import
//package 包名;
//package 包名.子包名.子子包名;
package com.webi.hwj.weixin.controller;
public class WeixinHandleController {
}
import 包名;
import 包名.子包名.子子包名;
package com.webi.hwj.weixin.controller;
import org.apache.log4j.Logger;
public class WeixinHandleController {
Logger logger = Logger.getLogger(WeixinHandleController.class);
}
封装
将对象实现的细节(属性和方法)隐藏起来,然后通过一些公用方法来暴露该对象的功能。
为什么要封装
开发者让使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑,限制对属性的不合理操作。
如何实现封装
Java的访问控制符
从小到大:private,default,protected,public
范围:同一类,同一包,子类,全局范围(同一项目)
注意
- 类的控制级别只有public和default,成员变量与方法四个都有
- 如果类的构造方法为private,则其他类均不能生成该类的实例(自己类内部可以)
- Java类中一般会使用private来修饰成员变量,来防止外部调用
模块设计追求高内聚、低耦合。
高内聚:尽可能把模块的内部数据、功能实现细节隐藏在模块的内部独立完成,不允许外部直接干涉。
低耦合:仅暴露少量的方法给外部使用。
方法的覆盖
重写(overriding)
在父子类继承情况下,子类写出一个跟父类一摸一样的方法,方法体内可以修改,这就是重写。
优势:子类可以根据需要,定义特定与自己的行为,即子类可以根据需要实现父类的方法
注意:子类中写的要覆盖父类的方法的访问权限要不小于父类中被覆盖方法的访问权限
重载(overloading)
在同一个类中,新写一个方法,方法名跟某一个老方法一样,但参数必须不一样,返回值可能也不一样,这就是新方法重载了老方法。
比较常见的重载方式是重载构造方法
多态(Polymorphism)
多态是建立在继承的基础上的,是指子类类型的对象可以赋值给父类类型的引用变量,但运行时仍表现子类的行为特征。
也就是说,同一中类型的对象执行同一个方法时可以表现出不同的行为特征。
为什么要使用多态
可以增强程序的可扩展性及可维护性,使代码更加简洁。
作用:在方法传递引用数据类型的时候,使方法内部的代码更具有可维护性,当有新增子类时,方法内部的代码不用去修改,进一步的使用抽象的概念。
java引用变量有两个类型:一个是编译时类型,一个是运行时类型。
编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定,如果编译时类型与运行时类型不一致,就可能会出现所谓的多态。
多态的三个必要条件:
- 要有类继承或实现接口
- 要有方法重写
- 父类引用指向子类对象(或接口引用指向实现类对象)。
满足条件后,当调用父类中被重写的方法后,运行时创建的是哪个子类的对象,就调用该子类中重写的那个方法。
注意
- 在多态情况下,父类的成员变量无法被子类覆盖,因此需要使用setter/getter方法。
- 在继承情况下,父类的成员变量可以被子类覆盖。
- 在多态情况下,子类有重写父类方法的情况,则调用子类方法。
- 多态情况下,对象无法调用子类独有的方法与属性,只能调用编译类型的成员。
抽象类、抽象方法
抽象方法
可以只有方法定义,没有方法实现的方法,抽象方法由子类来实现。
子类必须实现父类的抽象方法,否则报错,但如果子类也是抽象类就没问题了
抽象类
抽象类是从多个具体类中抽象出来的父类,它具有更高层次的抽象。从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为其子类的模板,从而避免了子类设计的随意性。
注意:
- 抽象类不能实例化,即不能new,抽象类的构造方法不能用于创建实例,而是用于被子类调用。可以这么理解:抽象类,既然还是抽象类,那怎么能实例化呢?比如说你跟老板说买十斤“鱼”,这个老板就为难了,“鱼”是一个抽象的概念,应该说清楚,买鲤鱼还是鲢鱼(也就是被子类调用)。
- static、final、private方法与构造方法不能被声明为抽象方法
- 抽象类中可以有非抽象方法,但含有抽象类的方法一定是抽象方法。
- 抽象类允许有构造方法(不是抽象方法),在子类实例化对象时会自动调用父类的构造方法
接口
接口是抽象类的变体,在接口中,所有方法都是抽象的,多继承性可通过实现这样的接口而获得。
接口就是标准(一些类需要遵守的规范),是用来隔离具体实现的(或者说是和具体实现解耦)。
程序接口的使用就将调用者和提供者之间进行了解耦,只要实现者遵守这个接口来做实现就好,实现细节不用管。比如说U盘,不需要关注U盘里存放的内容与不同电脑的兼容性,只要USB接口一样就OK。
注意
- 接口不是类,不能被实例化也没有构造方法,但抽象类有构造方法。
- 接口内所有的属性均默认为public static final,只能在定义时指定默认值。
- 接口内所有的方法均默认为public abstract,不能用static&final。
- 接口内不允许有正常方法(带方法体的方法)。
- 接口可以同时继承多个父接口,但接口只能继承接口,不能继承类。
- 方法提供者与方法调用者有可能是一个人也可能是不同的人(可以理解成,写一个接口,可以被自己调用也可以被别人调用)。
- 一个java源文件中最多只能有一个public接口,并且文件名与接口名相同。
类实现接口(implements)
类一旦实现接口,就必须实现其所有方法,否则这个类必须声明为抽象类。
一个类可以只能继承一个类,但可以实现多个接口。
多个无关的类可以实现一个接口,一个类可以实现多个无关的接口。
一个类可以在继承一个父类的同时,实现一个或多个接口。
接口与抽象类的区别
- 接口不能含有任何非抽象方法,而抽象类可以。(JDK8以及以上除外)
- 类可以实现多个接口,但只能继承一个父类。
- 接口不是类分级结构的一部分,没有联系的类可以实现相同的接口。(这也是接口的优势之一)
更多的请看原博客,这里简单的摘了一些。以便以后快速拾起来。