day10.面向对象
某IT公司有多名员工,按照员工负责的工作不同,进行了部门的划分(研发部、维护部)。
研发部(Developer)根据所需研发的内容不同,又分为 JavaEE工程师 、Android工程师 ;
维护部(Maintainer)根据所需维护的内容不同,又分为 网络维护工程师(Network) 、硬件维护工程师(Hardware) 。
公司的每名员工都有他们自己的员工编号、姓名,并要做他们所负责的工作。
工作内容:
- JavaEE工程师: 员工号为xxx的 xxx员工,正在研发电商网站
- Android工程师:员工号为xxx的 xxx员工,正在研发电商的手机客户端软件
- 网络维护工程师:员工号为xxx的 xxx员工,正在检查网络是否畅通
- 硬件维护工程师:员工号为xxx的 xxx员工,正在修复电脑主板
请根据描述,完成员工体系中所有类的定义,并指定类之间的继承关系。进行XX工程师类的对象创建,完成工作方法的调用。
public abstract class Employee {
private int id;
private String name;
public Employee() {
}
public Employee(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract void work();
}
public abstract class Developer extends Employee{
public Developer() {
}
public Developer(int id, String name) {
super(id, name);
}
}
public class JavaEE extends Developer{
public JavaEE() {
}
public JavaEE(int id, String name) {
super(id, name);
}
@Override
public void work() {
System.out.println("员工号为:"+this.getId()+"的"+this.getName()+"正在研发电商网站");
}
}
public class Test01 {
public static void main(String[] args) {
JavaEE javaEE = new JavaEE(1, "涛哥");
javaEE.work();
}
}

1.封装:将细节隐藏起来(不让外界直接使用),对外提供一套公共的接口(让外界通过这个公共接口间接调用隐藏起来的细节)
a.有代表性的关键字:private -> 私有化
b.get/set 方法 -> 提供的公共接口
c.构造:
无参构造:new 对象
有参构造:new 对象的同时,为属性赋值
2.继承:将子类中共有的内容抽取到父类中,子类直接继承父类,就可以直接使用父类中非私有成员
a.关键字:extends
b.成员变量:看等号左边是谁
成员方法:看 new 的是谁
3.抽象:定义抽象类,里面定义抽象方法
a.定义子类,继承抽象父类
b.重写所有抽象方法
c.创建子类对象,调用重写的方法
今日重点:
1.会定义接口,实现接口
2.会在接口中定义抽象方法
3.知道多态的前提
4.知道多态前提下成员访问特点
5.知道多态的好处和弊端
6.知道如何向下转型,调用子类特有功能
7.知道如何判断类型 -> instanceof
第一章.接口
1.接口的介绍

2.接口的定义以及使用
1.接口:是一种规则,一种标准
2.既然是一种标准,里面的成员就非常单一
3.jdk8之前:
a.抽象方法:不带abstract,默认也有
b.成员变量:必须是带public static final的,不写也有
4. jdk8开始:多了两个
a.默认方法:带default关键字的
b.静态方法:带static的方法
5.jdk9开始:多了一个
a.私有方法:带private
6.接口的定义:interface
public interface 接口名{}
7.实现接口: implements
实现类 implements 接口名{}
1.创建接口
2.创建实现类,实现此接口
3.在实现类中重写接口中所有的抽象方法
4.创建实现类对象(接口不能new对象),调用重写的方法
public interface USB {
public abstract void open();
public abstract void close();
}
public class Mouse implements USB{
@Override
public void open() {
System.out.println("鼠标打开");
}
@Override
public void close() {
System.out.println("鼠标关闭");
}
}
public class Test01 {
public static void main(String[] args) {
Mouse mouse = new Mouse();
mouse.open();
mouse.close();
}
}
3.接口中的成员
3.1 抽象方法
1.定义格式:
public abstract 返回值类型 方法名(形参);
2.特点:
不写abstract关键字默认也有
3.实现:
在实现类中重写
public interface USB {
public abstract void open();
void close();
}
public class Mouse implements USB {
@Override
public void open() {
System.out.println("鼠标打开");
}
@Override
public void close() {
System.out.println("鼠标关闭");
}
}
public class Test01 {
public static void main(String[] args) {
Mouse mouse = new Mouse();
mouse.open();
mouse.close();
}
}
3.2 默认方法
1.定义格式:
public default 返回值类型 方法名(形参){
方法体
return 结果
}
2.使用:
a.可重写,可不重写
b.创建实现类对象,调用默认方法
public interface USB {
//默认方法
public default void methodDef(){
System.out.println("我是接口中的默认方法");
}
}
public class Mouse implements USB{
@Override
public void methodDef(){
System.out.println("我是重写的接口中的默认方法");
}
}
public class Test01 {
public static void main(String[] args) {
Mouse mouse = new Mouse();
mouse.methodDef();
}
}
3.3 静态方法
1.定义格式:
修饰符 static 返回值类型 方法名(形参){
方法体
return 结果
}
2.实现:
接口名直接调用
public interface USB {
//默认方法
public default void methodDef(){
System.out.println("我是接口中的默认方法");
}
//静态方法
public static void methodStatic(){
System.out.println("我是接口中的静态方法");
}
}
public class Test01 {
public static void main(String[] args) {
Mouse mouse = new Mouse();
mouse.methodDef();
System.out.println("=============");
USB.methodStatic();
}
}
默认方法和静态方法:如果我们将来需要临时加一个功能,但是这个功能用不了几行代码就能完成,我们就没必要先定义抽象方法,然后再在实现类中重写了,此时我们就可以直接在接口中定义默认方法或者静态方法
3.4 成员变量
1.格式:public static final 数据类型 变量名 = 值
2.特点:不写 public static final 默认也有
3.没学的关键字: final -> 代表最终的 -> 被final修饰的变量不能二次赋值,我们认为是常量
4.调用:接口名直接调用
5.注意:
a.被static final修饰的变量需要手动赋值
b.习惯上将static final修饰的变量名大写
public interface USB {
//成员变量
public static final int NUM = 10;
int NUM1 = 100;
}
public class Test01 {
public static void main(String[] args) {
System.out.println(USB.NUM);
System.out.println(USB.NUM1);
}
}
3.5.私有方法
1.格式:
private 返回值类型 方法名(形参){
方法体;
return 结果;
}
public interface USB {
private void methodPrivate(){
System.out.println("接口中的私有方法");
}
public default void methodDef(){
methodPrivate();
}
}
public class Mouse implements USB{
}
public class Test01 {
public static void main(String[] args) {
Mouse mouse = new Mouse();
mouse.methodDef();
}
}
特殊语法:
接口名.super.方法名()
public class 实现类 implements 接口 A,接口 B{
public void method(){
接口名.super.方法名()
}
}
public interface 接口 A{
default void method(){
}
}
public interface 接口 B{
default void method(){
}
}
4.接口的特点
1.接口可以多实现:一个类可以实现一个或者多个接口
public class InterfaceImpl implements InterfaceA,InterfaceB{}
2.接口可以多继承:一个接口可以继承一个或者多个接口
public interface InterfaceC extends InterfaceA,InterfaceB{}
3.一个类可以继承一个父类的同时实现一个或者多个接口
public class Zi extends Fu implements InterfaceA,InterfaceB{}
当一个类实现多个接口时,如果接口中的抽象方法有重名且参数一样的,只重写一次
javapublic interface InterfaceA { public abstract void method(); }
javapublic interface InterfaceB { public abstract void method(); }
javapublic class InterfaceImpl implements InterfaceA,InterfaceB{ @Override public void method() { System.out.println("我是重写的method方法"); } }
当一个类实现多个接口时,如果默认方法有重名的,参数一样,默认方法必须要重写一次
javapublic interface InterfaceA { public abstract void method(); public default void methodDef() { System.out.println("InterfaceA.methodDef()"); } }
javapublic interface InterfaceB { public abstract void method(); public default void methodDef() { System.out.println("InterfaceB.methodDef()"); } }
javapublic class InterfaceImpl implements InterfaceA,InterfaceB{ @Override public void method() { System.out.println("我是重写的method方法"); } @Override public void methodDef() { System.out.println("重写的methodDef方法"); } }
5.接口和抽象类的区别
相同点:
a.都位于继承的顶端,用于被其他类实现或者继承
b.都不能new
c.都包含抽象方法,其子类都必须重写这些抽象方法
不同点:
a.抽象类:一般作为父类使用,可以有成员变量,构造,成员方法,抽象方法等
b.接口:成员单一,一般抽取接口,抽取的都是方法,是功能的大集合
c.类不能多继承,接口可以

第二章.多态
面向对象三大特征: 封装 继承 [多态]
1.多态的介绍
1.怎么学多态:
a.前提 b.如何new对象 c.多态好处
2.前提:
a.必须有子父类继承关系或者接口实现关系
b.必须有方法的重写(没有方法的重写,多态没有任何意义)
c.new对象 -> 父类引用指向子类对象 -> Fu fu = new Zi()
2.多态的基本使用
1.定义一个父类或者接口
2.定义一个子类或者实现类去继承或者实现父类或接口
3.重写父类或者接口中的抽象方法
4.创建对象,调用重写的方法
public class Animal {
public void eat(){
System.out.println("动物要吃饭");
}
}
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗啃骨头");
}
/**
* 特有功能
*/
public void lookHome(){
System.out.println("狗看家");
}
}
public class Test01 {
public static void main(String[] args) {
//原始形式
Dog dog = new Dog();
dog.eat();
dog.lookHome();
System.out.println("===================");
//多态形式
Animal animal = new Dog();
animal.eat();
//animal.lookHome();多态前提下,不能直接调用子类特有方法
}
}
3.多态的条件下成员的访问特点
3.1 成员变量
看等号左边是谁,先调用谁中的成员变量
public class Fu {
int num = 100;
}
public class Zi extends Fu{
int num = 10;
}
public class Test01 {
public static void main(String[] args) {
//多态形式
Fu fu = new Zi();
System.out.println(fu.num);
}
}
3.2 成员方法
看new的是谁,先调用谁中的方法,子类没有,找父类
public class Fu {
int num = 100;
public void method(){
System.out.println("我是父类中的method方法");
}
}
public class Zi extends Fu{
int num = 10;
@Override
public void method(){
System.out.println("我是子类中的method方法");
}
}
public class Test01 {
public static void main(String[] args) {
//多态形式
Fu fu = new Zi();
System.out.println(fu.num);
fu.method();
}
}
4.多态的好处(为什么学多态)
1.问题:
我们按照原始方式创建对象,既可以调用继承过来的,还能调用重写的,还能调用特有的;但是我们用多态形式new对象,不能调用子类特有功能,只能调用重写的方法,那么为啥还要用多态呢?
2.原始方式:
a.好处:既可以调用继承过来的,还能调用重写的,还能调用特有的
b.坏处:扩展性差
3.多态方式:
a.好处:扩展性强
b.坏处:不能直接调用子类特有功能
public class Animal {
public void eat(){
System.out.println("动物要干饭");
}
}
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃屎");
}
//特有方法
public void lookHome(){
System.out.println("狗会看家");
}
}
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
//特有方法
public void catchMouse(){
System.out.println("抓老鼠");
}
}
public class Test01 {
public static void main(String[] args) {
//原始方式创建对象
Dog dog = new Dog();
dog.eat();
dog.lookHome();
System.out.println("=================");
//多态方式创建对象
Animal animal = new Dog();
animal.eat();
//animal.lookHome();不能直接调用子类特有功能
}
}
public class Test02 {
public static void main(String[] args) {
Dog dog = new Dog();
method(dog);
Cat cat = new Cat();
method(cat);
/*Pig pig = new Pig();
method(pig);
Duck duck = new Duck();
method(duck);*/
}
public static void method(Dog dog){
dog.eat();
}
public static void method(Cat cat){
cat.eat();
}
/*public static void method(Pig pig){
pig.eat();
}*/
}
public class Test03 {
public static void main(String[] args) {
/* Animal animal = new Dog();
animal.eat();
*//*
好比是:
double b = 10;
b = 2.5;
*//*
animal = new Cat();
animal.eat();*/
Dog dog = new Dog();
method(dog);
Cat cat = new Cat();
method(cat);
}
/**
* 形参位置设置的是父类类型
* 那么就可以接收任意它的子类对象
* 接收哪个子类对象,就会指向哪个子类对象
* 就会调用哪个子类对象重写的方法
* 扩展性好强
* @param animal
*/
public static void method(Animal animal){//Animal animal = dog Animal animal = cat
animal.eat();
}
}
5.多态中的转型
5.1 向上转型
默认的: 父类引用指向子类对象
5.2 向下转型
1.将父类类型转成子类类型 -> 强转
2.向下转型的作用:
调用子类特有方法
3.使用:
Fu fu = new Zi();
Zi zi = (Zi)fu;
public class Animal {
public void eat(){
System.out.println("动物要干饭");
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃屎");
}
//特有方法
public void lookHome(){
System.out.println("狗会看家");
}
}
public class Test01 {
public static void main(String[] args) {
//向上转型
Animal animal = new Dog();
animal.eat();
//向下转型
Dog dog = (Dog) animal;
dog.lookHome();
}
}
6.转型可能会出现的问题
1.类型转换异常:
ClassCastException
2.原因:
强转的时候等号左右两边类型不一致
3.判断: instanceof -> 判断类型
a.格式1: 对象名 instanceof 类型 -> 判断instanceof前面的对象是否属于关键字后面的类型
b.格式2: 对象名 instanceof 类型 对象名 -> 会自动强转
public class Animal {
public void eat(){
System.out.println("动物要干饭");
}
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
//特有方法
public void catchMouse(){
System.out.println("抓老鼠");
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃屎");
}
//特有方法
public void lookHome(){
System.out.println("狗会看家");
}
}
public class Test01 {
public static void main(String[] args) {
Dog dog = new Dog();
method(dog);
Cat cat = new Cat();
method(cat);
}
public static void method(Animal animal){//Animal animal = dog Animal animal = cat
//animal.eat();
/*
向下转型
调用method方法,传递Cat对象,animal实际上接收的是Cat对象
将接收到Cat对象的animal强转成Dog类型
实际上类型是不一样的
格式1: 对象名 instanceof 类型 -> 判断instanceof前面的对象是否属于关键字后面的类型
*/
/* if (animal instanceof Dog){
Dog dog = (Dog) animal;
dog.lookHome();
}
if (animal instanceof Cat){
Cat cat = (Cat) animal;
cat.catchMouse();
}*/
//格式2: 对象名 instanceof 类型 对象名 -> 会自动强转
if (animal instanceof Dog dog){
dog.lookHome();
}
if (animal instanceof Cat cat){
cat.catchMouse();
}
}
}
7.综合练习
定义笔记本类,具备开机,关机和使用USB设备的功能。具体是什么USB设备,笔记本并不关心,只要符合USB规格的设备都可以。鼠标和键盘要想能在电脑上使用,那么鼠标和键盘也必须遵守USB规范,不然鼠标和键盘生产出来无法使用;
进行描述笔记本类,实现笔记本使用USB鼠标、USB键盘
- USB接口,包含开启功能、关闭功能
- 笔记本类,包含运行功能、关机功能、使用USB设备功能
- 鼠标类,要符合USB接口
- 键盘类,要符合USB接口
public interface USB {
void open();
void close();
}
public class Mouse implements USB{
@Override
public void open() {
System.out.println("鼠标开启");
}
@Override
public void close() {
System.out.println("鼠标关闭");
}
//特有方法
public void click(){
System.out.println("鼠标点击");
}
}
public class KeyBoard implements USB{
@Override
public void open() {
System.out.println("键盘开启");
}
@Override
public void close() {
System.out.println("键盘关闭");
}
//特有方法
public void input(){
System.out.println("键盘输入");
}
}
public class Computer {
public void start(){
System.out.println("开机");
}
/**
* 传递mouse -> USB usb = mouse -> 多态
* 传递keyBoard -> USB usb = keyBoard -> 多态
* @param usb
*/
public void useUSB(USB usb){
usb.open();
usb.close();
if (usb instanceof Mouse mouse){
mouse.click();
}
if (usb instanceof KeyBoard keyBoard){
keyBoard.input();
}
}
public void stop(){
System.out.println("关机");
}
}
public class Test01 {
public static void main(String[] args) {
Computer computer = new Computer();
Mouse mouse = new Mouse();
KeyBoard keyBoard = new KeyBoard();
computer.start();
computer.useUSB(mouse);
computer.useUSB(keyBoard);
computer.stop();
}
}

