Java面向对象

1.面向对象概述

面向过程:是具体的,按步骤进行,适合处理简单问题。

面向对象:是抽象的,解决问题先分类,对所分的类进行单独思考,适合处理复杂问题、多人协作问题。但对分类后的细节问题,仍需面向过程解决。

面向对象编程OOP的本质以类的方式组织代码,以对象的形式组织(封装)数据。

OOP的三大特性:封装、继承、多态

从认识论考虑:先有对象后有类!对象是具体的,类是抽象的,类是对对象的抽象。

从代码运行考虑:先类后有对象!类是对象的模板

2.回顾及加深方法

  1. 静态方法和非静态方法
  • 在不同类中

    可以直接调用静态方法,但是调用非静态方法必须先实例化后调用
    在这里插入图片描述

  • 在一个类中

​ 📜 非静态方法之间可以直接相互调用
在这里插入图片描述

​ 📜静态方法之间也可以直接相互调用
在这里插入图片描述

📜但是**静态方法不能调用非静态方法*
在这里插入图片描述

⭐️因为静态方法和类一起加载,而非静态方法在类实例化(New)之后才存在,所以已经存在的调用还没存在的会出错

  1. 值传递
public class 值传递 {
    public static void main(String[] args) {
        int a=1;
        change(a);
        System.out.println(a);//输出 1

    }
    //返回值为空
    public static void change(int a) {
        a =100;//改变的是形参a
    }
}
  1. 引用传递
//引用传递:传递的是对象,本质还是值传递

//只能有一个 public class,但是可以有多个 class
class Person{
    String name;//一个属性:name
}

public class 引用传递 {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println(person.name);   //输出 null

        引用传递.change(person);
        System.out.println(person.name);   //输出 ssss
    }

    public static void change(Person per) {
        //per 是一个对象,指向传递的person
        per.name="sssss";
    }
}

3.对象的创建分析

  1. 类与对象的关系

​ ❗️ 类是一种抽象的数据类型,它是对 某一类 事物整体的描述 / 定义,是一个模板,不能代表一个具体的事物!!!

​ ❗️ 对象是对抽象概念的具体实例,对象(在堆中)是通过引用(在栈中)来操作的

  1. 类与对象的创建
  • 创建类
public class Pet {

    //属性:也称字段Field 或者 成员变量
    //属性构成   修饰符 + 属性类型 + 属性名 = 属性值;
    //默认属性   数字:0  0.0 、char:u0000 、boolean:false 、 引用:null
    public int age;
    public String name;

    //利用默认的无参构造器

    //方法
    public void shout() {
        System.out.println(this.name+"叫了一声");
    }

}
  • 创建对象

使用 new 关键字创建对象。在new对象的时候,除了 分配内存空间 之外,还会给创建好的对象进行默认初始化(例如,对属性初始化),以及对类中构造器的调用
3. 构造器

一个类即使什么都不写,也会存在一个默认构造方法

在这里插入图片描述
类中的构造器,也称构造方法,是创建对象时必须调用的。主要作用为:new创建对象时,本质是在调用构造器、初始化值;并且构造器有以下两个特点:

  • 必须和类的名字相同
  • 没有返回类型,不能写void!!

人为定义一个构造器(显示定义一个构造器),能够初始化一些信息,可分为:无参构造器和有参构造器

  • 无参构造器
    在这里插入图片描述

  • 有参构造器
    在这里插入图片描述
    ❗️一旦定义了有参构造器,就必须显示定义无参构造器,该无参构造器可以什么都不写

    创建构造器的快捷键:alt+insert

  1. 创建对象的内存分析

    创建对象时,对象名字即引用变量名都在栈中,实际new的对象在堆中

4.面向对象的三大特性

1.封装

封装主要是针对类中的属性而言

属性私有 privateget / set :提供一些可以操作属性的方法

快捷键:alt+insert 生成 get/set 方法

  • 该露的露,该藏的藏

程序设计要求 ”高内聚、低耦合 “。高内聚:类的内部数据操作细节由自己完成,不许外部干涉;低耦合:仅暴露少量的方法给外部使用。

封装主要是针对类中的属性而言

  • 封装的意义
  1. 提高程序安全性,对传入的数据进行安全性判断
  2. 隐藏对数据操作的细节
  3. 提高了系统的维护性
  4. 统一接口,均为 get/set 方法
