Java模块化系统:引领代码革命与性能飞跃

JDK工程结构的问题

在说Java模块化系统之前,先来说说Java9之前的JDK在工程结构上的问题,从JDK本身的问题说起,Java从1996年发布第一版到2017年发布Java9,中间经历了近20年的时间,在这期间发布了无数个大大小小的版本用来支撑新的特性。

在Java新特性越来越丰富的同时,也带来了相应的问题。JDK8是一个广泛使用的版本,我们就以JDK8为例,先来看看目录结构
 

在这里插入图片描述


在JDK8以及之前的版本,我们安装的时候会安装两部分内容

  • JDK(Java Development Kit)主要用于开发者提供了开发工具和环境
  • JRE(Java Runtime Environment)主要提供Java运行时环境

JDK是开发Java应用的完整套装,而JRE则是为了支持已编译的Java程序在任何计算机上运行而设计的环境。JDK内部包含了JRE,以方便开发者在开发的同时也能直接运行和测试他们的代码

在jre/bin目录下有一个rt.jar文件,表示的是runtime,即运行时。JVM会加载这整个文件来支持Java运行时环境,而rt.jar文件的大小已经达到50-60M,也就是说在运行你的Java程序之前,就需要花这么多内存来加载Java运行时环境,我们来看看rt.jar中包含哪些内容
 

在这里插入图片描述


我们使用解压工具打开rt.jar可以清晰的看到,里面包括的内容很全,基本上包括了Java的方方面面,都给你加载进去了。就算你只写一个HelloWord,它也给你加载了Applet、awt等你根本不会用到的东西。现在的服务器和个人电脑随便都是8G、16G以上的内存,对于rt.jar占用的这点内存可能没什么感觉,但在一些对于内存很敏感的领域,Java这种方式就显得不太合理。Java官方可能也意识到了这个问题,所以在Java9的时候推出了Java平台模块系统(Java Platform Module System,JPMS)

Java平台模块系统(Java Platform Module System,JPMS)

JPMS是在Java9发布的,其实从Java7开始官方就在准备JPMS,本来准备在Java8中引入JPMS的,实在是改动太大,到Java9中才正式发布。其实做过开发的都会想的到,模块化相当于要从整体上重构整个系统,结构调整巨大,对于整个系统考验是很大的,这可能也是JPMS从Java7开始准备,直到Java9才发布的原因。

前面我们说过,在Java8及之前的版本中,其实是包括JDK和JRE两个部分的。但从Java9之后,就没有专门的JRE了,因为模块化之后,自己可以选择JVM加载哪些模块,相当于按需加载就行了,你写HelloWord可能只需要一个加载java.base就行了。
下面是JDK11的结构
 

在这里插入图片描述


在JDK安装目录下有一个jmods目录,在该目录下就定义了JDK中各个模块,以.jmod结尾的文件就是JDK中定义的各个模块,我们打开java.base.jmod文件看一下
 

在这里插入图片描述


可以看到在java.baseclass/java/目录中,包括了一些Java基础用到的lang、math、nio等基础包,没有包插applet、awt等不常用的包。
这样按模块化划分之后,一方面可以更好的管理JDK的各个模块,另外一方面对于使用者来说,也不用像旧版JDK那样一股脑把所有的内容加载到JVM中,这样更加合理,也更节省资源。

Java模块化系统以克服当前所存在的局限时,主要设定了两个目标

  • 对JDK本身进行模块化
  • 提供一个应用程序可以使用的模块系统

上面我们已经看到了JDK本身模块化的改造,下面我们就来看看应用程序是如何使用模块系统的

应用程序模块化实现

应用程序实现模块化只需要简单的三步就可以完成

  • 定义模块
  • 导出模块
  • 引用模块

先整体看一下,我们定义了三个模块userModule、OrderModule、GoodsModule,项目的结构如下:

在这里插入图片描述

module-info.java文件

module-info.java文件是用来定义模块的,在模块的src目录下定义一个module-info.java文件,内容如下

module UserModule {
    
}

简单的定义了一个UserModule的模块,里面内容是空的
现在三个模块是独立的,假如在OrderModule中需要使用UserModuler的UserService,直接使用肯定是引用不到的,需要进行exports

exports

如果需要将模块中的内容对外,需要在module-info.java中把相应的包exports出去

module UserModule {
    exports com.user;
}

如上所示,表示UserModule将com.user包对外提供服务

requires

如果需要引用其他模块的内容,需要先使用requires将模块引用进当前模块,如下

module OrderModule {
    requires UserModule;
}

如上所示,表示OrderModule引用了UserModule,如此在OrderModule中就可以使用UserModule中exports出来的包

    public static void main(String[] args) {
        UserService userService = new UserService();
        userService.register();
    }

如上所示,在OrderModule中就可以直接引入UserService了

如果你只想将UserModule开放给GoodsModule,可以这样写

