java Object 万字详解 (通俗易懂)

news2024/11/15 8:38:52
  • 基本介绍

  • 构造方法

  • 成员方法

  • hashCode()

  • getClass()

  • toString()

  • equals()

  • finalize()

  • JavaBean重写Object类的方法

  • 重写toString

  • 重写equals


一、基本介绍

Object类是java类层次最顶层的基类(父类),所有类都是直接或间接继承自Object类,因此,所有类都可以使用Object类中的成员方法。

Object类属于java.base模块,java.lang包下(java.lang包下的类可以直接使用,不需要导包),如下图所示 :


二、构造方法

Object() : 构造一个对象。

如下图所示 :

Object类仅一个构造器,根据继承机制,所有子类在初始化前都会默认优先调用该构造器。


三、成员方法

0.总览 :

Object类常用的方法,如下图所示 :

像notify,wait这些与线程相关的

方法,因为我们还没有讲到java高级篇——多线程的内容,因此这里不做说明。我们来一起看一看up用粗线条标注出的这五个方法

①int hashCode()

返回当前对象的哈希码值,该方法通过对象的地址值进行计算,不同对象的返回值一般不同

②Class <?> getClass()

返回调用此方法的对象的运行时类对象(字节码文件对象)

③String toString()

返回该对象的字符串表示(默认打印的是"全类名 + @ + 哈希码值的十六进制")

④boolean equals()

返回其他某个对象是否与此对象“相等”(默认情况下比较的是两个对象的引用)

⑤void finalize()

当“垃圾回收器”确定不存在该对象的更多引用时,由对象的垃圾回收器调用此方法

1.hashCode() :

其实我们在上一专题的封装篇中,就已经提到过hashCode方法,并且还给出了hashCode的应用和常规协定。不知道大家是否还有印象,如果忘了也不要紧,这里再给大家演示一下 :

演示 :

up以HashCode_类为测试类,以Student类为演示类。

代码如下 :

package knowledge.api.objectmethods;

/**
 * @author : Cyan_RA9
    1. hashCode() : 返回当前对象的哈希码值,该方法通过对象的地址值进行计算,
                 不同对象的返回值一般不同。
 */
public class HashCode_ {
    public static void main(String[] args) {
        //创建学生类对象
        Student student_0 = new Student();
        Student student_1 = new Student();
        //比较不同学生对象的哈希码值
        System.out.println("student_0对象的哈希码值为 : " + student_0.hashCode());
        System.out.println("student_1对象的哈希码值为 : " + student_1.hashCode());
        System.out.println("student_0对象的哈希码值为 : " + student_0.hashCode());
    }
}

class Student {}

运行结果 :

从运行结果可以看出,当我们打印不同对象的哈希码值时,得到的结果不同。而同一对象的哈希码值相同。

2.getClass() :

getClass方法需要用一个Class类来作接收,即获取字节码文件对象(即Class对象)。并且getClass方法要通过对象来调用,因此使用前一定要创建一个对象。这个方法呢,其实我也讲过😂。只不过是在未来的java反射专题(虽然我已经写好了)。同样的,不要紧,再来演示一下不就完了。

演示 :

up以GetClass_类为测试类,以Grape类和Apple类作为演示类。

代码如下 :

package knowledge.api.objectmethods;

/**
 * @author : Cyan_RA9
   2.Class <?> getClass() : 返回调用此方法的对象的运行时类对象(字节码文件对象)
 */
public class GetClass_ {
    public static void main(String[] args) {
        //创建葡萄类对象
        Grape grape_0 = new Grape();
        Grape grape_1 = new Grape();
        //获取葡萄类的Class对象
        Class class_grape_0 = grape_0.getClass();
        Class class_grape_1 = grape_1.getClass();
        Class grape_0_class = grape_0.getClass();
        //比较通过葡萄类不同对象获得的葡萄类的Class对象有什么不同。
        System.out.println("grape_0对象的字节码文件对象是:" + class_grape_0);
        System.out.println("grape_1对象的字节码文件对象是:" + class_grape_1);
        System.out.println("grape_0对象的字节码文件对象是:" + grape_0_class);
        System.out.println("--------------------------------------------------");
        
        //创建苹果类对象
        Apple apple_0 = new Apple();
        Apple apple_1 = new Apple();
        //获取苹果类的Class对象
        Class apple_0_class = apple_0.getClass();
        Class apple_1_class = apple_1.getClass();
        //比较通过苹果类不同对象获得的苹果类的Class文件有什么不同
        System.out.println("apple_0对象的字节码文件对象是:" + apple_0_class);
        System.out.println("apple_1对象的字节码文件对象是:" + apple_1_class);
    }
}