public class Student {
    //属性私有
    private String name;
    private int id;
    private char sex;

    //提供一些可以操作属性的方法
    //提供 public 的 get/set 方法
    //get 获得数据的值
    public String getName() {
        return this.name;
    }
    //set 设置数据的值
    public void  setName(String name1) {
        this.name=name1;
    }

    public int getId() {
        return id;
    }
    public void setId(int id1) {
        if (id1>0 && id1<100) {
            //数据安全性检验
            this.id = id1;
        }else {
            System.out.println("学号不合法");
        }
    }

    public char getSex() {
        return sex;
    }
    public void setSex(char sex) {
        this.sex = sex;
    }
}

public class Main {
    public static void main(String[] args) {
        Student s1 = new Student();
        s1.setName("三吉");
        System.out.println(s1.getName());

        s1.setId(105);//输出 学号不合法

    }
}
2.继承 extends

类与类之间的关系:继承、依赖、组合、聚合等等。

继承的本质是对某一批类的抽象,从而实现对现实世界更好地建模。extend 的意思是“扩展”,即子类是父类的扩展。子类,又称派生类;父类,又称基类。
父类中私有的属性或方法,无法被继承。Java中所有的类默认直接或间接地继承Object类

❗️ Java中只有单继承,没有多继承,只能直接继承一个类(一个儿子只能有一个父亲)

快捷键:CTRL+H 打开继承树

⭐️ super

  • super 只能在继承条件下使用

  • 在子类中可以通过 super+ . 对父类中的公共/受保护的属性或方法进行调用

  • 创建子类,总是会先调用父类的无参构造器。若利用super()显示地调用父类的无参构造器,则需要将super()放在子类无参构造器的最前面

  • super 和 this 不能同时调用构造方法!

⭐️ 方法重写

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WPxwXrfk-1632832501782)(面向对象.assets/image-20210928164709569.png)]

方法重写和静态方法无关,只和非静态方法有关

方法重写的前提是要有继承关系,是子类重写父类的非静态方法

快捷键:alt+insert
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5dR22Onb-1632832501785)(面向对象.assets/image-20210928165131935.png)]

方法重写
重写的前提是:有继承关系,子类重写父类的方法
方法名相同,方法体不同
参数列表必须相同
修饰符:范围只可以扩大,即子类访问权限 大于等于 父类访问权限 public > protected > default > private
返回类型:子类方法返回类型 小于等于 父类方法返回类型
抛出的异常:异常范围只可以缩小,即子类抛出异常 小于等于 父类抛出异常
重写的意义
父类的功能,子类不一定需要,或者不一定满足子类的需要
3.多态

多态,即同一个方法可以根据指向对象的引用不同而调用不同的方法。

多态存在的条件:有继承关系、子类重写父类的方法。父类引用指向子类对象

实现动态编译(类型的最终状态只有在执行的过程中才能决定),使得可扩展性增强。
在这里插入图片描述
多态中(有继承关系时)对象能执行哪些方法,主要看该对象的左边,左边有该方法则能调用,没有则报错。若父子类都有该方法,但子类重写了父类的方法则调用子类重写的方法。

父类,可以指向子类,但是不能调用子类独有的方法

多态
多态是方法的多态,没有属性的多态
多态存在于有继承关系的父子类,否则会出现 类型转换异常ClassCastException
方法重写
父类引用 指向 子类对象 Father f=new Son();

注意什么方法不能重写!例如,被static修饰的方法(属于类,不属于实例)、被final修饰的方法、被private修饰的方法

  • instanceof

instanceof 判断两个类之间是否存在父子关系

X instanceof Y,看X引用指向的对象是否为Y的子类型,有就返回true,无则返回false。如果X类和Y类没有继承关系则编译报错

  • 类型转换

基本类型之间的转换,高转低——强转,低转高——自动

引用类型之间也遵循如上规则

在这里插入图片描述

5.抽象类和接口

1.抽象类Abstract

在一个类前加关键字 abstract ,就变成了抽象类,抽象出共有属性,提高开发效率

抽象类不能多继承

抽象方法没有方法体,在一个类中,只声明了方法名字而不实现方法体,在方法前加关键字 abstract ,就变成了抽象方法。抽象方法不能脱离抽象类而单独存在。

普通方法也可以出现在抽象类中

