[JavaSE]面向对象篇(两万字超详细篇)

目录

一. 权限修饰符

二. 继承

2.1 前提

2.2 概述

三. 继承的初步使用

四. 方法重写

4.1 前提

4.2 概念

4.3 继承中方法的调用规则

4.4 方法继承的注意事项

五. 继承中的构造器

5.1 前提

5.2 子类中提供自己的构造方法

5.3 super和this

5.4 综合案例

六. 抽象类概述

6.1 概念

6.2 抽象方法

6.3 前提

6.4 抽象方法的定义

6.5 抽象类使用

七.抽象类的注意事项及模版设计模式

7.1 抽象类的注意事项

7.2 模版设计模式

八. static关键字

8.1 概念

8.2 静态成员访问方式

8.3 static修饰成员方法

8.4 static静态代码块

8.5 静态的访问规则

8.6 静态的应用场景

九. final关键字

9.1概念

9.2 使用

十. 接口的概述

10.1 概念

10.2 格式

十一. 接口的定义和使用

十二. 新版本的jdk中的接口的内容升级

12.1 默认方法

12.2 私有方法

12.3 静态方法

十三. 接口和抽象类的异同点

十四.综合案例

十五. 多态

1.1 概念

1.2 如何判别当前有没有使用多态

1.3 多态的好处

1.4 多态的弊端

十六. 内部类

1.1 概念

1.2 分类

1.3 匿名内部类和外部类的区别

1.4 匿名内部类的常见使用方式


        内容非常多而全面,建议使用目录

一. 权限修饰符

概念: 就是java中的一些关键字, 关键字的作用控制当前内容被访问的权限

分类:

public: 如果一个内容被public修饰, 谁来都能访问

protected:

默认(什么都不写):

private:如果一个内容被private修饰, 除了当前类自己, 谁来都不能访问

二. 继承

2.1 前提

public class Cat {
​
    //行为
    public void sleep(){
        System.out.println("睡觉觉~");
    }
​
    public void drink(){
        System.out.println("喝水水~");
    }
​
    public void eat(){
        System.out.println("吃鱼~");
    }
}
​
public class Dog {
​
    //行为
    public void sleep(){
        System.out.println("睡觉觉~");
    }
​
    public void drink(){
        System.out.println("喝水水~");
    }
​
    public void eat(){
        System.out.println("吃骨头~");
    }
}

上述两份代码中有重复的代码, 希望这些重复的代码不要多次书写,此时需要使用继承

2.2 概述

概念: 面向对象语言的三大特性之一, 描述的类与类之间的关系

作用: 当A类与B类有继承关系的时候, 那么A类中就可以使用B类中所有非私有的内容

格式: class A extends B{}

三. 继承的初步使用

//抽取cat类和dog类中共性的内容
public class Animal {
    public void sleep(){
        System.out.println("睡觉觉~");
    }
​
    public void drink(){
        System.out.println("喝水水~");
    }
}
​
​
​
//让cat类继承Animal类 Animal是父类, Cat是子类
public class Cat extends Animal {
​
    //行为
    public void eat(){
        System.out.println("吃鱼~");
    }
}
​
​
​
public class Dog extends Animal{
    //行为
    public void eat(){
        System.out.println("吃骨头~");
    }
}
​
​
public class Test {
​
    public static void main(String[] args) {
        //测试Cat
        Cat c = new Cat();
        c.eat();
        //ctrl+鼠标移动  变小手
        c.drink();
        c.sleep();
​
        System.out.println("=====================");
​
        //测试Dog
        Dog d = new Dog();
        d.eat();
        d.drink();
        d.sleep();
​
    }
}

四. 方法重写

4.1 前提

当从父类中继承的内容不能满足子类需求时,子类可以重写父类的方法

4.2 概念

当子类中出现了和父类一模一样的方法声明时, 子类就重写了父类的方法

//抽取cat类和dog类中共性的内容
public class Animal {
    public void sleep(){
        System.out.println("睡觉觉~");
    }
​
    public void drink(){
        System.out.println("喝水水~");
    }
}
​
//让cat类继承Animal类 Animal是父类, Cat是子类
public class Cat extends Animal {
    //重写父类的drink方法
    @Override//作用: 检查子类是否正确的重写了父类的方法
    public void drink(){
        System.out.println("喝水水~");
        System.out.println("舔舔嘴~");
    }
​
    //生成重写的代码: 写方法名+回车
​
    //行为
    public void eat(){
        System.out.println("吃鱼~");
    }
}
​
public class Test {
​
    public static void main(String[] args) {
       Cat c = new Cat();
       c.drink();
​
    }
}

4.3 继承中方法的调用规则

当使用子类对象调用方法时,如果子类中有该方法,那么执行, 如果子类中没有该方法,则向上查找父类中的方法执行

4.4 方法继承的注意事项

  1. 类与类的继承, 只支持单继承,不支持多继承

  2. 类与类的继承,支持多层继承

//一个类文件中要声明多个类,那么只能有一个类被public修饰,而且该类的名字和类文件的名字要保持一致
public class Test {
    public static void main(String[] args) {
        E e = new E();
        e.show();
    }
}
​
​
class A{
    public void show(){
        System.out.println("aaaa");
    }
}
​
class B extends A{
    public void msg(){
        System.out.println("bbbb");
    }
}
​
//单继承
class C extends A{
​
}
​
/*
报错,不支持多继承
class D extends A,B{
​
}*/
​
class E extends B{
​
}