class Grape {}
class Apple {}

运行结果 :

从输出结果我们可以看出,一个类只有一个字节码文件对象。我们通过创建同一个类的不同对象来分别调用getClass方法,得到的Class对象是相同的。而不同类的字节码文件是不同的。同时,我们也能发现字节码文件对象的格式为“class + 类的正名(类的正名 = 包类+ 类名)

3.toString() :

关于toString方法要注意一点 : 当我们直接输出一个对象时,默认调用toString方法

演示 :

up以ToString_类为测试类,以Animal类为演示类。

代码如下 :

package knowledge.api.objectmethods;

/**
 * @author : Cyan_RA9
    3. toString() : 返回该对象的字符串表示(默认打印的是"全类名 + @ + 哈希码值的十六进制")
 */
public class toString_ {
    public static void main(String[] args) {
        //创建Animal类对象
        Animal animal_0 = new Animal();
        Animal animal_1 = new Animal();
        Animal animal_2 = new Animal();
        //toString() 方法的返回值类型为String类型(也可不做接收)
        String animal_0_string = animal_0.toString();
        System.out.println("animal_0对象的字符串表示是:" + animal_0_string);
        System.out.println(animal_0);
        System.out.println("------------------------------------------------");
        System.out.println("animal_1对象的字符串表示是:" + animal_1.toString());
        System.out.println("animal_2对象的字符串表示是:" + animal_2.toString());
    }
}

class Animal {}

运行结果 :

运行结果可以验证我们之前的结论——当我们直接输出一个对象时,默认调用toString方法。而且toString() 方法默认打印的的确是“类的正名 + @ + 哈希码值的十六进制”。当然,可能有p小将(Personable小将,指风度翩翩的人)要怀疑这里“@”后面跟着的一大堆玩意儿是不是当前对象哈希码值的十六进制?

哎😂,其实验证方法也很简单,你先把这里的某个十六进制数转换成十进制数,然后利用hashCode() 方法打印出该对象的哈希值,比对一下就知道了。当然up这里就不演示了,绝不是因为我懒!是因为我已经明确知道结论了,才给大家演示的,对不对?

这不是重点。大家有没有想过,toString() 方法既然要打印出对象的字符串表示形式,那肯定是要有用的啊,最起码给人直观想象的机会。但是现在就这一堆乱七八糟的玩意儿,给谁第一眼看了也觉得糟心。那怎么办?诶~,别急,等等我们讲到子类重写Object类成员方法时再说。

4.equals() :

Object类中的equals()方法默认比较的是两个对象的引用。

演示 :

up以Equals_类为测试类,以Teacher类为演示类。

代码如下 :

package knowledge.api.objectmethods;

/**
 * @author : Cyan_RA9
    4. equals() : 返回其他某个对象是否与此对象“相等”(默认情况下比较的是两个对象的引用)
 */
public class Equals_ {
    public static void main(String[] args) {
        //创建教师类对象
        Teacher teacher_0 = new Teacher();
        Teacher teacher_1 = new Teacher();
        //通过对象调用equals() 方法
        System.out.println("teacher_0和teacher_1是一个对象吗?" + teacher_0.equals(teacher_1));
        System.out.println("teacher_0和teacher_0是一个对象吗?" + teacher_0.equals(teacher_0));
    }
}

class Teacher {}

相信大家看代码也能感觉出来了——这方法的原版没什么意义!你只比较个地址值有个啥用?雷声大雨点小!我们创建对象的目的是什么?创建对象是为了描述某一类事物的一个具体存在,每个对象的属性和行为都不尽相同。所以,我想你也猜到了,这个方法也要在子类重写的。