第三章.权限修饰符
1 概述
在 Java 中提供了四种访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限,
- public:公共的,最高权限,被 public 修饰的成员,在哪里都能访问
- protected:受保护的
- default::默认的 注意 不写权限修饰符就是默认权限,不能直接把 default 写出来
- private:私有的,只能在自己的类中直接访问
2 不同权限的访问能力
public | protected | default(空的) | private | |
---|---|---|---|---|
同类 | yes | yes | yes | yes |
同包不同类 | yes | yes | yes | no |
不同包子父类 | yes | yes | no | no |
不同包非子父类 | yes | no | no | no |
public 具有最大权限,private 有最小权限
编写代码时,如果没有特殊的考虑,建议这样使用权限:
属性用private -> 封装思想
构造用public -> 便于new对象
方法用public -> 便于调用
第四章.final 关键字
1.概述:代表的是最终的
2.使用:
修饰类
修饰方法
修饰对象
修饰局部变量
修饰成员变量
1.final 修饰类
1.格式:
public final class 类名{}
2.特点:
不能被继承
public final class Animal {
}
public class Dog /*extends Animal*/{
}
2.final 修饰方法
1.格式:
修饰符 final 返回值类型 方法名(形参){
方法体
return 结果
}
2.特点:
a.不能被重写
b.不能和abstract一起使用
public abstract class Animal {
public final void eat(){
}
//public final abstract void drink();
}
public class Dog extends Animal{
/* @Override
public void eat() {
System.out.println("狗吃骨头");
}*/
}
3.final 修饰局部变量
1.格式:
final 数据类型 变量名 = 值
2.特点:
不能被二次赋值
public class Test01 {
public static void main(String[] args) {
final int i = 10;
//i = 20;
}
}
4.final 修饰对象
1.格式:
final 类名 对象名 = new 类名()
2.特点:
地址值不能改变,但是属性值可以改变
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class Test02 {
public static void main(String[] args) {
final Person p1 = new Person("jack", 20);
System.out.println(p1);//地址值
//p1 = new Person("rose", 18);
//System.out.println(p1);//地址值
p1.setName("rose");
System.out.println(p1.getName());
}
}
5.final 修饰成员变量
1.格式:
final 数据类型 变量名 = 值
2.特点:
a.被final修饰的成员变量不能被二次赋值
b.被final修饰的成员变量手动赋值
public class Student {
final String name = "张三";
public Student() {
}
/* public Student(String name) {
this.name = name;
}
public void setName(String name){
this.name = name;
}*/
public String getName() {
return name;
}
}