Java与Python结合开发是指将Python语言与Java语言结合起来,利用它们的优势,共同开发一个应用程序。
Python语言拥有许多强大的特性,如易于学习、快速开发、可扩展性等,而Java语言则拥有跨平台、可靠性、安全性等优势,因此将它们结合起来,可以发挥出更大的作用。
在一个大型企业系统中,Java可能用于后端服务和业务逻辑,而Python可能用于数据分析和机器学习任务。在这种情况下,两种语言需要能够协同工作,以实现全面的功能。
操作系统:Win11
Java开发环境:安装并配置了Java开发环境,包括Java Development Kit (JDK) 和设置了正确的环境变量。(这里就不详细讲JDK的安装了,可以参考 最详细jdk安装以及配置环境(保姆级教程))
Python解释器:安装Python解释器,并且可以在命令行中执行python命令。可以通过在命令行中输入python --version来验证Python是否正确安装。
下面开始下载安装Python、配置环境变量。
python --version
系统需要有Python解释器环境。
Java提供了ProcessBuilder类,可以在Java代码中调用外部程序或脚本。我们可以利用这个类调用Python解释器,从而执行Python的代码。通过使用ProcessBuilder类,我们可以传递命令行参数,获取脚本的输出结果,并实现Java与Python的互操作性。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class PythonTest {
public static void main(String[] args) {
try {
// 创建ProcessBuilder对象,指定要执行的命令和参数
ProcessBuilder pb = new ProcessBuilder("python", "-c", "print('Hello, Python!')");
// 启动子进程并等待其完成
Process process = pb.start();
// 读取子进程的输出结果
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
// 等待子进程完成并获取退出值
int exitCode = process.waitFor();
System.out.println("Exit Code: " + exitCode);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
def say_hello(name):
return 'Hello, ' + name + '!'
if __name__ == '__main__':
print(say_hello('Python'))
public static void main(String[] args) {
try {
// 创建ProcessBuilder对象,指定要执行的命令和参数
ProcessBuilder pb = new ProcessBuilder("python", getResourceFilePath("test.py"));
// 启动子进程并等待其完成
Process process = pb.start();
// 读取子进程的输出结果
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
// 等待子进程完成并获取退出值
int exitCode = process.waitFor();
System.out.println("Exit Code: " + exitCode);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
/**
* 获取资源文件路径
* * @param fileName 文件名称
* @return 文件绝对路径
*/
public static String getResourceFilePath(String fileName) {
// 获取当前项目的根目录路径
String rootPath = System.getProperty("user.dir");
// 拼接资源文件夹的相对路径
String resourceFolderPath = rootPath + File.separator + "src" + File.separator + "test" + File.separator + "resources" + File.separator + fileName;
// 创建File对象,并打印资源文件夹的绝对路径
File resourceFolder = new File(resourceFolderPath);
// 打印资源文件夹的绝对路径
return resourceFolder.getAbsolutePath();
}
Jython 是一个将Python代码嵌入到Java中的工具,它使Java应用程序能够调用和执行Python代码。这为Java开发人员提供了在其应用程序中集成Python脚本的能力。
在maven坐标中添加:
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.7.2</version>
</dependency>
编写Java代码测试:
public static void main(String[] args) {
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.exec("print('Hello from Python!')");
}
运行结果:
这个涉及到C语言编码,使用JNI调用Python C API来执行Python代码。通过C去调用python,再在Java中调用native方法去执行,需要将C语言编写的代码编译成动态链接库,并在Java代码中加载它。【过程较复杂,这里不做过多描述】
GPT示例:
#include <Python.h>
jint JNICALL Java_PythonCaller_callPythonCode(JNIEnv *env, jobject obj) {
PyObject *pModule = NULL, *pFunc = NULL, *pResult = NULL;
jint result = 0;
// 初始化Python解释器
Py_Initialize();
// 导入Python模块
pModule = PyImport_ImportModule("test");
if (pModule == NULL) {
PyErr_Print();
goto CLEANUP;
}
// 获取Python函数对象
pFunc = PyObject_GetAttrString(pModule, "get_number");
if (pFunc == NULL || !PyCallable_Check(pFunc)) {
PyErr_Print();
goto CLEANUP;
}
// 调用Python函数并获取结果
pResult = PyObject_CallObject(pFunc, NULL);
if (pResult == NULL) {
PyErr_Print();
goto CLEANUP;
}
// 将Python结果转换为Java整数类型
result = (jint) PyLong_AsLong(pResult);
CLEANUP:
// 释放Python对象和解释器资源
Py_XDECREF(pResult);
Py_XDECREF(pFunc);
Py_XDECREF(pModule);
Py_Finalize();
return result;
}
public class PythonCaller {
static {
System.loadLibrary("callpython");
}
public native int callPythonCode();
public static void main(String[] args) {
PythonCaller caller = new PythonCaller();
int result = caller.callPythonCode();
System.out.println("Result: " + result);
}
}
gcc -shared -fpic -I /usr/include/python3.6m -o libcallpython.so callpython.c