5.finalize() :

垃圾回收机制的调用,是由系统来决定的,即有自己的GC算法;也可以通过System.gc()来尝试主动触发,虽然也有可能无效。你也可以重写此方法,做一些释放资源的操作。

finalize()方法在实际开发中用的并不多,对于初学者几乎用不到,因此这里不做演示


四、JavaBean重写Object类的方法

0.需求 :

实际开发中,通常需要将对象转换成字符串形式进行运输,也需要对即将使用的对象进行相等判断。而toString() 方法和equals() 方法本身的特点无法实现以上需求。因此,这时候就需要我们定义标准JavaBean类,并重写Object类的toString() 方法 和 equals() 方法

IDEA中提供了自动重写toString和equals方法的机制,可以使用快捷键Alt + Enter,选择要定义或重写的方法,即可自动完成。

1.重写toString() 方法

up以ToString_EX类为测试类,以Teacher类为演示类。

代码如下 :

package knowledge.api.objectmethods.override_;

/**
 * @author : Cyan_RA9
 * @purpose : 重写Object类的toString方法
 */
public class ToString_EX {
    public static void main(String[] args) {
        Teacher teacher_0 = new Teacher();
        teacher_0.setName("王斌");
        teacher_0.setAge(44);
        teacher_0.setSalary(20000);

        Teacher teacher_1 = new Teacher("许银川", 48, 100000);

        //直接输出对象,默认调用toString() 方法
        System.out.println(teacher_0);
        System.out.println(teacher_1);
    }
}

class Teacher {     /** 以JavaBean标准来敲 */
    //成员变量
    private String name;
    private int age;
    private double salary;

    //构造器
    public Teacher() {}
    public Teacher(String name, int age, double salary) {
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    //getter,setter方法
    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 double getSalary() {
        return salary;
    }
    public void setSalary(double salary) {
        this.salary = salary;
    }

    //重写的toString() 方法
    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                '}';
    }
}

运行结果 :

可以看到,重写后的toString方法本身并不复杂,就是返回了一个拼接后的字符串。而当我们在Teacher类中重写toString方法后,输出Teacher类对象调用的就是我们重写后的toString方法,成功打印出了Teacher类对象的相关信息。因此,重写toString() 方法的目的,往往是将对象的信息能够显式地打印出来,让我们看到。

2.重写equals() 方法(重点)

up以Equals_EX类为测试类,以Animal类为演示类。

代码如下 :

package knowledge.api.objectmethods.override_;

import java.util.Objects;

/**
 * @author : Cyan_RA9
 * @purpose : 重写Object类的equals方法
 */
public class Equals_EX {
    public static void main(String[] args) {
        //利用带参构造创建不同Animal类对象
        Animal animal_0 = new Animal("猫", 15);
        Animal animal_1 = new Animal("狗", 12);
        Animal animal_2 = new Animal("猫", 15);
        //查看不同Animal对象的信息
        System.out.println("animal_0对象的信息为:" + animal_0);
        System.out.println("animal_1对象的信息为:" + animal_1);
        System.out.println("animal_2对象的信息为:" + animal_2);
        System.out.println("----------------------------------------------");
        //通过重写后的equals方法比较不同对象的信息是否相同
        System.out.println("animal_0对象和animal_1对象信息相同吗?" + animal_0.equals(animal_1));
        System.out.println("animal_0对象和animal_2对象信息相同吗?" + animal_0.equals(animal_2));
        System.out.println("animal_1对象和animal_2对象信息相同吗?" + animal_1.equals(animal_2));
    }
}

class Animal {      /** JavaBean标准 */
    //成员变量
    private String species_name;
    private int average_age;
    
    //构造器
    public Animal() {}
    public Animal(String species_name, int average_age) {
        this.species_name = species_name;
        this.average_age = average_age;
    }

    //getter,setter方法
    public String getSpecies_name() {
        return species_name;
    }
    public void setSpecies_name(String species_name) {
        this.species_name = species_name;
    }

    public int getAverage_age() {
        return average_age;
    }
    public void setAverage_age(int average_age) {
        this.average_age = average_age;
    }

