继承java
1.1 继承的概述程序员
在现实生活中,继承通常指的是子女继承父辈的财产。在程序中,继承描述的是事物之间的所属关系,经过继承可使多种事物之间造成一种关系体系。算法
格式: class 子类 extends 父类 {}
1.2 继承的格式&使用ide
在程序中,若是想声明一个类继承另外一个类,须要使用extends关键字函数
1.2.1 案例代码一学习
package com.gao_01; /* * 继承:多个类有共同的成员变量和成员方法,抽取到另一个类中(父类),在让多个类去继承这个父类,咱们的多个类就能够获取到父类中的成员了。 * extends * */ public class ExtendsDemo { public static void main(String[] args) { DotA1 d = new DotA1(); d.start(); LOL1 l = new LOL1(); l.start(); } } class Game1 { String name; double version;//版本号 String agent;//代理商 public void start() { System.out.println("游戏启动了"); } public void stop() { System.out.println("游戏关闭了"); } } class DotA1 extends Game1 { /*String name; double version;//版本号 String agent;//代理商 public void start() { System.out.println("游戏启动了"); } public void stop() { System.out.println("游戏关闭了"); }*/ } class LOL1 extends Game1 { /*String name; double version;//版本号 String agent;//代理商 public void start() { System.out.println("游戏启动了"); } public void stop() { System.out.println("游戏关闭了"); }*/ }
1.3 继承的特色this
再类的继承中,须要注意一些问题,具体以下:spa
一、 在java中,类只支持单继承,不容许多继承,也就是说一个类只能有一个直接父类,例以下面这种状况是不合法的。代理
class A{} class B{} class C extends A,B{} // C类不能够同时继承A类和B类
二、 多继承能够继承一个父类,例以下面这种状况是容许的。code
class A{} class B extends A{} class C extends A{} // 类B和类C均可以继承类A
三、在Java中,多层继承是能够的,即一个类的父类能够再去继承另外的父类,例如C类继承自B类,而B类又能够去继承A类,这时,C类也可称做A类的子类。下面这种状况是容许的。
class A{} class B extends A{} // 类B继承类A,类B是类A的子类 class C extends B{} // 类C继承类B,类C是类B的子类,同时也是类A的子类
四、在Java中,子类和父类是一种相对概念,也就是说一个类是某个类父类的同时,也能够是另外一个类的子类。例如上面的这种状况中,B类是A类的子类,同时又是C类的父类
1.3.1 案例代码二
package com.gao_01; /* * Java中继承的特色: * Java语言只支持单一继承,只能继承一个父类(一个儿子只能有一个亲爹) * Java语言支持多层继承(一个儿子能够有一个亲爹,还能够有一个亲爷爷) * */ public class ExtendsDemo2 { public static void main(String[] args) { LOL l = new LOL(); l.update(); l.start(); } } class Game { public void start() { System.out.println("游戏启动了"); } } class PCGame extends Game { public void update() { System.out.println("PCGame更新了"); } } class MobileGame extends Game { public void update() { System.out.println("MobileGame更新了"); } } class LOL extends PCGame { }
1.4 继承中成员变量的特色
A:子类只能获取父类非私有成员
子父类中成员变量的名字不同直接获取父类的成员变量
子父类中成员变量名字是同样的获取的是子类的成员变量
B:就近原则:谁离我近我 就用谁
若是有局部变量就使用局部变量
若是没有局部变量,有子类的成员变量就使用子类的成员变量
若是没有局部变量和子类的成员变量,有父类的成员变量就使用父类的成员变量
C: super:能够获取父类的成员变量和成员方法,用法和this是类似的
1.4.1 案例代码三
package com.gao_01; /* * 继承中成员变量的特色 * 子类只能获取父类非私有成员 * 子父类中成员变量的名字不同直接获取父类的成员变量 * 子父类中成员变量名字是同样的获取的是子类的成员变量 * * 就近原则:谁离我近我就用谁 * 若是有局部变量就使用局部变量 * 若是没有局部变量,有子类的成员变量就使用子类的成员变量 * 若是没有局部变量和子类的成员变量,有父类的成员变量就使用父类的成员变量 * 啥都没有,出错了!!! * * super:能够获取父类的成员变量和成员方法,用法和this是类似的 */ public class ExtendsDemo3 { public static void main(String[] args) { Kid3 k = new Kid3(); k.show(); } } class Dad3 { String name = "小红"; } class Kid3 extends Dad3 { String name = "四葱"; public void show() { String name = "五葱"; System.out.println(super.name); System.out.println(this.name); System.out.println(name); } }
1.5 继承中成员方法的特色&方法重写
1.5.1 案例代码四
A: 若是子类中没有这个方法,调用父类的
package com.gao_01; /* * 继承中成员方法的特色 * 子类中没有这个方法,调用父类的 */ public class ExtendsDemo4 { public static void main(String[] args) { Kid4 k = new Kid4(); k.eat(); } } class Dad4 { public void eat() { System.out.println("小酌两口"); System.out.println("去睡觉了"); } } class Kid4 extends Dad4 { }
1.5.2 案例代码五
B: 子类中重写了这个方法,调用子类的
方法的重写:在子父类当中,子类的方法和父类的彻底同样,子类重写了父类的方
法(覆盖),当子类重写了父类的方法以后,使用子类对象调用的就是子类的方法
package com.gao_01; /* * 继承中成员方法的特色 * 子类中没有这个方法,调用父类的 * 子类中重写了这个方法,调用子类的 * 方法的重写:在子父类当中,子类的方法和父类的彻底同样,子类重写了父类的方法(覆盖),当子类重写了父类的方法以后,使用子类对象调用的就是子类的方法 方法的重载:在一个类中,有多个重名的方法,可是其参数不同(参数的个数,参数的类型,参数的顺序),和返回值无关 */ public class ExtendsDemo4 { public static void main(String[] args) { Kid4 k = new Kid4(); k.eat(); } } class Dad4 { public void eat() { System.out.println("小酌两口"); System.out.println("去睡觉了"); } } class Kid4 extends Dad4 { public void eat() { System.out.println("好好吃饭"); } }
1.6 方法重写的应用场景&注意事项
方法重写的应用场景:当父类的方法不能彻底知足子类使用的时候,既能够保留父类的功能(沿袭、传承),还能够有本身特有的功能
方法重写的注意事项:
不能够重写父类私有的成员方法,压根就看不到父类的私有成员
子类重写父类方法,权限必须大于等于父类方法的权限
注解:
@Override:方法重写,说明下面的方法是重写父类的方法
1.6.1 案例代码六
package com.gao_03; /* * 方法重写的应用场景:当父类的方法不能彻底知足子类使用,这个时候子类重写父类的方法, * 并能够在方法中使用关键字super调用父类的方法,这样作便可以保有父类的功能,也能够拥有子类特有的功能 * 方法重写的注意事项: * 不能重写父类私有的方法 * 权限必须大于等于父类方法的权限 * * 注解:@ * */ public class ExtendsDemo5 { public static void main(String[] args) { NewPhone np = new NewPhone(); np.call(); } } class Phone { void call() { System.out.println("打电话"); } } class NewPhone extends Phone { @Override public void call() { System.out.println("录音"); //System.out.println("打电话"); //super.call(); } }
1.7 继承中构造方法的执行顺序
A: super(实参列表);语句 在子类的构造方法中使用,用来调用父类中的构造方法(具体哪一 个由传递的参数决定),而且只能在构造方法第一行使用
B: this(实参列表); 语句 在类的构造方法中使用,用来调用本类中的其它构造方法(具体哪个由传递的参数决定),而且只能在构造方法的第一行使用
1.7.1 案例代码七
package com.gao_01; /* * 继承中构造方法的执行顺序 * 在子父类中,建立子类对象,调用子类的构造方法, * 在子类的构造方法的第一行代码若是没有调用父类的构造或者没有调用子类的其余构造,则默认调用父类无参构造 * 为何要调用父类构造? * 由于须要给父类的成员变量初始化 * 确定会先把父类的构造执行完毕,在去执行子类构造中的其余代码 * * 我是父类无参构造 --- 我是子类有参构造 --- 我是子类无参构造 */ public class ExtendsDemo6 { public static void main(String[] args) { //Die d = new Die(); Zi6 z = new Zi6(); } } class Die6 { public Die6() { System.out.println("我是父类无参构造"); } public Die6(int num) { System.out.println("我是父类有参构造"); } } class Zi6 extends Die6 { public Zi6() { //super(1); //super(); this(1);//不会再调用父类的无参构造了 System.out.println("我是子类无参构造"); } public Zi6(int num) { //会默认调用父类无参构造 System.out.println("我是子类有参构造"); } }
1.8 this 与 super区别
1.8.1 案例代码八
package com.gao_01; /* * this和super的区别 this:当前对象的引用 调用子类的成员变量 调用子类的成员方法 在子类的构造方法第一行调用子类其余构造方法 super:子类对象的父类引用 调用父类的成员变量 调用父类的成员方法 在子类的构造方法第一行调用父类的构造方法 */ public class ExtendsDemo7 { public static void main(String[] args) { Zi z = new Zi(); z.function(); } } class Die { int num = 10; public Die() { System.out.println("我是父类无参构造"); } public Die(int num) { System.out.println("我是父类有参构造"); } public void method() { System.out.println("我是父类的方法"); } } class Zi extends Die { //int num = 30; public Zi() { //this(1);//第一行不调用子类其余构造或者是父类构造,默认调用父类无参构造 super(); System.out.println("我是子类无参构造"); } public Zi(int num) { System.out.println("我是子类有参构造"); } public void method() { System.out.println("我是子类的方法"); } public void function() { //this.num = 50; //System.out.println(num); //this.method(); //super.num = 40; //super.method(); System.out.println(this.num); } }
1.9 继承的优缺点
A:优势
提升了代码的复用性
提升了代码的可维护性
B:缺点:
类的耦合性加强了
开发的原则:高内聚低耦合
内聚:就是本身完成某件事情的能力
耦合:类与类的关系
匿名对象&final
2.1 匿名对象定义&使用
匿名对象即无名对象,直接使用new关键字来建立对象
2.1.1 案例代码九
package com.gao_01; /* * 匿名对象:没有名字的对象 * 匿名对象的应用场景: * 当方法只调用一次的时候可使用匿名对象 * 能够看成参数进行传递,可是没法在传参以前作其余的事情 * * 注意:匿名对象能够调用成员变量并赋值,可是赋值并无意义 * */ public class AnonymousObejctDemo { public static void main(String[] args) { //Student s = new Student(); //s.study(); //s.study(); //s.study(); //new Student();//匿名对象,没有变量引用的对象 //new Student().study(); //new Student().study(); //new Student().study(); //new Student().age = 18; //System.out.println(new Student().age); //Student s = new Student(); //s.age = 18; //s.name = "张三"; //method(s); method(new Student()); } public static void method(Student s) { } } class Student { String name; int age; public void study() { System.out.println("好好学习,高薪就业"); } }
final: 修饰符,能够用于修饰类、成员方法和成员变量
final所修饰的类:不能被继承,不能有子类
final所修饰的方法:不能被重写
final所修饰的变量:是不能够修改的,是常量
2.2.1 案例代码十
package com.gao_01; /* * final: 修饰符,能够用于修饰类、成员方法和成员变量 * final所修饰的类:不能被继承,不能有子类 * final所修饰的方法:不能被重写 * final所修饰的变量:是不能够修改的,是常量 * * 常量: * 字面值常量:1,2,3 * 自定义常量:被final所修饰的成员变量,一旦初始化则不可改变 * * 注意:自定义常量必须初始化,能够选择显示初始化或者构造初始化 * * */ public class FinalDemo { public static void main(String[] args) { //Animal a = new Animal(); //a.eat(); Dog d = new Dog(); //d.eat(); //d.num = 20; System.out.println(d.NUM); } } /*final*/ class Animal { public final void eat() { System.out.println("吃东西"); } } class Dog extends Animal { /*public void eat() {}*/ final int NUM; public Dog() { NUM = 10; } }
抽象类
3.1 抽象类概述
当编写一个类时,咱们每每会为该类定义一些方法,这些方法是用来描述该类的功能具体实现方式,那么这些方法都有具体的方法体。
可是有的时候,某个父类只是知道子类应该包含怎么样的方法,可是没法准确知道子类如何实现这些方法。好比一个图形类应该有一个求周长的方法,可是不一样的图形求周长的算法不同。那该怎么办呢?
分析事物时,发现了共性内容,就出现向上抽取。会有这样一种特殊状况,就是方法功能声明相同,但方法功能主体不一样。那么这时也能够抽取,但只抽取方法声明,不抽取方法主体。那么此方法就是一个抽象方法。
3.1.1 案例代码十一
package com.gao_01; /* * abstract:关键字,用于修饰方法和类 * 抽象方法:不一样类的方法是类似,可是具体内容又不太同样,因此咱们只能抽取他的声明,没有具体的方法体,没有具体方法体的方法就是抽象方法 * 抽象类:有抽象方法的类必须是抽象类 * * 注意:一个类继承了抽象类须要重写他全部的抽象方法,不然这个类就得是抽象类 */ public class AbstractDemo { } abstract class Animal1 { public abstract void eat(); //非抽象方法子类能够不重写 public void run() { } } class Cat1 extends Animal1 { @Override public void eat() { System.out.println("猫吃鱼"); } /*public void eat() { System.out.println("猫吃鱼"); }*/ } abstract class Dog1 extends Animal1 { /*public void eat() { System.out.println("狗吃屎"); }*/ }
3.2 抽象类的特色
抽象方法只能在抽象类里面
抽象类和抽象方法必须被abstract修饰
抽象类不能建立对象(不能实例化)
抽象类中能够有非抽象的方法
抽象类和类的关系也是继承
一个类继承了抽象类要么重写全部的抽象方法,要么他本身是抽象类
3.2.1 案例代码十二
package com.gao_01; /* * 抽象类的特色: * 抽象方法只能在抽象类里面 * 抽象类和抽象方法必须被abstract修饰 * 抽象类不能建立对象(不能实例化) * 抽象类中能够有非抽象的方法 * 抽象类和类的关系也是继承 * 一个类继承了抽象类要么重写全部的抽象方法,要么他本身是抽象类 */ public class AbstractDemo2 { public static void main(String[] args) { //Animal a = new Animal(); } } abstract class Animal2 { public abstract void eat(); public void run() { } } class Cat2 extends Animal2 { @Override public void eat() { // TODO Auto-generated method stub } }
3.3 抽象类的成员的特色
A:抽象类的成员特色:
成员变量
能够有成员变量
能够有常量
成员方法
能够有抽象方法
能够有非抽象方法
构造方法
能够有构造方法的,须要对抽象类的成员变量进行初始化
3.3.1 案例代码十三
package com.gao_01; /* * 抽象类的成员特色: * 成员变量 * 能够有成员变量 * 能够有常量 * 成员方法 * 能够有抽象方法 * 能够有非抽象方法 * 构造方法 * 能够有构造方法的,须要对抽象类的成员变量进行初始化 * * final:修饰类、成员变量、成员方法 */ public class AbstractDemo3 { public static void main(String[] args) { Dog d = new Dog(); d.barking(); } } abstract class Animal { String name = "哮天犬"; final int num = 10; public Animal() { System.out.println("我是抽象类的构造方法"); } public abstract void eat(); public void run() {} } class Dog extends Animal { public void barking() { System.out.println(name); System.out.println(num); } @Override public void eat() { // TODO Auto-generated method stub } }
3.4 抽象类案例
3.4.1 老师案例
老师类:
属性:姓名,年龄,性别
行为:讲课
基础班老师:
属性:姓名,年龄,性别
行为:讲基础班课程
就业班老师:
属性:姓名,年龄,性别
行为:讲就业班课程
package com.gao_02; /* * 基础班老湿,就业班老湿 * * 共性: * 属性 姓名,年龄,性别 * 行为 讲课,唱歌 */ public class AbstractTest { public static void main(String[] args) { BasicTeacher bt = new BasicTeacher(); bt.name = "老师一"; bt.teach(); JobTeacher jt = new JobTeacher(); jt.name = "老师二"; jt.teach(); } } abstract class Teacher { String name;//姓名 int age;//年龄 String gender;//性别 //讲课 public abstract void teach(); } class BasicTeacher extends Teacher { @Override public void teach() { System.out.println(name + "讲基础班课程"); } } class JobTeacher extends Teacher { @Override public void teach() { System.out.println(name + "讲就业班课程"); } }
3.4.2 雇员案例
雇员类:
属性:姓名,编号,薪水
行为:工做
程序员:
属性:姓名,编号,薪水
行为:写代码工做
经理:
属性:姓名,编号,薪水,奖金
行为:盯着程序员写代码工做
package com.gao_02; /* * 雇员(Employee)示例: 需求: 公司中 程序员(programmer)有姓名(name),工号(id),薪水(pay),工做内容(work)。 项目经理(Manager)除了有姓名(name),工号(id),薪水(pay),还有奖金(bonus),工做内容(work) 员工: 属性 name,id,pay 行为 work */ public class AbstractTest2 { public static void main(String[] args) { Programmer p = new Programmer(); p.work(); Manager m = new Manager(); m.work(); } } abstract class Employee { String name;//姓名 String id;//id double pay;//薪水 //工做 public abstract void work(); } class Programmer extends Employee { @Override public void work() { System.out.println("写代码"); } } class Manager extends Employee { byte bonus; @Override public void work() { System.out.println("盯着程序员写代码"); } }
3.4.3 技师案例
技师:
属性:姓名,年龄
行为:服务
足疗技师:
属性:姓名,年龄
行为:按按脚揉揉肩
其它技师:
属性:姓名,年龄
行为:你懂的
package com.gao_02; /* * 足疗店 * 技师 * 足疗技师 * 其余技师 * * 共性: * 属性 姓名,年龄 * 行为 服务 */ public class AbstractTest3 { public static void main(String[] args) { 足疗技师 zl = new 足疗技师(); zl.service(); 其余技师 qt = new 其余技师(); qt.service(); } } abstract class 技师 { String name;//姓名 int age;//年龄 //服务 public abstract void service(); } class 足疗技师 extends 技师 { @Override public void service() { System.out.println("按按脚揉揉肩"); } } class 其余技师 extends 技师 { @Override public void service() { System.out.println("你懂的"); } }
3.5 抽象类的细节
A:抽象类关键字abstract能够和哪些关键字共存?
1.private:
私有的方法子类是没法继承到的,也不存在覆盖,而abstract和private一块儿使用修饰方法,abstract既要子类去实现这个方法,而private修饰子类根本没法获得父类
这个方法。互相矛盾。
2.final:
抽象类不能和final共存,由于抽象类自身没法建立对象,咱们须要经过子类建立对象,一旦抽象类使用final关键字,那么抽象类就没有子类
抽象方法不能和final共存,由于抽象方法后期须要被子类重写,一旦加final没法重写
3.static:
抽象方法不能和static关键字共存,由于一旦加static咱们就能够经过类名直接访问抽象方法,因为抽象方法没有方法体,没有任何意义,也不容许这样作
B:抽象类中是否能够不定义抽象方法?
是能够的,那这个抽象类的存在到底有什么意义呢?不让该类建立对象,方法能够直接让子类去使用
C:抽象类是否有构造函数?
有,抽象类的构造函数,是由子类的super语句来调用,用于给抽象类中的成员初始化