五. 继承中的构造器

5.1 前提

在继承中,构造方法是不存在继承的,也就是说,子类不能继承父类的构造方法

5.2 子类中提供自己的构造方法

//定义父类,用于抽取共性内容
public class Person {
    private String name;
    private int age;
​
    public Person() {
        System.out.println("你大爷...");
    }
​
    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 Teacher extends Person {
    private String subject;//学科
​
    public Teacher(){
        //super();//调用父类的空参构造
        //注意: 如果子类的构造方法没有手动的通过super()调用父类的构造方法,那么子类构造方法第一行隐藏了一个super()
    }
​
    public Teacher(String name,int age,String subject){
        //this.name = name; 报错,因为这两个成员变量在父类中私有了
        //this.age = age;
        //super关键字: 父类引用, 可以使用super关键字调用父类的构造方法,也可以调用父类的成员方法
        super(name,age);
        this.subject = subject;
    }
​
​
    public String getSubject() {
        return subject;
    }
​
    public void setSubject(String subject) {
        this.subject = subject;
    }
}
​
​
​
​
public class Test {
​
    public static void main(String[] args) {
        //Teacher t = new Teacher("马老师",18);
        Teacher t = new Teacher("马老师",18,"人体动力学...");
        System.out.println(t.getSubject()+","+t.getName()+","+t.getAge());
​
        Teacher t2 = new Teacher();
​
    }
}

5.3 super和this

可以使用super访问父类的内容

可以使用this访问当前类的内容

public class Teacher extends Person {
    private String subject;//学科
​
    public Teacher(){
        //super();//调用父类的空参构造
        //注意: 如果子类的构造方法没有手动的通过super()调用父类的构造方法,那么子类构造方法第一行隐藏了一个super()
    }
​
    public Teacher(String name,int age,String subject){
        //this.name = name; 报错,因为这两个成员变量在父类中私有了
        //this.age = age;
        //super关键字: 父类引用, 可以使用super关键字调用父类的构造方法,也可以调用父类的成员方法
        super(name,age);
        this.subject = subject;
    }
​
    public Teacher(String name){
        this();//调用当前类的空参构造
    }
​
​
    public String getSubject() {
        return subject;
    }
​
    public void setSubject(String subject) {
        this.subject = subject;
    }
​
    public void deSe(){
        System.out.println("摇头晃脑");
    }
​
    //反抗
    public void fanKang(){
        super.daErZi();//super.和this.可以加可以不加,但是建议加,因为可以提高代码的阅读性
        this.deSe();
        System.out.println("谁打我,我干谁....");
    }
}

5.4 综合案例

/*
        需求:
            1.定义一个员工类,
                其中有如下属性:
                    姓名,年龄,岗位
                其中有如下行为:
                    工作
            2.定义一个主管类,
                其中有如下属性:
                    姓名,年龄,岗位,司龄
                其中有如下行为:
                    工作,汇报
            3.定义一个经理类:
                其中有如下属性:
                    姓名,年龄,岗位,区域
                其中有如下行为:
                    工作,指定战略
            注意: 普通员工的工作内容: 简单工作,   主管类的工作内容: 复杂工作     经理类的工作内容: 统筹工作
​
            4.在测试类中分别创建员工类的,主管类的对象和经理类的对象进行调用方法测试
     */
//员工类
public class Employee {
    private String name;//姓名
    private int age;//年龄
    private String post;//岗位
​
​
    public Employee() {
    }
​
    public Employee(String name, int age, String post) {
        this.name = name;
        this.age = age;
        this.post = post;
    }
​
    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 String getPost() {
        return post;
    }
​
    public void setPost(String post) {
        this.post = post;
    }
​
    //工作的方法
    public void work(){
        System.out.println("简单工作~");
    }
}
//主管类
public class Manager extends Employee{
    private int servingAge;//司龄
​
    public Manager() {
    }
​
    public Manager(String name, int age, String post, int servingAge) {
        super(name, age, post);
        this.servingAge = servingAge;
    }
​
    public int getServingAge() {
        return servingAge;
    }
​
    public void setServingAge(int servingAge) {
        this.servingAge = servingAge;
    }
​
    //重写父类的work方法
    @Override
    public void work() {
        System.out.println("复杂工作");
    }
​
    //汇报
    public void report(){
        System.out.println("阅读汇报");
    }
}
​
//经理类
public class Leader extends Employee{
    private String area;//区域
​
    public Leader() {
    }
​
    public Leader(String name, int age, String post, String area) {
        super(name, age, post);
        this.area = area;
    }
​
    public String getArea() {
        return area;
    }
​
    public void setArea(String area) {
        this.area = area;
    }
​
    //重写父类的work方法
​
    @Override
    public void work() {
        System.out.println("统筹工作");
    }
​
    //指定战略
    public void plan(){
        System.out.println("计划");
    }
}
public class Test {
    /*
        需求:
            1.定义一个员工类,
                其中有如下属性:
                    姓名,年龄,岗位
                其中有如下行为:
                    工作
            2.定义一个主管类,
                其中有如下属性:
                    姓名,年龄,岗位,司龄
                其中有如下行为:
                    工作,汇报
            3.定义一个经理类:
                其中有如下属性:
                    姓名,年龄,岗位,区域
                其中有如下行为:
                    工作,指定战略
            注意: 普通员工的工作内容: 简单工作,   主管类的工作内容: 复杂工作     经理类的工作内容: 统筹工作
​
            4.在测试类中分别创建员工类的,主管类的对象和经理类的对象进行调用方法测试
     */
    public static void main(String[] args) {
        Employee e = new Employee("王老师",18,"讲师");
        e.work();
        System.out.println(e.getName()+","+e.getAge()+","+e.getPost());
​
        System.out.println("==============================================");
        Manager m = new Manager("张三",19,"内勤主管",3);
        m.work();
        m.report();
        System.out.println(m.getName()+","+m.getAge()+","+m.getPost()+","+m.getServingAge());
​
        System.out.println("==================================================");
        Leader l = new Leader("李四",20,"销售经理","华东区");
        l.work();
        l.plan();
        System.out.println(l.getName()+","+l.getAge()+","+l.getPost()+","+l.getArea());
    }
​
​
}
​

六. 抽象类概述

6.1 概念

不具体的类, 被abstract关键字修饰的类

6.2 抽象方法

不具体的方法, 被abstract修饰的方法, 没有方法体

6.3 前提

定义某一个方法时,并不知道该方法的具体实现方案, 那么此时需要把该方法定义成抽象方法

//抽取cat类和dog类中共性的内容
public class Animal {
    public void sleep(){
        System.out.println("睡觉觉~");
    }
​
    public void drink(){
        System.out.println("喝水水~");
    }
​
    //吃
    //定义动物的吃的方法时: 1.动物都有吃的行为, 2.不知道这个行为的具体方案
    public void eat(){
        System.out.println("吃食物...");
    }
}

6.4 抽象方法的定义

格式:

权限修饰符 abstract 返回值类型 方法名(参数列表);

注意:

抽象方法所在的类,必须是抽象类,也就是必须被abstract修饰

//抽取cat类和dog类中共性的内容
//如果一个类中包含了抽象方法,那么该类必须是抽象类
public abstract class Animal {
    public void sleep(){
        System.out.println("睡觉觉~");
    }
​
    public void drink(){
        System.out.println("喝水水~");
    }
​
    //吃
    //定义动物的吃的方法时: 1.动物都有吃的行为, 2.不知道这个行为的具体方案
    //如果一个方法没有方法体,那么该方法必须被abstract修饰,该方法就是一个抽象方法
    public abstract void eat();
}

6.5 抽象类使用

1.如果一个类是抽象的,那么该类不能被创建对象

2.如果要使用抽象类,必须定义子类继承抽象类,通过使用子类的方式,从而间接的使用当前抽象类

2.1 子类要么是抽象的,被abstract修饰

2.2 子类要么实现父类的所有的抽象方法

//快速实现父类中所有的抽象方法, 光标放到报错的地方,alt+enter
public /*abstract*/ class Sheep extends Animal{
​
    @Override
    public void eat() {
        System.out.println("吃草草~");
    }
}
​
​
public class Test {
    public static void main(String[] args) {
        //Animal a = new Animal();
        Sheep s = new Sheep();
        s.eat();
        s.drink();
    }
}

七.抽象类的注意事项及模版设计模式

7.1 抽象类的注意事项

如果一个类中,没有抽象方法,那么这个类,只要被abstract修饰,它就是一个抽象类

7.2 模版设计模式

设计模式: 是前人总结出来的针对一类问题的通用解决方案

java中的设计模式: 23种

单例设计模式, 多例设计模式,装饰者设计模式, 观察者设计模式, 责任链设计模式, 模板设计模式,代理设计模式.......

模版设计模式:

解决的问题: 大部分内容一样,少部分内容有差异

使用:

1.设计模板,规定通用的内容

2.继承模板,书写差异的内容

需求:

写作文:

<我的爸爸>

张三:
            <我的爸爸>
    我的爸爸真好,给我买零食....
    
