
Lecture:波哥
Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机,Java 仍是企业和开发人员的首选开发平台。
格式
class 子类名称 extends 父类名称{
}被继承的这个类称为父类、 基类或者 超类
继承的这个类称为子类 或者 派生类
父类:
package com.bobo.oop08;
/**
* 这是个Person类,抽取了 Student、Doctor、Police三个类的公共代码
* @author dpb
*
*/
public class Person {
public String name;
public int age;
public String gender;
public void sleep() {
System.out.println("sleep .... ");
}
}Student,Police,Doctor三个子类
package com.bobo.oop08;
/**
* 这是一个学生类
* @author dpb
*
*/
public class Student extends Person{
public String stuNo; // 学生编号
public void study(){
System.out.println("study ....");
}
}Police
package com.bobo.oop08;
/**
* 这是一个警察类
* @author dpb
*
*/
public class Police extends Person{
public String policeNo; // 警员编号
/**
* 抓坏人的方法
*/
public void catchBadGuys(){
System.out.println(".....");
}
}Doctor
package com.bobo.oop08;
/**
* 这是一个医生类
* @author dpb
*
*/
public class Doctor extends Person{
public String doctorNum; // 医生编号
public String department; // 部门
public void savePeople(){
System.out.println("save ...");
}
}开发设计思想:高内聚低耦合(尽量在一个类里面内聚,类和类之间的关系尽量保持独立)
继承后耦合性提高,牵一发动全身, 这个缺点不能改进,在Java中里面尽量不要使用继承