    //重写equals方法
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Animal animal = (Animal) o;
        return average_age == animal.average_age && 
                    species_name.equals(animal.species_name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(species_name, average_age);
    }

    //重写toString方法以打印出对象的信息
    @Override
    public String toString() {
        return "Animal{" +
                "species_name='" + species_name + '\'' +
                ", average_age=" + average_age +
                '}';
    }
}

运行结果 :

我们先来解读一下关于equals方法的重写 :

//重写equals方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Animal animal = (Animal) o;
return average_age == animal.average_age &&
species_name.equals(animal.species_name);
}

解读①——该方法的形参列表是一个Object类型的对象,也就是多态了。

解读②——方法第一行是一个if条件语句的判断,判断条件“this == o”中,用到了比较运算符“==”,我们之前讲过,==比较运算符如果判断引用类型,判断的是二者的地址是否相同,即判定是否为同一对象;因此这里就是像看看你要判断的对象是不是它本身,如果判断为true,意思就是你拿一个对象和它自己比去了。那还用比吗😅,这不就和你照镜子一样,比个🐔儿?因此直接return true,不再进行后续的比较。

解读③——接着,又来了第二个if条件语句的判断,判断条件“o == null || getClass() != o.getClass())”中,由逻辑运算符短路或“||”分为了两部分,短路或的判断中,从左向右执行,且只要满足第一部分的判断,之后的部分便不再执行。第一部分“o==null”,是判断传入的对象是否为空。你想,一个在堆空间中真正存在的对象和一个空能比出个啥来吗?就像你比身高,让你和空气比,这不虚空对线呢😅?因此,如果传入的对象为空,立刻return false,没啥比头。来看第二部分“getClass() != o.getClass())”,这不我们前面刚说过getClass方法么,巧了😋。其实,第一个getClass() 前面隐含了“this.”,当然你也可以手动加上。这部分判断是看你传入的对象和调用该方法的对象是否是同一类对象。因为一个类的只有一个字节码文件,因此同一个类的字节码文件对象一定相同。你想,如果一条狗和你手里的泡泡糖都叫“大大”,那**能比么?因此,如果第一部分判断条件不通过,说明传入的对象不为空;如果第二部分判断条件不通过,说明传入的对象和调用方法的对象是同一类型的对象,可做后续的比较。反之,return false,不再进行后续的判断。

解读④——当前两个if条件语句都没有把o对象拦下来后,我们已经确定传入的对象既不是调用方法的对象本身,也不为空,并且和调用方法的对象是同一类对象。这时候它来了一个强制转型“Animal animal = (Animal) o;”,没毛病吧,妥妥地强转,原因估计你也猜到了,现在的o对象是一个Object类型的对象,根据多态的弊端,父类引用不能直接使用子类对象的特有成员。因此,这里要把o对象进行强制向下转型,以改变o对象的编译类型,使得做接收后的新的引用变量可以调用要判断类型(此处为Animal类)的特有成员,以便进行后续的判断。

解读⑤——最后就可以开始判断了。IDEA也很干脆,直接return了一个boolean类型。注意,具体的比较语句中up还要说一下,判断非引用类型直接用比较运算符“==”即可,如果判断的是引用类型,比如说字符串,要使用“字符串.equals()”的形式来判断,很明显字符串属于String类,而String类中重写了Object类的equals方法,可以比较两个字符串的内容是否相同。

其次,看到代码后,可能会有小伙伴儿们疑惑——

为什么我用快捷键重写equals方法时,IDEA会默认同时重写equals方法和hashCode方法呢?

这要说起来可就大费篇章了😂。这与hashCode的常规协定有关,也是为了避免某些程序执行出现异常的情况。现在不需要深究,大家了解一下即可。等你到找工作面试的时候,你不想懂也得懂它了🤗。


五、总结

其实,关于Object类中的方法,大家只要理解这几个原初的方法,并且掌握toString方法和equals方法的重写问题就没问题了。

🆗,以上就是我们关于API常用类Object类内容分享的全部内容了,下一节String类我们不见不散,感谢阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/382943.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

进程概念(详细版)