    啊,这就是我的爸爸
    
李四:
                <我的爸爸>
    我的爸爸是大坏蛋,不陪我...
    
    啊,这就是我的爸爸
//设计模板
public abstract class WriteArticle {
    //写作文
    public void write(){
        System.out.println("          <我的爸爸>          ");
        writeMajor();
        System.out.println("啊,这就是我的爸爸...");
    }
​
    //定义一个写正文的方法
    public abstract void writeMajor();
}
​
​
//继承模版
public class XiaoMing extends WriteArticle{
    //写正文
    @Override
    public void writeMajor() {
        System.out.println("我的爸爸今天带我去公园, 走着走着走累了, 骑自行车载我, 不小心,我的脚卡到了轮胎里, 我哭的不行不行的,我越哭,他越骑....最后站起来蹬...");
    }
}
​
//测试
public class Test {
​
    public static void main(String[] args) {
        //让小明写作文
        XiaoMing xm = new XiaoMing();
        xm.write();
    }
}
​

八. static关键字

8.1 概念

关键字,静态的意思, 如果一个类中的成员被static关键字修饰,那么该成员属于类, 被当前类的多个对象共享

//学校类
public class School {
    //如果成员被static修饰,那么该成员属于类,当前成员会被当前类的多个对象共享
    static String name;//学校的名称
    String address;//学校的地址
​
}
​
​
public class Test {
​
    public static void main(String[] args) {
        School s1 = new School();
        s1.name = "衡水一中";
        s1.address = "衡水";
        System.out.println(s1.name);
        System.out.println(s1.address);
​
        System.out.println("===============================");
        School s2 = new School();
        s2.name="清华附中";
        s2.address="清华路";
        System.out.println(s2.name);
        System.out.println(s2.address);
​
        System.out.println("=======注意观察=======");
        System.out.println(s1.name);
        System.out.println(s1.address);
​
    }
}

8.2 静态成员访问方式

可以使用类名方法,也可以是使用对象名访问,但是推荐使用类名

public class Test2 {
​
    public static void main(String[] args) {
        //推荐使用类名访问
        School.name = "北京大学";
        School s = new School();
        s.name = "清华大学";
​
    }
}

8.3 static修饰成员方法

如果static修饰成员方法,那么该方法属于类, 建议使用类名调用

//学校类
public class School {
    //如果成员被static修饰,那么该成员属于类,当前成员会被当前类的多个对象共享
    static String name;//学校的名称
    String address;//学校的地址
​
    public static void show(){
        System.out.println("我是最牛逼的学校...");
    }
}
​
public class Test2 {
​
    public static void main(String[] args) {
        //推荐使用类名访问
        School.name = "北京大学";
        School s = new School();
        s.name = "清华大学";
​
        //推荐使用类名调用
        School.show();
        s.show();
    }
}

8.4 static静态代码块

格式:

static{

写代码

}

执行时机:

随着类的加载而执行,并且一次程序的运行过程中,只执行一次

作用:

1. 可以给静态变量赋值
2. 预先加载内容

public class A {
    private static String name;
    //只执行一次
    static{
        //name在某个文件中存储着, 读取文件的内容,把读取到的内容赋值给name属性
        System.out.println("静态代码块执行了");
    }
}
public class Test {
​
    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new A();
    }
}

