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 > private
public | 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.132741228718345
final关键字是 最终
的意思,可以修饰类,变量和方法
该类就不能被继承
变量会变为常量,只能赋值一次,之后就不能改变了, final修饰的变量称为常量,常量名我们都大写,常量一般我们会声明为static
成员变量:在定义的同时必须给出初始值。
局部变量:可以在使用之前赋值
final修饰的方法,子类是不能重写该方法的!
Cannot override the final method from Person