继承的本质是什么? --> 简化代码
1、定义一个人类(姓名,年龄,性别,吃,睡) ,学生类继承人类(学号,班级,课程) ,老师类继承人类(工号,教龄,教书)
package com.bobo.oop09;
/**
* 姓名,年龄,性别,吃,睡
* @author dpb
*
*/
public class Person {
public String name;
public int age;
public String gender;
public void eat(){
System.out.println("Person.eat() ....");
}
public void sleep(){
System.out.println("Person.sleep() ...");
}
}package com.bobo.oop09;
/**
* 老师类继承人类(工号,教龄,教书)
* @author dpb
*
*/
public class Teacher extends Person{
public String workNum;
public int schoolAge;
public String course;
}package com.bobo.oop09;
/**
* 学生类继承人类(学号,班级,课程)
* @author dpb
*
*/
public class Student extends Person{
public String stuNo;
public String className;
public String course;
} super关键字可以理解为 父类对象,this关键字表示当前对象
当一个属性的使用没有添加this或者super关键字,那么他的查找顺序是 局部变量–>成员变量–>父类变量 如果还没有找到那么就会包编译异常。
被this修饰的变量,如果本类的成员变量中没有找到,同样也会去父类中查找
被super修饰的变量只会从父类中查找,如果父类中没有,而子类中存在,同样会报编译错误
super和this关键字访问成员的区别
成员变量
成员方法:
构造方法:
super和this方法构造方法都必须出现在构造方法的第一句,this和super在方法构造方法的时候,二者是不能共存
static静态的上下文都是不能出现this和super的
案例代码:
package com.bobo.oop01;
public class Son extends Father{
/**
* 在子类中定义了一个和父类中同名的属性
* 子类中定义的同名的属性会覆盖掉父类中的属性
*/
public int num = 30;
public void show(){
// 局部变量会覆盖掉成员变量
//int num = 40;
// 输出局部变量
System.out.println("num:" + num);
// 输出成员变量
System.out.println("num:" + this.num);
// 输出父类的成员变量
System.out.println("num:" + super.num);
System.out.println(super.getAge());
eat();
}
public Son(){
// 在构造方法中,默认都会添加一句 super(); 而且必须是第一行
// Constructor call must be the first statement in a constructor
System.out.println("Son 子类构造器执行了...");
}
public Son(int num){
this();
//super(); 会在无参构造方法中执行 super(); 此处如果再执行一次就会出现两次初始化父类中成员变量的情况
}
}package com.bobo.oop01;
public class Father {
public int num = 10;
private int age ;
public void eat(){
System.out.println("Father.eat ...");
}
public Father(){
System.out.println("Father 。。。。构造器执行了");
}
public int getAge() {
return age;
}
}package com.bobo.oop01;
public class OOPDemo01 {
public static void main(String[] args) {
Son son = new Son();
son.show();
}
}作用:表示被修饰的元素的访问权限
访问权限修饰符有四个: public protected [default] private
访问权限修饰符可以修饰的元素:
四个修饰符的特点
Java中的封装就是通过访问权限修饰符来实现的
访问权限修饰符的宽严的关系
public > protected > default > privatepublic | protected | [default] | private | |
|---|---|---|---|---|
同一类中 | √ | √ | √ | √ |
同一包中子类、其它类 | √ | √ | √ | |
不同包中子类 | √ | √ | ||
不同包中其它类 | √ |
如果从父类继承的方法不能满足子类的需求的情况下,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写,子类中出现了和父类中一模一样的方法声明,,也称为方法的覆盖或者方法的复写。
方法的重写的规则
方法重写的注意事项:
面试题:
重载和重写的区别:
重载的定义:
位置 | 方法名 | 参数列表 | 返回值 | 访问权限修饰符 | |
|---|---|---|---|---|---|
方法重写 | 子类 | 相同 | 相同 | 相同或者子类 | 不能严于父类 |
方法重载 | 同类 | 相同 | 不相同 | 没有关系 | 没有关系 |
(1)设计一个User类,其中包括用户名、口令等属性以及构造方法(至少重载2个)。获取和设置口令的方法,显示和修改用户名的方法等。编写应用程序测试User类。
package com.bobo.oop05;
public class OOPDemo01 {
/**
* 设计一个User类,其中包括用户名、口令等属性以及构造方法(至少重载2个)。
* 获取和设置口令的方法,显示和修改用户名的方法等。编写应用程序测试User类。
* @param args
*/
public static void main(String[] args) {
User user = new User("admin","123");
System.out.println(user.getUserName());
System.out.println(user.getPassword());
}
}
class User{
private String userName;
private String password;
public User(){
}
public User(String userName,String password){
this.userName = userName;
this.password = password;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}(2)定义一个Student类,其中包括用户名、密码、姓名、性别、出生年月等属行以及init()——初始化各属性、display()——显示各属性、modify()——修改姓名等方法。实现并测试这个类。
package com.bobo.oop05;
public class OOPDemo02 {
/**
* 定义一个Student类,其中包括用户名、密码、姓名、性别、出生年月等属行
* 以及init()——初始化各属性、display()——显示各属性、
* modify()——修改姓名等方法。实现并测试这个类。
* @param args
*/
public static void main(String[] args) {
Student stu = new Student();
// 初始成员变量
stu.init("root", "123", "波波老师", "男", "198704");
// 打印信息
stu.display();
// 修改姓名
stu.modify("张三");
// 打印信息
stu.display();
}
}
class Student{
private String userName;
private String password;
private String name;
private String gender;
private String birth;
/**
* 初始化成员变量
* @param userName
* @param password
* @param name
* @param gender
* @param birth
*/
public void init(String userName,String password
,String name,String gender,String birth)
{
this.userName = userName;
this.password = password;
this.name = name;
this.gender = gender;
this.birth = birth;
}
/**
* 打印各个属性的方法
*/
public void display(){
System.out.println("userName=" + this.userName
+ "\t password=" + this.password
+ "\t name=" + this.name
+ "\t gender=" + this.gender
+ "\t birth="+this.birth);
}
/**
* 修改姓名的方法
* @param name
*/
public void modify(String name){
this.name = name;
}
}(3)从上题的Student类中派生出Granduate(研究生)类,添加属性:专业subject、导师adviser。重载相应的成员方法。并测试这个类。
package com.bobo.oop05;
public class OOPDemo02 {
/**
* 定义一个Student类,其中包括用户名、密码、姓名、性别、出生年月等属行
* 以及init()——初始化各属性、display()——显示各属性、
* modify()——修改姓名等方法。实现并测试这个类。
* @param args
*/
public static void main(String[] args) {
/*Student stu = new Student();
// 初始成员变量
stu.init("root", "123", "波波老师", "男", "198704");
// 打印信息
stu.display();
// 修改姓名
stu.modify("张三");
// 打印信息
stu.display();*/
Granduate g = new Granduate();
g.init("root", "123", "波波老师", "男", "198704","医学专业","xxxx");
g.display();
g.modify("aaa");
g.display();
}
}
class Student{
public String userName;
public String password;
public String name;
public String gender;
public String birth;
/**
* 初始化成员变量
* @param userName
* @param password
* @param name
* @param gender
* @param birth
*/
public void init(String userName,String password
,String name,String gender,String birth)
{
this.userName = userName;
this.password = password;
this.name = name;
this.gender = gender;
this.birth = birth;
}
/**
* 打印各个属性的方法
*/
public void display(){
System.out.println("userName=" + this.userName
+ "\t password=" + this.password
+ "\t name=" + this.name
+ "\t gender=" + this.gender
+ "\t birth="+this.birth);
}
/**
* 修改姓名的方法
* @param name
*/
public void modify(String name){
this.name = name;
}
}
/**
* 从上题的Student类中派生出Granduate(研究生)类,
* 添加属性:专业subject、导师adviser。重载相应的成员方法。并测试这个类。
* @author dpb
*
*/
class Granduate extends Student{
public String subject;
public String adviser;
/**
* 重载的init方法 实现子类成员变量的初始化和父类中的成员变量的初始化操作
* @param subject
* @param adviser
*/
public void init(String userName,String password
,String name,String gender,String birth,String subject,String adviser){
super.init(userName, password, name, gender, birth);
this.subject = subject;
this.adviser = adviser;
}
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("userName=" + this.userName
+ "\t password=" + this.password
+ "\t name=" + this.name
+ "\t gender=" + this.gender
+ "\t birth="+this.birth
+ "\t subject=" + this.subject
+ "\t adviser=" + this.adviser);
}
}(4)创建两个具有继承结构的两个类,父类和子类均有自己的静态代码块、构造方法。观察他们的运行顺序。
package com.bobo.oop05;
public class OOPDemo03 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Son son1 = new Son();
Son son2 = new Son();
Son son3 = new Son();
}
}
/**
* 创建两个具有继承结构的两个类,
* 父类和子类均有自己的静态代码块、构造方法。观察他们的运行顺序。
* @author dpb
*
*/
class Father{
static{
System.out.println("father ... 静态代码块");
}
public Father(){
System.out.println("father 构造方法...");
}
}
class Son extends Father{
static{
System.out.println("son .... 静态代码块");
}
public Son(){
System.out.println("son ... 构造方法");
}
}输出结果
father ... 静态代码块
son .... 静态代码块
father 构造方法...
son ... 构造方法
father 构造方法...
son ... 构造方法
father 构造方法...
son ... 构造方法(5)编写一个汽车类Car 编写一个宝马类BMW 继承Car 编写一个奔驰类Benz 继承Car 在三个类中都有一个run方法,表示不同车在跑 编写一个人类Person,不同的对象有不同的车
package com.bobo.oop05;
public class OOPDemo04 {
/**
* 编写一个汽车类Car
编写一个宝马类BMW 继承Car
编写一个奔驰类Benz 继承Car
在三个类中都有一个run方法,表示不同车在跑
编写一个人类Person,不同的对象有不同的车
* @param args
*/
public static void main(String[] args) {
Car car = new Car();
BMW bmw = new BMW();
Benz benz = new Benz();
Person p1 = new Person(car);
Person p2 = new Person(bmw);
Person p3 = new Person(benz);
}
}
class Car{
public void run(){
System.out.println("汽车在运行...");
}
}
class BMW extends Car{
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("宝马车在运行...");
}
}
class Benz extends Car{
@Override
public void run() {
System.out.println("奔驰车在运行...");
}
}
/**
* 不同的对象又不同的车
* @author dpb
*
*/
class Person{
public Car car;
public Person(Car car){
this.car = car;
}
}(6)有农民(farmer),教师(teacher),科学家(scientist),服务生(attendant),其中农民,服务生只有基本工资.教师除基本工资外,还有课酬(元/天),科学家除基本工资外,还有年终奖,请你写出相关类,将各种类型的员工的全年工资打印出来
package com.bobo.oop05;
public class OOPDemo05 {
/**
* 有农民(farmer),教师(teacher),科学家(scientist),服务生(attendant),
* 其中农民,服务生只有基本工资.教师除基本工资外,还有课酬(元/天),
* 科学家除基本工资外,还有年终奖,
* 请你写出相关类,将各种类型的员工的全年工资打印出来
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
// 农民
class Farmer{
public double basePay; // 基本工资
public void printYearSalary(){
System.out.println("Farmer全年的工资:" + basePay * 12);
}
}
class Attendant{
public double basePay; // 基本工资
public void printYearSalary(){
System.out.println("Attendant全年的工资:" + basePay * 12);
}
}
class Teacher extends Farmer{
public double classFee; // 课时费(天)
@Override
public void printYearSalary() {
System.out.println("教师的全年工资:" + this.basePay*12 + classFee * 200);
}
}
class scientist extends Farmer{
public double yearBonus; // 年终奖
@Override
public void printYearSalary() {
System.out.println("科学家全年的收入是:" + this.basePay *12 + yearBonus);
}
}(7)完成如下功能 a.设计一个表示二维平面上点的类Point,包含有表示坐标位置的protected 类型的 成员变量x 和y,获取和设置x 和y 值的public 方法。 b.设计一个表示二维平面上圆的类Circle,它继承自类Point,还包含有表示圆半径 的protected 类型的成员变量r、获取和设置r 值的public 方法、计算圆面积的public 方 法。 c.设计一个表示圆柱体的类Cylinder,它继承自类Circle,还包含有表示圆柱体高的 protected 类型的成员变量h、获取和设置h 值的public 方法、计算圆柱体体积的public 方法。 d.建立Cylinder 对象,输出其轴心位置坐标、半径、面积、高及其体积的值。
package com.bobo.oop05;
public class OOPDemo06 {
/**
* 完成如下功能
a.设计一个表示二维平面上点的类Point,包含有表示坐标位置的protected 类型的
成员变量x 和y,获取和设置x 和y 值的public 方法。
b.设计一个表示二维平面上圆的类Circle,它继承自类Point,还包含有表示圆半径
的protected 类型的成员变量r、获取和设置r 值的public 方法、计算圆面积的public 方
法。
c.设计一个表示圆柱体的类Cylinder,它继承自类Circle,还包含有表示圆柱体高的
protected 类型的成员变量h、获取和设置h 值的public 方法、计算圆柱体体积的public
方法。
d.建立Cylinder 对象,输出其轴心位置坐标、半径、面积、高及其体积的值。
* @param args
*/
public static void main(String[] args) {
Cylinder c = new Cylinder();
c.x = 1;
c.y = 1;
c.r = 2;
c.h = 2;
System.out.println("圆心点的底坐标是(" +c.getX() + ","+c.getY()+")");
System.out.println("圆的半径是:" + c.getR());
System.out.println("圆的面积是:" + c.getArea());
System.out.println("圆柱体的体积是:" + c.getVolume());
}
}
/**
* a.设计一个表示二维平面上点的类Point,包含有表示坐标位置的protected 类型的
成员变量x 和y,获取和设置x 和y 值的public 方法。
* @author dpb
*
*/
class Point{
protected int x;
protected int y;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
/**
* b.设计一个表示二维平面上圆的类Circle,它继承自类Point,还包含有表示圆半径
的protected 类型的成员变量r、获取和设置r 值的public 方法、计算圆面积的public 方
法。
* @author dpb
*
*/
class Circle extends Point{
protected int r;
public int getR() {
return r;
}
public void setR(int r) {
this.r = r;
}
/**
* 获取圆面积的方法
* pi*r*r
* @return
*/
public double getArea(){
return Math.PI * this.r * this.r;
}
}
/**
* c.设计一个表示圆柱体的类Cylinder,它继承自类Circle,还包含有表示圆柱体高的
protected 类型的成员变量h、获取和设置h 值的public 方法、计算圆柱体体积的public
方法。
* @author dpb
*
*/
class Cylinder extends Circle{
protected int h;
public int getH() {
return h;
}
public void setH(int h) {
this.h = h;
}
/**
* 计算圆柱体 体积的方法
* 面积*高
* @return
*/
public double getVolume(){
return super.getArea() * this.h;
}
}输出的结果:
圆心点的底坐标是(1,1)
圆的半径是:2
圆的面积是:12.566370614359172
圆柱体的体积是:25.132741228718345final关键字是 最终 的意思,可以修饰类,变量和方法
该类就不能被继承
变量会变为常量,只能赋值一次,之后就不能改变了, final修饰的变量称为常量,常量名我们都大写,常量一般我们会声明为static
成员变量:在定义的同时必须给出初始值。
局部变量:可以在使用之前赋值

final修饰的方法,子类是不能重写该方法的!
Cannot override the final method from Person