8.5 静态的访问规则

静态的成员属于类, 非静态的成员属于对象, 类先于对象存在, 静态成员先于非静态成员存在!

1.静态里面只能访问静态的成员!

2.非静态里面可以访问静态的成员,也可以访问非静态的成员!

public class A {
​
    //静态变量
    static String name;
    //非静态变量
    int age;
​
    static{
        System.out.println(name);
        //System.out.println(age);
    }
​
    //静态方法
    public static void show(){
        //静态中只能访问静态
        System.out.println(name);
        //静态中不能访问非静态
        //System.out.println(age); 报错
    }
​
    //非静态方法
    public void message(){
        //非静态中都可以访问
        System.out.println(name);
        System.out.println(age);
    }
}

8.6 静态的应用场景

静态属于类,所以没有对象也可以访问这些静态的内容, 在开发中,一般情况下,我们的工具类(只提供方法,不提供成员变量)中的方法一般都会设计成静态的!

public class Test {
​
    public static void main(String[] args) {
        //Math: jdk提供的数学工具类
        //求绝对值
        System.out.println(Math.abs(-2));
        System.out.println(Math.max(2, 3));
        System.out.println(Math.pow(2, 3));
    }
}

九. final关键字

9.1概念

是一个关键字, 被final修饰的内容,将不能发生改变

9.2 使用

  1. final修饰类

    当前的类不能被其他类继承

  2. final修饰方法

    当前的方法不能被子类重写

  3. final修饰变量

    该变量只能赋值一次

public class Test {
​
}
​
//如果一个类被final修饰,则不能被继承
final class A{
​
}
​
class B /*extends A*/{
​
}
​
class C{
    public void show(){
​
    }
    //该方法不能被重写
    public final void msg(){
​
    }
}
​
class D extends C{
    @Override
    public void show() {
        System.out.println("aaaa");
    }
​
    /*public final void msg(){
​
    }*/
}
​
class E{
    //如果final修饰成员变量,该成员变量只能赋值一次
    //如果final修饰成员变量,那么定义该成员变量的同时,需要给改成员变量赋值
    //被final修饰的变量,称为常量
    final String name = "阿三";
​
    public void changeName(){
        //name = "小四"; 报错
    }
}

十. 接口的概述

10.1 概念

接口: 规范

java代码中的接口:用于规定实现类中必须有哪些内容

10.2 格式

interface 接口名{

常量;

抽象方法;

}

十一. 接口的定义和使用

接口不能直接new对象,必须通过实现类间接的使用

如果一个类要实现某个接口: class 类名 implements 接口名{}

//游泳的接口
public interface Swimming {
    //常量: 接口中的成员变量默认被 public static final
    //某个内容是灰色: 1.该内容内有被使用  2.该内容可以不写(默认值)
    //给常量起名字时: 使用大写,如果是多个单词,那么用_连接
    /*public static final */String ADDRESS = "水利局";
​
    //抽象方法 接口中的方法,默认被public abstract修饰
    /*public abstract*/ void show();
    void swim();
}
public class Dog implements Swimming{
​
    @Override
    public void show() {
        System.out.println("我是天下最美丽的狗....");
    }
​
    @Override
    public void swim() {
        System.out.println("狗刨式游泳....");
    }
}
​
​
​
public class Sheep implements Swimming{
    @Override
    public void show() {
        System.out.println("我是天下最帅的洋洋...");
    }
​
    @Override
    public void swim() {
        System.out.println("仰泳....");
    }
}
​
public class Test {
​
    public static void main(String[] args) {
        //接口中的常量推荐使用接口名访问
        System.out.println(Swimming.ADDRESS);
​
        //创建一个接口对象使用 接口不能直接创建对象
        //Swimming s = new Swimming();
​
        Dog d = new Dog();
        d.swim();
        d.show();
        //System.out.println(d.ADDRESS);
        System.out.println("========");
​
        Sheep s = new Sheep();
        s.swim();
        s.show();
        //System.out.println(s.ADDRESS);
    }
}

