继承是从已有的类中派生出新的类,新的类能够吸收已有的类的属性和方法,并能派生出新的属性和方法。(换种说话,从已有的类中提取共有的属性和方法,把它作为父类,已有的类都继承这个类。)
使用继承可以优化设计
Dog类 |
name ,health,love |
strain |
Print() |
Penguin类 |
name ,health,love |
Sex |
Print() |
Pet类 |
name ,health,love |
Print() |
1.定义父类
2.子类 extends 父类
extends 关键字
[访问修饰符] class pet{
共有的属性 和方法
}
[访问修饰符] class Dog extends Pet{
子类特有的属性和方法
}
java 只支持单根继承,每个子类只能有一个直接父类,一个父类可以被多个子类继承。
(1)使用super关键字,super代表父类对象 ;
(2)在子类构造方法中调用且必须是第一句。
(3)不可以访问父类中定义为private的属性和方法。
super() 表示调用父类的无参构造
super(name) 表示调用父类的带参构造 super(属性1,属性2,属性3….)
super.name
super.print() super.方法名 调用父类的方法
调用规则:
子类:没有通过this显示的调用自己的构造方法,也没有super(属性名)调用父类的带参构造方法,那么默认调用父类的无参构造方法。
子类:子类通过super(属性名)调用父类的带参构造方法,那么执行父类的带参构造,而不会执行无参构造
子类:子类构造方法通过this显示调用自身的其他构造方法时,在相应构造方法中应用以上两条规则
示例:
父类Pet
/**
* 1.将共有的属性,和方法 抽取到父类中
* 2.通过 extends 关键字 让子类继承父类 建立子父类之间的联系
* 构造的调用规则:
* super() 表示调用父类的无参构造 super(属性1,属性2,属性3...) 表示调用父类的带参构造
* 子类中没有通过this(属性名),this()调用自身的其他构造,也没有通过super(属性名)显式的调用父类的带参构造,默认调用父类的无参构造。
* 子类通过super(属性名)调用父类的带参构造方法,那么执行父类的带参构造,而不会执行无参构造
* 子类:子类构造方法通过this显示调用自身的其他构造方法时,在相应构造方法中应用以上两条规则
* super.方法名() 表示调用父类的方法
* @authorAdministrator
*/
publicclassPet {
privateString name; //名字
privateinthealth;//健康值
privateintlove; //亲密度
/**
* 父类里无参构造
*/
publicPet() {
System.out.println("调用了父类Pet中的无参构造Pet()");
}
/**
* 父类里带2个参数 name,health的构造
* @paramname
* @paramhealth
*/
publicPet(String name,inthealth){
super(); //表示Object基类中的无参构造 ,super()写不写都一样,不写默认也会调用
this.name= name;
this.health= health;
System.out.println("调用了父类Pet中带2个参数的构造Pet(name,health)");
}
/**
* 父类Pet的构造中,只能出现super()表示调用基类Object的无参构造 ,this(),this(属性名) 表示调用自身的其他构造 ,不可能出现super(属性名)
* @paramname
* @paramhealth
* @paramlove
*/
publicPet(String name, inthealth, intlove) {
this(name,health);
this.love= love;
}
publicString getName() {
returnname;
}
publicvoidsetName(String name) {
this.name= name;
}
publicintgetHealth() {
returnhealth;
}
publicvoidsetHealth(inthealth) {
this.health= health;
}
publicintgetLove() {
returnlove;
}
publicvoidsetLove(intlove) {
this.love= love;
}
publicvoidprint(){
System.out.print("宠物的自白:\n我叫"+this.getName()+",我的健康值是:"+this.getHealth()+",和主人的亲密度为:"+this.getLove());
}
}
子类Dog
/**
* 1如何写子父类之间带参构造
* 2.如何调用父类的方法 super.方法名
* @authorAdministrator
*
*/
publicclassDog extendsPet {
privateString strain; //品种 狗狗特有的属性
/**
* 无参构造
*/
publicDog() {
super();
System.out.println("调用了子类Dog()中的无参构造");
}
/**
* 带2个参数name,strain的构造
* @paramname
* @paramstrain
*/
publicDog(String name,String strain){
super(); //表示显示的调用父类里的无参构造,写不写都一样,默认都会去调用父类的无参构造
//super.方法名 调用父类Pet中set方法给name属性赋值 this.setName(name);
super.setName(name);
this.strain= strain;
System.out.println("调用了子类Dog(name,strain)中带2个参数的构造");
}
/**
* 带3个参数 name,health,strain的构造
* @paramname
* @paramhealth
* @paramstrain
*/
publicDog(String name,inthealth,String strain){
super(name,health); //super(属性名)调用父类里带2个参数的构造
this.strain= strain;
System.out.println("调用了子类Dog(name,health,strain)中带3个参数的构造");
}
/**
* 子类Dog中带4个参数的构造
* @paramname
* @paramhealth
* @paramlove
* @paramstrain
*/
publicDog(String name,inthealth,intlove,String strain){
this(name,health,strain); //调用自身的带3个参数的构造,给name,health,strain3个属性赋值
super.setLove(love);
System.out.println("调用了子类Dog(name,health,love,strain)中带4个参数的构造");
}
publicString getStrain() {
returnstrain;
}
publicvoidsetStrain(String strain) {
this.strain= strain;
}
publicvoidprint(){
//先去调用父类的print()显示前3个属性的信息
super.print();
System.out.println(",我是一只"+this.getStrain());
}
}
子类Penguin:
publicclassPenguin extendsPet {
privateString sex; //性别 企鹅特有的属性
publicPenguin() {
}
publicPenguin(String name,inthealth,intlove,String sex) {
/*super.setName(name);
super.setHealth(health);
super.setLove(love);*/
super(name,health,love);
this.sex= sex;
}
publicString getSex() {
returnsex;
}
publicvoidsetSex(String sex) {
this.sex= sex;
}
publicvoidprint(){
super.print();
System.out.println(",我的性别是:"+this.getSex());
}
}
只能继承public 和protected 修饰的,不管在不在同一包里
继承默认(default)修饰的,只能在同一个包里
构造方法不能继承。只能调用 ,通过super调用。
is-a 关系的设计使用继承 (猫是一种哺乳动物,藏獒是一种狗)
子类根据需求对父类继承的方法进行重新编写,
重写时,可以用super.方法的方式来保留父类的方法
构造方法不能被重写
方法重写的规则:
方法名相同
参数列表相同
返回值类型相同或者是其子类
访问权限不能严于父类
(如果父类方法用protected修饰 ,子类可以用protected,public ,如果父类用default修饰的,子类可以用default,protected,public)
父类的静态方法不能被子类覆盖为非静态方法,父类的非静态方法不能被子类覆盖为静态方法。
子类可以定义与父类同名的静态方法,以便在子类中隐藏父类的静态方法。
父类的私有方法不能被子类覆盖
不能抛出比父类方法更多的异常,运行时异常除外。
面试题: 重写和重载的区别?
方法重写:父子类, 方法同名,同参,返回值相同或是其子类,访问权限不能严于父类的方法权限
方法重载:同一个类 方法同名,参数列表不同(个数,类型,顺序),和返回值,访问权限无关。
示例:
importjava.io.FileNotFoundException;
importjava.text.ParseException;
publicclassBase {
publicvoidceshi1(){
System.out.println("hello");
}
voidceshi2(){
System.out.println("测试2");
}
protectedvoidceshi2(String name,String sex){
}
publicintceshi3(inta){
returna;
}
publicBase getBase(){
returnnewBase();
}
/**
* 父类的静态方法
*/
publicstaticvoidceshi4(){
}
/**
* 父类的非静态方法(普通方法)
*/
publicvoidceshi5(){
}
publicstaticvoidceshi6(){
System.out.println("父类Base中的静态方法ceshi6()");
}
privatevoidceshi7(inta){
System.out.println(10);
}
/**
* 该方法抛出2个可查的异常
* @throwsFileNotFoundException
* @throwsParseException
*/
publicvoidceshi8() throwsFileNotFoundException,ParseException{
}
/**
* 该方法抛出2个运行时异常
* @throwsArithmeticException
* @throwsNullPointerException
*/
publicvoidceshi9() throwsArithmeticException,NullPointerException{
}
}
importjava.io.FileNotFoundException;
importjava.text.ParseException;
publicclassSub extendsBase {
publicvoidceshi1(){
System.out.println("world");
}
/**
* 编译错误 ,访问权限(访问修饰符级别>=父类的方法的访问级别) 不能严于父类,
*/
/*private void ceshi2(){
System.out.println("子类里的测试2");
}*/
protected/*public*/voidceshi2(){
}
/**
* 重写,参数列表相同
*/
protectedvoidceshi2(String name,String sex){
}
/**
* 重写,返回值类型和父类相同
*/
publicintceshi3(intb){
returnb;
}
/**
* 重写,返回值类型是其子类
*/
publicSub getBase(){
returnnewSub();
}
/**
* 编译错误,不是重写,父类的静态方法不能被子类覆盖为非静态方法
*/
/*public void ceshi4(){
}*/
/**
* 编译错误,不是重写 父类的非静态方法不能被子类覆盖为静态方法
*/
/*public static void ceshi5(){
}*/
/**
*不是重写, 只是子类定义了父类同名的静态方法
*/
publicstaticvoidceshi6(){
System.out.println("子类Sub中的静态方法ceshi6()");
}
/**
* 不是重写,此处的ceshi7(inta)和父类Base中的私有方法ceshi7(inta),没有任何关系,就是方法同名
* 父类Base中的ceshi7(inta) 该方法的作用域只在类Base中有效,超过该类,任何地方都访问不到
* @parama
*/
publicvoidceshi7(inta){
System.out.println(12);
}
/**
* 不能抛出比父类方法更多的异常
*/
/*public void ceshi8() throws FileNotFoundException,ParseException,ClassNotFoundException{
}*/
/**
* 虽然抛出了比父类更多的异常,但是这些异常是运行时异常,所以不会编译出错,仍旧是重写
*/
publicvoidceshi9() throwsArithmeticException,NullPointerException,ClassCastException,ArrayStoreException{
}
}
例题1:
packagecom.njwb.inherit2;
classPerson{
privateString name;
publicString getName() {
returnname;
}
publicvoidsetName(String name) {
this.name= name;
}
publicPerson() {
//super(); //调用Object基类的无参构造
System.out.println("execute Person()");
}
publicPerson(String name) {
super();
this.name= name;
System.out.println("execute Person(name)");
}
}
/**
* 学生类 继承Person人类
* @authorAdministrator
*
*/
classStudent extendsPerson{
privateString school; //学校
publicString getSchool() {
returnschool;
}
publicvoidsetSchool(String school) {
this.school= school;
}
publicStudent() {
System.out.println("execute Student()");
}
publicStudent(String name,String school) {
super(name);
this.school= school;
System.out.println("execute School(name,school)");
}
}
/**
* 研究生类 继承学生类
* @authorAdministrator
*
*/
classPostGraduate extendsStudent{
privateString guide; //导师
publicString getGuide() {
returnguide;
}
publicvoidsetGuide(String guide) {
this.guide= guide;
}
publicPostGraduate() {
System.out.println("execute PostGraduate()");
}
publicPostGraduate(String name,String school,String guide) {
super(name,school);
this.guide= guide;
System.out.println("executePostGraduate(name,school,guide) ");
}
}
@SuppressWarnings("unused")
publicclassTestStudent {
publicstaticvoidmain(String[] args) {
PostGraduate post = newPostGraduate();
System.out.println("---------------------\n");
PostGraduate post2 = newPostGraduate("张三","北京大学","王教授");
}
}
示例2:
父类的实例成员 --à父类的构造---à子类的实例成员----à子类的构造
classFather{
intnum=getNum() ; //实例成员 getNum()虽然是静态方法,但是赋值给num变量,num是实例成员
publicstaticintgetNum(){
System.out.println("1父类Father中的getNum()");
return10;
}
publicFather() {
System.out.println("2父类Father的无参构造");
}
}
classSon extendsFather{
intnum2= getNum2(); //实例成员
publicstaticintgetNum2(){
System.out.println("3子类Son中的getNum2()");
return20;
}
publicSon() {
System.out.println("4子类Son无参构造");
}
}
publicclassTest2 {
publicstaticvoidmain(String[] args) {
Son son= newSon();
}
}
注意:加载顺序:启动类(java虚拟机启动时,被标明为启动类的类)的static block 最先加载(父类静态成员,静态代码块----子类静态成员,静态代码块---父类实例成员,代码块-----父类构造函数------子类实例成员,代码块---子类构造函数)
final 修饰成员变量,则成为实例常量
final修饰类,类不能被继承
final修饰成员方法,则该方法不能被子类重写。
/**
* 将项目中能够用到的常量都存放在一个类里,这个类叫做常量类
* @authorAdministrator
*
*/
publicclassConstant {
publicfinalString GENDER="男";
publicfinaldoublePI=3.14;
publicfinalintMAX_COUNT=100;
}
网吧管理系统
User用户类,包含用户名、密码等相关属性
UserManager用户管理类,有一个存放用户的数组,数组的每一个元素是一个User类
方法包括添加用户、删除用户、编辑用户、查询所有用户
UserManagerSystem测试类,包含main方法,调用UserManager用户管理类的增删改查。