进程的概念本文主要介绍进程的相关知识 文章目录认识冯诺依曼体系结构操作系统的基本概念操作系统的作用是什么系统调用和库函数相关概念进程基本概念描述进程进程控制块(PCB)task_struct 结构体进程是如何被操作系统管理起来的先描述再组织描述好&#xff0c;组织好&#xff0…

taobao.item.img.delete( 删除商品图片 )

&#xffe5;开放平台免费API必须用户授权 删除商品图片 公共参数 请求地址: HTTP地址&#xff1a;http://gw.api.taobao.com/router/rest 公共请求参数: 公共响应参数: 请求参数 响应参数 点击获取key和secret 请求示例 TaobaoClient client new DefaultTaobaoClient(url…

学习ifconfig实战技巧,成为网络管理高手

文章目录前言一. ifconfig 命令介绍二. 语法格式及常用选项三. 参考案例3.1 显示网络设备信息3.2 启动和关闭指定的网卡3.3 对指定的网卡设备执行修改IP地址操作3.4 启动和关闭ARP协议3.5 使用ifconfig添加网卡总结前言 大家好&#xff0c;又见面了&#xff0c;我是沐风晓月&a…

Neovim for Rust

之前学习 Rust 一直使用的都是 VScode rust-analyzer&#xff0c;最近看到有网友安利 Neovim 于是就试了试&#xff0c;发现确实美观&#xff0c;好用&#xff0c;而且内存占用比较小。我个人很喜欢&#xff0c;也推荐给给大家。 前提&#xff1a;得有个代理&#xff0c;不然大…

一个自学自动驾驶(决策规划控制方向)的研究生学习资料总结(附相关资料的链接)

项目仓库 欢迎访问我的Github主页 项目名称说明chhCpp学习C仓库chhRobotics学习自动驾驶、控制理论相关仓库(python实现)chhRobotics_CPP学习自动驾驶、控制理论相关仓库(c实现)chhML 、chh-MachineLearning学习机器学习仓库chhRL学习强化学习仓库chhTricks存放一些有意思的t…

Unity烘焙常见问题

本文首发于公众号洪流学堂&#xff0c;未经允许&#xff0c;不可转载。 Unity中光影烘焙经常会遇到很多莫名其妙的问题&#xff0c;大智总结了一个问题解决手册&#xff0c;本文是比较常见的一些问题&#xff0c;还有一些不那么常见的问题&#xff0c;《手册全文pdf》获取方法&…

【2023蓝桥杯】2018年第九届C/C++A组真题(解析笔记)

目录 ♥【分数】循环累乘/快速幂运算/最大公因数 ♥【星期一】闰年/周期循环 ♥【乘积尾零】遍历/取余/取整 ♥【第几个幸运数】 遍历 ♥【打印图形】dfs填空 【航班时间】字符串/思维/时间换算 【三体攻击】差分&#xff01;中等难度 ♥【全球变暖】dfs/连通块计数 *…

Python解题 - CSDN周赛第33期

本期四道题全考过&#xff0c;题解在网上也都搜得到。。。没有想法&#xff0c;顺手水一份题解吧。 第一题&#xff1a;奇偶排序 给定一个存放整数的数组&#xff0c;重新排列数组使得数组左边为奇数&#xff0c;右边为偶数。 输入描述&#xff1a;第一行输入整数n。(1<n<…

深究Java Hibernate框架下的Deserialization

写在前面 Hibernate是一个开源免费的、基于 ORM 技术的 Java 持久化框架。通俗地说&#xff0c;Hibernate 是一个用来连接和操作数据库的 Java 框架&#xff0c;它最大的优点是使用了 ORM 技术。 Hibernate 支持几乎所有主流的关系型数据库&#xff0c;只要在配置文件中设置好…

在 The Sandbox 中以全新的 Rabbids 体验庆祝兔年!

育碧(Ubisoft) 和 The Sandbox 联手为你们带来终极的农历新年体验&#xff01; 穿戴上你们新鲜出炉的 Rabbids 人物化身来参加派对吧&#xff0c;保证震撼整个元宇宙&#xff01;这个全新体验为 Rabbids 人物化身持有者专属。没有获得 Rabbids 人物化身吗&#xff1f;不要担心&…