十二. 新版本的jdk中的接口的内容升级

在jdk1.7及以前, 接口中只有常量和抽象方法

在jdk1.8版本中,新增了默认方法和静态方法

在jdk1.9版本中,新增了私有方法

12.1 默认方法

使用添加抽象方法的方式,升级接口,不得不修改该接口的实现类,比较麻烦

格式:

public default 返回值类型 方法名(){

方法体;

return 返回值;

}

//游泳的接口
public interface Swimming {
    //常量: 接口中的成员变量默认被 public static final
    //某个内容是灰色: 1.该内容内有被使用  2.该内容可以不写(默认值)
    //给常量起名字时: 使用大写,如果是多个单词,那么用_连接
    /*public static final */String ADDRESS = "水利局";
​
    //抽象方法 接口中的方法,默认被public abstract修饰
    /*public abstract*/ void show();
    void swim();
    //void shaiGan();
    //这个默认方法,会被所有的实现类继承,子类可以重写,也可以不重写
    public default void shiaGan(){
        System.out.println("在太阳底下晒干...");
    }
}
public class Sheep implements Swimming{
    @Override
    public void show() {
        System.out.println("我是天下最帅的洋洋...");
    }
​
    @Override
    public void swim() {
        System.out.println("仰泳....");
    }
​
​
}
​
​
public class Dog implements Swimming{
​
    @Override
    public void show() {
        System.out.println("我是天下最美丽的狗....");
    }
​
    @Override
    public void swim() {
        System.out.println("狗刨式游泳....");
    }
​
    @Override
    public void shiaGan() {
        System.out.println("在浴霸底下晒干...");
    }
}
public class Test {
​
    public static void main(String[] args) {
        //接口中的常量推荐使用接口名访问
        System.out.println(Swimming.ADDRESS);
​
        //创建一个接口对象使用 接口不能直接创建对象
        //Swimming s = new Swimming();
​
        Dog d = new Dog();
        d.swim();
        d.show();
        d.shiaGan();
        //System.out.println(d.ADDRESS);
        System.out.println("========");
​
        Sheep s = new Sheep();
        s.swim();
        s.show();
        s.shiaGan();
        //System.out.println(s.ADDRESS);
    }
}

12.2 私有方法

用于解决多个默认方法中有共性代码的问题

格式:

private 返回值类型 方法名(){

方法体;

return 返回值;

}

//游泳的接口
public interface Swimming {
    //常量: 接口中的成员变量默认被 public static final
    //某个内容是灰色: 1.该内容内有被使用  2.该内容可以不写(默认值)
    //给常量起名字时: 使用大写,如果是多个单词,那么用_连接
    /*public static final */String ADDRESS = "水利局";
​
    //抽象方法 接口中的方法,默认被public abstract修饰
    /*public abstract*/ void show();
    void swim();
    //void shaiGan();
    //这个默认方法,会被所有的实现类继承,子类可以重写,也可以不重写
    public default void shiaGan(){
        preWork();
        System.out.println("在太阳底下晒干...");
    }
​
    public default void fengGan(){
        preWork();
        System.out.println("在吹风机下风干...");
    }
​
    //私有方法,用于解决多个默认方法有共性代码的问题
    private void preWork(){
        System.out.println("先走出泳池");
        System.out.println("再穿上裤子");
    }
​
}

12.3 静态方法

jdk1.8及以前, 要使用接口,必须借助于实现类使用.为了让接口可以脱离实现类单独使用,因此jdk1.9新增了静态方法

格式:

public static 返回值类型 方法名(参数列表){

方法体;

return 返回值;

}

//游泳的接口
public interface Swimming {
    //常量: 接口中的成员变量默认被 public static final
    //某个内容是灰色: 1.该内容内有被使用  2.该内容可以不写(默认值)
    //给常量起名字时: 使用大写,如果是多个单词,那么用_连接
    /*public static final */String ADDRESS = "水利局";
​
    //抽象方法 接口中的方法,默认被public abstract修饰
    /*public abstract*/ void show();
    void swim();
    //void shaiGan();
    //这个默认方法,会被所有的实现类继承,子类可以重写,也可以不重写
    public default void shiaGan(){
        preWork();
        System.out.println("在太阳底下晒干...");
    }
​
    public default void fengGan(){
        preWork();
        System.out.println("在吹风机下风干...");
    }
​
    //私有方法,用于解决多个默认方法有共性代码的问题
    private void preWork(){
        System.out.println("先走出泳池");
        System.out.println("再穿上裤子");
    }
​
    //多人游泳
    public static void multiSwim(){
        System.out.println("多人游泳...");
    }
​
}
​
​
public class Test {
​
    public static void main(String[] args) {
        //接口中的常量推荐使用接口名访问
        System.out.println(Swimming.ADDRESS);
​
        //创建一个接口对象使用 接口不能直接创建对象
        //Swimming s = new Swimming();
​
        Dog d = new Dog();
        d.swim();
        d.show();
        d.shiaGan();
        //System.out.println(d.ADDRESS);
        System.out.println("========");
​
        Sheep s = new Sheep();
        s.swim();
        s.show();
        s.shiaGan();
        //System.out.println(s.ADDRESS);
​
        //静态方法可以被接口名直接调用
        Swimming.multiSwim();
    }
}