//抽象类
public abstract class Action {

    //抽象方法,有人帮我们实现
    //抽象方法必须在抽象类中
    public abstract void run();
    
    //普通方法
    public void eat() {
        System.out.println("吃饭啦");
    }
    
}

**抽象类 **中如果有 抽象方法 ,则继承该 抽象类的子类 必须重写这些抽象方法,除非子类也是抽象类。

//抽象类的所有方法,必须由抽象类的子类实现
//除非子类也是抽象类
public class A extends Action{
    @Override
    public void run() {
    
    }
}

抽象类不能直接 new 实例化,只能靠 它的子类 new实现!,抽象类虽然有构造方法,但是不能直接实例化的原因是抽象类是用来初始化的,而非实例化的

注意:在抽象类的方法权限修饰符禁止用private,因为抽象类的目的就是要实现代码复用,方便子类继承。

抽象类的中抽象方法只允许用public和默认修饰(JDK1.8之前默认是用protected修饰,但在JDK1.8之后则是默认为default修饰) , 所以抽象类的子类访问权限修饰符可以是public 或 protected


Java中只能实现单继承,但是可以利用 接口 实现多继承

2.接口Interface

  • 普通类 中只有具体的实现
  • 抽象类 中具体的实现(即普通方法)和规范(即抽象方法)都有
  • 接 口 中只有规范,只能进行约束,将约束和实现分离

接口 就是规范,定义的是一组规则,本质是契约,需要大家遵守,让不同的人实现。接口是面向对象的精髓,是对于对象的抽象。

接口 中定义的所有方法 ,默认为抽象方法 public abstract 的,意味着接口需要有实现类。抽象方法没有方法体。

接口没有构造方法

在 JDK8 中 ,接口中的方法可以被default和static修饰,但是!!!被修饰的方法必须有方法体。

接口 中定义的所有属性 默认为 静态常量 public static final,但是一般不在接口中定义属性。

接口 和抽象类一样不能直接被实例化,因为接口中没有 构造方法。

一个类可以实现多个接口,需要关键字 implement,类必须重写接口中的方法。接口和类不一样,接口中只有方法的定义,类中有方法的实现

注意:在接口的子类中,子类方法的访问权限修饰符不能低于父类(父类方法的默认权限为 public abstract),因此子类方法也只能为public

//接口类
public interface UserService {

    //接口中定义的 所有属性 默认为 静态常量   public static final
    public static final int age=18;

    //用户服务: 增删改查
    //接口中定义的 所有方法 都是抽象的  public abstract
    void add(String name);

    void delete(String name);

    void update(String name);

    void query(String name);
}
//接口类
public interface TimeService {
    void timer();
}

//类 可以实现 接口,利用关键字implement
public class UserServiceImpl implements UserService,TimeService{
    @Override
    public void add(String name) {

    }

    @Override
    public void delete(String name) {

    }

    @Override
    public void update(String name) {

    }

    @Override
    public void query(String name) {

    }

    @Override
    public void timer() {

    }
}

6.内部类和OOP实战

1.内部类

内部类 就是在一个类的内部定义一个类。如,A类中定义一个B类,则B类相对于A类就称为内部类,A类相对B类为外部类。

  1. 成员内部类

❣️ 内部类的实例化 需要调用 外部类

❣️ 内部类 可以访问 外部类的 私有变量和私有方法

public class Outer {
    private int id;
    public void out() {
        System.out.println("这是外部类的方法");
    }

    public class Inner{
        public void in() {
            System.out.println("这是内部类的方法");
        }

        //内部类 可以访问 外部类的私有变量、私有方法
        public void getId() {
            System.out.println(id);
        }

        public void getMethod() {
            out();
        }
    }
}
  1. 静态内部类

❣️ 内部类 不可以访问 外部类的私有变量和私有方法,因为 静态内部类先实例化

  1. 局部内部类

方法中定义的变量为 局部变量,方法中定义的类为 局部内部类

public class Outer2 {
    public void method() {
        //方法中定义的变量为 局部变量
        int a=10;

        //局部内部类
        class  Inner {
            public void in() {
                System.out.println("这是局部内部类的方法");
            }
        }
        
    }
}
  1. 匿名内部类

匿名内部类,即 没有名字来初始化类,不需要将实例保存到变量中。

匿名内部类可以匿名创建类、接口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值