module UserModule {
    exports com.user to GoodsModule;
}

这样就算OrderModule引用了UserModel,也没办法使用UserService,因为UserModule只开放给GoodsModule了

以上就是一个使用模块化来实现模块之间相关调用的简单例子,当然实际的模块化系统不可能这么简单,此处只起到一个抛转引玉的作用,如果对模块化系统比较感兴趣可以去JDK官网了解详细的信息

模块化的好处

1、强封装性

类和包可以被模块化,只有模块之间声明的接口是对外可见的,提高了代码的封装性,减少了不必要的耦合

2、明确的依赖管理

块之间通过requires声明依赖,明确指出了哪些模块需要哪些其他模块,避免了隐式依赖和类路径冲突

3、运行时性

JVM可以仅加载运行应用程序所需的模块,减少了内存占用,提高了启动速度和运行时性能

4、安全性和隔离

模块边界强化了安全性,限制了代码的访问权限,降低了攻击面

通过模块化,Java开发者可以构建更加健壮、高效且易于维护的大型应用程序

前端的世界总是在不断变化,作为开发者,我们需要保持好奇心和学习热情,不断探索新的技术,只有这样,我们才能在这个快速发展的时代中立于不败之地。Web Components 就是这样一个值得我们深入探索的领域,让我们拭目以待,它将给前端世界带来怎样的变革。

介绍一款程序员都应该知道的软件JNPF快速开发平台,很多人都尝试用过它,它是功能的集大成者,任何信息化系统都可以基于它开发出来。

这是一个基于 Java Boot/.Net Core 构建的简单、跨平台快速开发框架。前后端封装了上千个常用类,方便扩展;集成了代码生成器,支持前后端业务代码生成,实现快速开发,提升工作效率;框架集成了表单、报表、图表、大屏等各种常用的 Demo 方便直接使用;后端框架支持 Vue2、Vue3。如果你有闲暇时间,可以做个知识拓展。

看完本文如果觉得有用,记得点个赞支持,收藏起来说不定哪天就用上啦~

  • 24
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的Unity汽车飞跃斜坡的代码示例: ```csharp public class CarController : MonoBehaviour { public WheelCollider[] wheelColliders; public Transform[] tireMeshes; public float motorTorque = 500f; public float maxSteerAngle = 30f; public float brakeTorque = 5000f; public float jumpForce = 10000f; public float jumpAngle = 45f; private Rigidbody carRigidbody; private float currentSteerAngle; private float currentMotorTorque; private bool isJumping; private void Start() { carRigidbody = GetComponent<Rigidbody>(); } private void FixedUpdate() { float horizontalInput = Input.GetAxis("Horizontal"); float verticalInput = Input.GetAxis("Vertical"); currentSteerAngle = maxSteerAngle * horizontalInput; currentMotorTorque = motorTorque * verticalInput; ApplySteer(); ApplyMotorTorque(); UpdateTireMeshes(); if (Input.GetKeyDown(KeyCode.Space) && !isJumping) { Jump(); } } private void ApplySteer() { foreach (WheelCollider wheelCollider in wheelColliders) { if (wheelCollider.steerAngle != currentSteerAngle) { wheelCollider.steerAngle = currentSteerAngle; } } } private void ApplyMotorTorque() { foreach (WheelCollider wheelCollider in wheelColliders) { if (wheelCollider.motorTorque != currentMotorTorque) { wheelCollider.motorTorque = currentMotorTorque; } if (Mathf.Abs(currentMotorTorque) > 0 && wheelCollider.brakeTorque != 0) { wheelCollider.brakeTorque = 0; } else if (Mathf.Abs(currentMotorTorque) == 0 && wheelCollider.brakeTorque != brakeTorque) { wheelCollider.brakeTorque = brakeTorque; } } } private void UpdateTireMeshes() { for (int i = 0; i < tireMeshes.Length; i++) { Quaternion rotation; Vector3 position; wheelColliders[i].GetWorldPose(out position, out rotation); tireMeshes[i].position = position; tireMeshes[i].rotation = rotation; } } private void Jump() { isJumping = true; carRigidbody.AddForce(transform.up * jumpForce); carRigidbody.AddForce(transform.forward * jumpForce * Mathf.Tan(jumpAngle * Mathf.Deg2Rad)); StartCoroutine(ResetJump()); } private IEnumerator ResetJump() { yield return new WaitForSeconds(1f); isJumping = false; } } ``` 该脚本附加到汽车对象上,并使用WheelCollider和Rigidbody组件来控制汽车的运动。在FixedUpdate方法中,它根据输入调整汽车的转向和动力输出,并更新轮胎网格的位置和旋转。如果玩家按下空格键,它将调用Jump方法来使汽车跳跃。在Jump方法中,它使用AddForce方法来给汽车一个向上的力和一个向前的力,使其跳跃,并使用协程在一段时间后重置isJumping标志。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值