十三. 接口和抽象类的异同点

抽象类:

既有常规方法,又有抽象方法

接口:

一般都是抽象方法

类与类的关系:

1. 类与类之间只能单继承
2. 支持多层继承

接口与接口的关系:

1. 接口与接口之间支持多继承
2. 支持多层继承

类与接口的关系:

一个类可以同时继承另外一个类,并实现多个接口

public class Test {
​
​
}
​
interface A{
​
}
​
interface B{
​
}
//多继承
interface C extends A,B{
​
}
​
interface D extends C{
​
}
//多层继承
interface E extends D{
​
}
​
class F {
​
}
//一个类可以继承其他类的同时实现多个接口
class G extends F implements A,B{
​
}

十四.综合案例

需求:
            定义一个接口,需要有一个行为: 闹钟
            定义一个接口,需要有一个行为: 看视频
​
            定义一个类(手机),需要有如下内容:
                1.有属性: 品牌,颜色,价格
                2.有行为: 打电话,发短信
​
            定义一个苹果手机类,需要有如下内容:
                1.有属性: 品牌,颜色,价格
                2.有行为: 打电话,发短信,自动上报定位, 闹钟(参照接口)
            定义一个华为手机类,需要有如下内容:
                1.有属性: 品牌,颜色,价格
                2.有行为: 打电话,发短信,卫星通话, 看视频(参照接口)
​
            定义测试类:
                创建苹果手机和华为手机调用方法测试
//闹钟接口
public interface Alarming {
    //闹钟行为
    void alarm();
}
//视频
public interface Video {
    //看视频
    void watchVideo();
}
public class Phone {
    private String brand;//品牌
    private String color;//颜色
    private double price;//价格
​
    public Phone() {
    }
​
    public Phone(String brand, String color, double price) {
        this.brand = brand;
        this.color = color;
        this.price = price;
    }
​
    public String getBrand() {
        return brand;
    }
​
    public void setBrand(String brand) {
        this.brand = brand;
    }
​
    public String getColor() {
        return color;
    }
​
    public void setColor(String color) {
        this.color = color;
    }
​
    public double getPrice() {
        return price;
    }
​
    public void setPrice(double price) {
        this.price = price;
    }
​
    //打电话
    public void call(){
        System.out.println("打电话...");
    }
​
    //发短信
    public void message(){
        System.out.println("发短信...");
    }
}
//苹果手机类,继承了手机类,复用手机类中的内容
public class IPhone extends Phone implements Alarming{
    //构造方法
    public IPhone() {
    }
​
    public IPhone(String brand, String color, double price) {
        super(brand, color, price);
    }
​
    //自动上报定位
    public void reportLocation(){
        System.out.println("24小时上报位置...");
    }
​
    //闹钟行为
    @Override
    public void alarm() {
        System.out.println("叮铃铃...");
    }
}
​

//华为手机类
​​​​​​​public class HuaWei extends Phone implements Video {
​
    //构造方法
    public HuaWei() {
    }
​
    public HuaWei(String brand, String color, double price) {
        super(brand, color, price);
    }
​
    //卫星通话
    public void satellite(){
        System.out.println("随时随地打电话...");
    }
​
    @Override
    public void watchVideo() {
        System.out.println("空气投影看视频....");
    }
​
}
public class Test {
    /*
        需求:
            定义一个接口,需要有一个行为: 闹钟
            定义一个接口,需要有一个行为: 看视频
​
            定义一个类(手机),需要有如下内容:
                1.有属性: 品牌,颜色,价格
                2.有行为: 打电话,发短信
​
            定义一个苹果手机类,需要有如下内容:
                1.有属性: 品牌,颜色,价格
                2.有行为: 打电话,发短信,自动上报定位, 闹钟(参照接口)
            定义一个华为手机类,需要有如下内容:
                1.有属性: 品牌,颜色,价格
                2.有行为: 打电话,发短信,卫星通话, 看视频(参照接口)
​
            定义测试类:
                创建苹果手机和华为手机调用方法测试
​
     */
    public static void main(String[] args) {
        //创建苹果手机对象,调用方法完成测试
        IPhone iPhone = new IPhone("苹果","土豪金",999);
        iPhone.alarm();
        iPhone.reportLocation();
        iPhone.call();
        iPhone.message();
        System.out.println(iPhone.getBrand()+","+iPhone.getColor()+","+iPhone.getPrice());
​
        System.out.println("==================================");
        HuaWei huaWei = new HuaWei("华为","天青",19999);
        huaWei.satellite();
        huaWei.watchVideo();
        huaWei.call();
        huaWei.message();
        System.out.println(huaWei.getBrand()+","+huaWei.getColor()+","+huaWei.getPrice());
    }
}
 

十五. 多态