【Java】P2 基础语法与运算符

Java 基础语法 运算符Java注释方法基本数据类型驼峰命名法Scanner类基本运算除法隐式转换逻辑运算符 以及 短路逻辑运算符三元运算符前言 上一节内容涵盖Java的基础知识&#xff0c;包含安装下载&#xff0c;JDK与JRE等。 链接&#xff1a;https://blog.csdn.net/weixin_43098…

java 多线程处理任务

首先介绍一下我的使用场景我在redis set集合中有几十万个行程id&#xff0c;我需要一个脚本来离线计算每个行程的里程&#xff0c;计算完了之后&#xff0c;将公里数填到mongodb的表中&#xff0c;并且删除set集合中这个元素。我的目录结构我们创建一个maven项目&#xff0c;然…

STM32之PWM

PWMPWM&#xff0c;英文名Pulse Width Modulation&#xff0c;是脉冲宽度调制缩写&#xff0c;它是通过对一系列脉冲的宽度进行调制&#xff0c;等效出所需要的波形&#xff08;包含形状以及幅值&#xff09;&#xff0c;对模拟信号电平进行数字编码&#xff0c;也就是说通过调…

Office 365用户报告

通过ADManager Plus的现成Office 365用户报告&#xff0c;您无需复杂的PowerShell脚本&#xff0c;即可查找Office 365环境中用户的重要信息。使用这些报告&#xff0c;您只需点击几次基于Web的控制台&#xff0c;即可提取Office 365环境中活动和不活动用户数量等信息&#xff…

Celery 分布式任务队列

1. 认识 Celery Celery 是一个 基于 Python 开发的分布式异步消息任务队列&#xff0c;可以实现任务异步处理&#xff0c;制定定时任务等。 异步消息队列&#xff1a;执行异步任务时&#xff0c;会返回一个任务 ID 给你&#xff0c;过一段时间后拿着任务 ID 去取执行结果定时…

进程的介绍

文章目录一.进程的概念1.1概念1.2进程的组成1.2.1 PCB中描述进程的特征二.进程的虚拟地址空间三.进程间的通信引入线程一.进程的概念 1.1概念 百科的介绍: 换句话说,一个跑起来的程序,就是一个进程,也就是在操作系统中运行的exe程序就是一个进程,如下图的进程列表 进程是操…

【女士,房间墙上凿个洞,看你在干嘛~】安全攻防内网渗透-绕过防火墙和安全检测,搭建DNS隐蔽隧道

作者&#xff1a;Eason_LYC 悲观者预言失败&#xff0c;十言九中。 乐观者创造奇迹&#xff0c;一次即可。 一个人的价值&#xff0c;在于他所拥有的。所以可以不学无术&#xff0c;但不能一无所有&#xff01; 技术领域&#xff1a;WEB安全、网络攻防 关注WEB安全、网络攻防。…

Java并发包提供了哪些并发工具类?

第19讲 | Java并发包提供了哪些并发工具类&#xff1f; 通过前面的学习&#xff0c;我们一起回顾了线程、锁等各种并发编程的基本元素&#xff0c;也逐步涉及了 Java 并发包中的部分内容&#xff0c;相信经过前面的热身&#xff0c;我们能够更快地理解 Java 并发包。 今天我要…

SpringBoot集成Swagger3.0(入门) 02

文章目录Swagger3常用配置注解接口测试API信息配置Swagger3 Docket开关&#xff0c;过滤&#xff0c;分组Swagger3常用配置注解 ApiImplicitParams,ApiImplicitParam&#xff1a;Swagger3对参数的描述。 参数名参数值name参数名value参数的具体意义&#xff0c;作用。required参…

mes系统核心业务流程及应用场景介绍

现在许多企业已经开始使用MES系统控制和管理工厂的生产过程&#xff0c;实时监控、诊断和控制生产过程&#xff0c;完成单元集成和系统优化。本文将为大家具体介绍一下MES系统的业务流程。 MES系统业务流程 1、计划调度MES系统承接了ERP订单&#xff0c;开始干预生产。该模块…