1.1 概念

同一个对象在不同时刻展现出的不同形态!

1.2 如何判别当前有没有使用多态

有没有存在父引用(父类的引用,父接口的引用)指向子类对象

public abstract class Animal {
    //吃
    public abstract void eat();
    //喝
    public void drink(){
        System.out.println("喝水水~");
    }
}
​
​
//继承父类
public class Cat extends Animal{
​
    @Override
    public void eat() {
        System.out.println("猫吃鱼...");
    }
}
​
public class Test {
​
    public static void main(String[] args) {
        //多态: 同一个对象在不同时刻,展现出的不同形态
        //使用多态: 父引用指向子类对象
        Cat c = new Cat();//并没有使用多态
​
        Animal a = c;//使用了多态
    }
}
//老师接口
public interface Teacher {
    void teach();
}
​
//工人接口
public interface Worker {
​
    void work();
}
​
public class Somebody implements Worker,Teacher{
    @Override
    public void teach() {
        System.out.println("教书育人...");
    }
​
    @Override
    public void work() {
        System.out.println("平地起楼...");
    }
}
​
​
public class Test {
​
    public static void main(String[] args) {
        Somebody s = new Somebody();//创建了一个人的对象
​
        Worker w = s;//使用了多态, 展现的形态是工人
        Teacher t = s;//使用了多态, 展现的心态是老师
    }
}

1.3 多态的好处

可以提高代码的扩展性和灵活性

public abstract class Animal {
    //吃
    public abstract void eat();
    //喝
    public void drink(){
        System.out.println("喝水水~");
    }
}
​
​
//继承父类
public class Cat extends Animal {
​
    @Override
    public void eat() {
        System.out.println("猫吃鱼...");
    }
}
​
public class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("吃骨头...");
    }
}
​
​
public class Pig extends Animal{
    @Override
    public void eat() {
        System.out.println("啥都吃...");
    }
}
public class Test {
​
    public static void main(String[] args) {
        Cat c = new Cat();
        //feedCat(c);
        feedAnimal(c);
​
        Dog d = new Dog();
        //feedDog(d);
        //feedCat(d); 这里会报错
        feedAnimal(d);
​
        Pig p = new Pig();
        feedAnimal(p);
    }
​
    //定义一个方法,接收一个猫对象,喂猫
    public static void feedCat(Cat c){
        c.eat();
        c.drink();
    }
​
    //定义一个方法,接收一个狗对象,喂狗
    public static void feedDog(Dog d){
        d.eat();
        d.drink();
    }
​
    //每有一个新的动物, 需要定义一个新的方法来喂这种动物
    //可以设计一个方法,喂所有的动物
​
    public static void feedAnimal(Animal a){
        a.eat();
        a.drink();
    }
}

1.4 多态的弊端

使用父类引用无法调用子类特有的内容

注意:

在多态的调用中, 编译看左边(左边的类中有没有该方法), 运行看右边

public abstract class Animal {
    //吃
    public abstract void eat();
    //喝
    public void drink(){
        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 watchDoor(){
        System.out.println("看门...");
    }
}
public class Test {
    public static void main(String[] args) {
​
​
        Animal a = new Cat();
        a.eat();
        a.drink();
        //a.catchMouse();//会报错  编译看左边,而Animal类中并没有catchMouse方法
​
        //需要把父类引用转换成子类引用才可以调用子类特有的内容
        /*
            引用类型数据的转换:
                向上转型: 把低类型的引用转换成高类型的引用
                    Dog d = new Dog();
                    Animal a1 = d;
                向下转型: 把高类型的引用转换成低类型的引用
                    低类型 变量 = (低类型)高类型的变量;
         */
        Cat c = (Cat) a;
        c.catchMouse();
    }
}
public class Test2 {
​
    public static void main(String[] args) {
        Cat c = new Cat();
        useAnimal(c);
​
        Dog d = new Dog();
        useAnimal(d);
    }
​
    //定义一个方法,使用动物
    public static void useAnimal(Animal a){
        a.eat();
        a.drink();
        //向下转型有报错的风险 ClassCastException(类型转换异常)
        // instanceof    引用名 instanceof 类名 :  判断当前引用指向的对象是不是指定类的对象
        if (a instanceof Cat){
            Cat c = (Cat) a;
            c.catchMouse();
        }
​
    }
}

十六. 内部类

1.1 概念

定义到某个类中的其他类,把它称之为内部类

1.2 分类

成员内部类: 定义到类的成员位置的类

public class Person {
​
    //成员内部类
    public class Heart{
        
    }
}

局部内部类: 定义到方法中的类

public class Person {
​
    public void show() {
        //局部内部类,不能有权限修饰符
        class A {
​
        }
    }
​
    //成员内部类
    public class Heart {
​
    }
}

匿名[局部]内部类: 定义到方法中的,没有名字的类

匿名内部类及其使用格式:

new 父类名/接口名(){

//类的内容

}

public abstract class Animal {
    //吃
    public abstract void eat();
    //喝
    public void drink(){
        System.out.println("喝水水~");
    }
}
​
//继承父类
/*
    public: 公共的,谁都能访问呢
    class: 定义的是一个类
    Cat: 类名: 为了让别人可以通过该名字反复的使用该名字所代表的内容
    extends Animal: 继承父类, 规定子类中必须有什么内容
    {}: 指定类的内容
​
 */
public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼...");
    }
}
​
public class Test {
​
    public static void main(String[] args) {
        //创建Cat类的对象,并调用方法使用
        Animal a1 = new Cat();
        a1.eat();
​
        //使用匿名内部类的方式,创建一个动物对象
        /*
            new 父类名/接口名(){
                //内容
            }
         */
        /*
            new: 申请内存,调用构造方法创建对象
            Animal: 用于规定匿名内部类中必须有什么内容
            (): 调用匿名内部类的空参构造创建对象
            {}: 指定类的内容
         */
        Animal a2 = new Animal(){
            @Override
            public void eat() {
                System.out.println("吃草草~");
            }
        };
        a2.eat();
​
    }
}

1.3 匿名内部类和外部类的区别

public class Test {
​
    public static void main(String[] args) {
        //创建Cat类的对象,并调用方法使用
        Animal a1 = new Cat();
        a1.eat();
​
        //使用匿名内部类的方式,创建一个动物对象
        /*
            new 父类名/接口名(){
                //内容
            }
         */
        /*
            new: 申请内存,调用构造方法创建对象
            Animal: 用于规定匿名内部类中必须有什么内容
            (): 调用匿名内部类的空参构造创建对象
            {}: 指定类的内容
         */
        Animal a2 = new Animal(){
            @Override
            public void eat() {
                System.out.println("吃草草~");
            }
        };
        a2.eat();
​
        //使用匿名内部类的方式创建另外一个对象
        //注意: 使用匿名内部类,定义类的同时可以根据该类创建一个对象,没有办法重复使用
        Animal a3 = new Animal() {
            @Override
            public void eat() {
                System.out.println("吃草草~");
            }
        };
        a3.eat();
​
        /*
            匿名内部类和传统外部类的区别:
                匿名局部内部类:
                    定义类的同时可以创建一个该类的对象
                    无需要单独创建文件
                    内部类在项目编译完毕后,在jvm运行过程中,在jvm内部进行编译,不存在.class文件
                外部类:
                    可以根据该类创建无数个对象
                    每定义一个类,需要创建一个新的文件
                    外部类在项目编译完毕后,存在.class文件
​
                使用场景:
                    如果某个类只创建一个对象,建议使用匿名内部类
                    如果某个类要反复创建对象, 建议使用外部类
                    
         */
​
    }
}

1.4 匿名内部类的常见使用方式

在传递参数的时候使用

//游泳接口
public interface Swimming {
    void swim();
}
​
public class Sheep implements Swimming{
    @Override
    public void swim() {
        System.out.println("仰泳...");
    }
}
public class Test {
    //主方法
    public static void main(String[] args) {
        //调用method方法
        //Swimming接口的实现类对象
        Swimming sheep = new Sheep();
        method(sheep);
​
        //匿名内部类的方式
        Swimming frog = new Swimming() {
            @Override
            public void swim() {
                System.out.println("蛙泳...");
            }
        };
​
        //method(frog);
        method(new Swimming() {
            @Override
            public void swim() {
                System.out.println("蛙泳...");
            }
        });
​
        //匿名内部类最常用的使用方式
        method(new Swimming() {
            @Override
            public void swim() {
                System.out.println("狗刨...");
            }
        });
​
    }
​
    //定义一个方法, 接收一个会游泳的生物,让他游泳
    public static void method(Swimming s) {
        s.swim();
    }
}
  • 18
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
面向对象编程是一种编程范式,它将程序的构建和设计思路以面向对象的方式进行组织和实现。在Java中,面向对象编程是基于Java SE(Standard Edition)的一种编程方式。第07讲主要介绍了面向对象编程中的一些基本概念和关键术语。 在面向对象编程中,我们将程序中的数据和对数据的操作(方法)封装在一起,形成一个对象。对象由两部分构成:属性和方法。属性是用来描述对象的特征,而方法则是对象可以执行的操作。对象之间通过消息(方法调用)进行通信和交互。面向对象的核心思想是通过封装、继承和多态实现程序的复用和扩展。 封装是面向对象编程中的一个重要概念,它指的是将类的属性和方法进行封装,使得外部无法直接访问和修改对象的内部状态,只能通过公共的方法来操作属性和执行方法。封装提供了一种将数据和行为组合在一起的方式,可以保护数据的完整性和安全性。 继承是面向对象编程中的另一个重要概念,它指的是通过定义一个新的类来继承现有类的属性和方法。通过继承,子类可以继承父类的属性和方法,并可以在此基础上进行扩展和修改。继承提供了一种代码复用的机制,可以减少重复编码的工作量。 多态是面向对象编程的又一个重要概念,它指的是同一类型的对象在不同的情况下可以有不同的表现形式。多态通过方法的重写和方法的重载实现。方法的重写指的是在子类中重新定义和实现父类的方法,方法的重载指的是在同一个类中可以定义多个同名但参数列表不同的方法。 总结来说,面向对象编程是一种将程序组织和设计思路以对象为中心的编程方式。在JavaSE中,我们可以通过封装、继承和多态来实现面向对象编程的目标。封装可以提高程序的可维护性和可复用性,继承可以减少重复编码的工作量,多态可以灵活地操作对象。掌握这些基本概念和关键术语,可以帮助我们更好地理解和应用面向对象编程的思想。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值