IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> python调用java之jpype参数类型转换 -> 正文阅读

[Java知识库]python调用java之jpype参数类型转换

本章概述

python调用java,关键的一点是python 类型和 Java 类型之间的转换。这个功能借助JPype完成,Jpype提供了一系列API,帮助使用者完成python参数到java参数的转换。
本章的目的是尽可能覆盖java参数类型,通过示例演示如何将python数据类型转换为指定的java数据类型。

参数类型转换参考表

这部分原文链接如下:
http://jpype.sourceforge.net/doc/user-guide/userguide.html#conversion

下图横坐标代表java类型,竖坐标代表python类型,其中以“J”开头的,是JPype封装的类型,由于JPype是python的一个模块,所以Jpype封装的类型在这里也认为是python类型。

JPype 定义了 Python 对象和 Java 类型之间“匹配”的不同层次。这些级别是:

  • 下图空白单元格:代表对应的两个类型没有办法转换。
  • 单元格为“I”的:JPype 将根据需要进行转换,即隐式转换。
  • 单元格为“X”的:与“I”对应,是显示转换,但优先级高于隐式转换。比如有的类型同时支持隐式转换和显示转换,如果明确指定显示转换,则转换过程就是显示转换。举个例子,java的byte类型,对应到python中int、long、JByte类型都可以转换为byte类型。如果一个java函数的参数是byte类型,那么在python中调用这个java函数时,参数值可以直接填写python中的数字(python2才区分Long类型, python3统一划分为数字类型),这时是把参数自动隐式转换java的byte类型。参数值也可以填JByte(2)这样的显示转换,这时是把参数值显示转换给java中的byte类型,此时隐式转换是不生效的。

在这里插入图片描述
对于上图单元格中的数字,是对该单元格所对应的转换关系的补充说明:
(1) 如果 Python 值适合 java 本机类型,则会发生转换。

(2) 如果python字符串或unicode长度为1,则发生转换

(3) 所需对象的类型必须与java.lang.String ( java.lang.Object , java.util.Comparable )兼容

(4) 维数必须匹配,类型必须兼容

(5) 仅当需要的类型为java.lang.Object 时

(6) 仅当 JObject 包装器的指定类型是兼容的数组类时。

(7) 仅当所需的类型与包装器的指定类型兼容时。不考虑 java 对象的实际类型。

(8) 仅当requireds 类型与Java Object 实际类型兼容时。

(9) 仅当所需类型为java.lang.Object或java.lang.Class 时

(10) 只有 True 和 False 值被隐式转换为布尔值。

示例

下面通过示例演示python类型与java类型的转换,笔者为了使转换过程看起来更规范,都是使用显示转换。这样所有的转换统一依赖Jpype提供的API来完成。

byte

java :

package com.linchao;

public class myJpypeTest {

    public int test_byte(byte param){
        int res =  param + 1;
        return res;
    }

    public static void main(String[] args){
        System.out.println("Jpype Test...");
    }
}

python:

# coding: utf-8
# TransferParam。py
from jpype import JByte

def to_byte(param):
    return JByte(param)
# coding: utf-8

from jpype import JClass
import jpype
from TransferParam import to_byte



if __name__ == "__main__":
    jpype.startJVM(classpath=r"D:\myProjects\java\JpypeTest\out\artifacts\JpypeTest_v0_1\JpypeTest_v0.1.jar")

    myJpypeTest = JClass("com.linchao.myJpypeTest")()

    # 测试byte类型转换
    res = myJpypeTest.test_byte(to_byte(100))

    print(res)



输出结果

"D:\Program Files\Python39\python.exe" D:/myProjects/python/test_JPype/main.py
101

Process finished with exit code 0

第一个示例,显示了java和python的全部代码。
后面的示例,为了更清晰的排版和显示主要内容,只贴关键代码。不过完整的代码可以到指定链接获取。

short

java:

public String test_short(short param){
        int res = param + 1;
        return param + "+" + "1" + "=" + res;
    }

python:

def to_short(param):
    return JShort(param)
# 测试short类型转换
res = myJpypeTest.test_short(to_short(100))
print(res)
"D:\Program Files\Python39\python.exe" D:/myProjects/python/test_JPype/main.py
100+1=101

Process finished with exit code 0

int

java:

    public String test_int(int param){
        int res = param + 1;
        return param + "+" + "1" + "=" + res;
    }

python:

def to_int(param):
    return JInt(param)
# 测试int类型转换
res = myJpypeTest.test_int(to_int(200))
print(res)
"D:\Program Files\Python39\python.exe" D:/myProjects/python/test_JPype/main.py
200+1=201

Process finished with exit code 0

long

java:

    public String test_long(long param){
        long res = param + 1;
        return param + "+" + "1" + "=" + res;
    }

python:

def to_long(param):
    return JLong(param)
# 测试long类型转换
res = myJpypeTest.test_long(to_long(300))
print(res)
"D:\Program Files\Python39\python.exe" D:/myProjects/python/test_JPype/main.py
300+1=301

Process finished with exit code 0

float

java:

    public String test_float(float param){
        float res = param + 1;
        return param + "+" + "1" + "=" + res;
    }

python:

def to_float(param):
    return JFloat(param)
# 测试float类型转换
res = myJpypeTest.test_float(to_float(400.54))
print(res)
"D:\Program Files\Python39\python.exe" "D:\Program Files\Python39\python.exe" D:/myProjects/python/test_JPype/main.py
400.54+1=401.54

Process finished with exit code 0

double

java:

    public String test_double(double param){
        double res = param + 1;
        return param + "+" + "1" + "=" + res;
    }

python:

def to_double(param):
    return JDouble(param)
# 测试double类型转换
res = myJpypeTest.test_double(to_double(520.54))
print(res)
"D:\Program Files\Python39\python.exe" D:/myProjects/python/test_JPype/main.py
520.54+1=521.54

Process finished with exit code 0

boolean

java:

    public String test_boolean(boolean param){
        if(param == true){
            return "param is true"; 
        }
        else {
            return "param is false";
        }
    }

python:

def to_boolean(param):
    return JBoolean(param)
# 测试boolean类型转换
res = myJpypeTest.test_boolean(to_boolean(False))
print(res)
"D:\Program Files\Python39\python.exe" D:/myProjects/python/test_JPype/main.py
param is false

Process finished with exit code 0
# 测试boolean类型转换
res = myJpypeTest.test_boolean(to_boolean(True))
print(res)
"D:\Program Files\Python39\python.exe" D:/myProjects/python/test_JPype/main.py
param is true

Process finished with exit code 0

char

java:

    public String test_char(char param){
        int a = param;
        return "ascii: " + param + "->" + a;
    }

python:

def to_char(param):
    return JChar(param)
# 测试char类型转换
res = myJpypeTest.test_char(to_char("a"))
print(res)
"D:\Program Files\Python39\python.exe" D:/myProjects/python/test_JPype/main.py
ascii: a->97

Process finished with exit code 0

String

java:

    public String test_String(String param){
        return "Hello! " + param ;
    }

python:

def to_String(param):
    return JString(param)
# 测试String类型转换
res = myJpypeTest.test_String(to_String("Devin"))
print(res)
"D:\Program Files\Python39\python.exe" D:/myProjects/python/test_JPype/main.py
Hello! Devin

Process finished with exit code 0

Array

在java中,数组类型根据数组元素,可以是整形数组、字符串数组、某种对象的数组等等。但无论是什么类型的数组,在jpype中,都是通过JArray这个API来实现。
示例

int[]: JArray(JInt)
float[]: JArray(JFloat)
String[]: JArray(JString)

JArray API返回一个JClass对象,通过传入参数调用这个对象即可以得到一个数组对象。调用这个对象有两种传参方式,第一种是传入一个整数,会得到一个长度为整数的数组,数组中的元素值默认初始化值(int是0,String是None),第二种方式是传入序列,得到一个长度为序列长度,元素值为序列值的数组。
看代码演示:
先演示int[],
java:

    public int test_Array(int[] param){
        int sum = 0;
        for(int i : param){
            sum = sum + i;
        }
        return sum;
    }

python:

def to_int_array(param):
    return JArray(JInt)(param)
# 测试int[]类型转换
# 传入的数组是[0,0,0,0,0]
res = myJpypeTest.test_Array(to_int_array(5))
print(res)
"D:\Program Files\Python39\python.exe" D:/myProjects/python/test_JPype/main.py
0

Process finished with exit code 0
# 传入的数组是[1,2,3,4,5]
res = myJpypeTest.test_Array(to_int_array([1,2,3,4,5]))
print(res)
"D:\Program Files\Python39\python.exe" D:/myProjects/python/test_JPype/main.py
15

Process finished with exit code 0

再演示String[]
Java:

    public String test_Array(String[] param){
        String sum = "";
        for(String i : param){
            sum = sum + i;
        }
        return sum;
    }

python:

def to_String_array(param):
    return JArray(JString)(param)
# 测试String[]类型转换
res = myJpypeTest.test_Array(to_String_array(["我", "爱", "中", "国"]))
print(res)
"D:\Program Files\Python39\python.exe" D:/myProjects/python/test_JPype/main.py
我爱中国

Process finished with exit code 0

最后,演示一个自定义对象数组。
这个例子是在java中自定义对象,然后定义一个函数,其输入参数是自定义对象。最后在python中调用这个函数。
首先,看看在java中自定义的对象,这是一个描述动物的对象,有名字、年龄、别名三个私有属性,对外提供了一个接口返回一段自我介绍。

package params;

public class Animals {

    private String name="";
    private int age=0;
    private String alias="";

    public Animals(String name, int age, String alias) {
        this.name = name;
        this.age = age;
        this.alias = alias;
    }

    public String sayHello(){
        return "你好!我是" + this.name + ",今年" + this.age + "岁, 人们通常叫我"+ this.alias;
    }
}

java中待调用的目标函数:

//  遍历Animals数组,调用每个动物的sayHello接口,将其自我介绍打包到一个序列里并返回。
    public List<String> test_Array(Animals[] params){

        List<String> res = new ArrayList();
        for(Animals animal: params){
            res.add(animal.sayHello());
        }
        return res;
    }

接下来是python中,自定义对象数组的转换:

def to_Animal_array(param, Animal):
    return JArray(Animal)(param)
# 测试自定义对象数组类型转换
names = ["假老练", "风车车", "莽哥"]
ages = [3,2,4]
alias = ["猫儿", "耗子", "狗儿"]
# 得到Animals类定义
Animal = JClass("params.Animals")
animals = []
for i in range(3):
    # 初始化Animal,并将其加入到列表里。
    animals.append(Animal(to_String(names[i]), to_int(ages[i]), to_String(alias[i])))
# 参数准备工作已经完成,调用java函数。
res = myJpypeTest.test_Array(to_Animal_array(animals, Animal))
for i in res:
    print(i)
"D:\Program Files\Python39\python.exe" D:/myProjects/python/test_JPype/main.py
你好!我是假老练,今年3, 人们通常叫我猫儿
你好!我是风车车,今年2, 人们通常叫我耗子
你好!我是莽哥,今年4, 人们通常叫我狗儿

Process finished with exit code 0

这是一个较为综合性的示例,还涉及到了下面才要描述的自定义对象类型转换。如果这里暂时没看懂,没关系,先看下面,然后再回过头来看这个示例。

自定义Class对象

依然使用Animals对象:

package params;

public class Animals {

    private String name="";
    private int age=0;
    private String alias="";

    public Animals(String name, int age, String alias) {
        this.name = name;
        this.age = age;
        this.alias = alias;
    }

    public String sayHello(){
        return "你好!我是" + this.name + ",今年" + this.age + "岁, 人们通常叫我"+ this.alias;
    }
}

    public String test_class(Animals animals){
        return animals.sayHello();
    }

在python中调用这个函数:

# Animal类构造函数接受三个参数,但param是个序列,所以用了*
def to_java_class(cls, param):
    # 获得java class
    java_class = JClass(cls)
    # 调用java class的构造函数示例化对象
    return java_class(*param)
# 测试自定义类型转换
res = myJpypeTest.test_class(to_java_class("params.Animals", [to_String("假老练"), to_int(3), to_String("猫儿")]))
print(res)
"D:\Program Files\Python39\python.exe" D:/myProjects/python/test_JPype/main.py
你好!我是假老练,今年3, 人们通常叫我猫儿

Process finished with exit code 0

Tips:

python中的 JClass("params.Animals")
类似java中的 import params.Animals;

List

对于java中List类型对象,jpype使用java.util.ArrayList这个api来转换。
List<String>为例:
Java:

    public String test_List(List<String> params){
        String res = "";
        for(String param : params){
            res = res + param;
        }
        return res;
    }

python:

def to_list(param):
    return java.util.ArrayList(param)
# 测试自定义类型转换
res = myJpypeTest.test_List(to_list(["新","年","快","乐"]))
print(res)
"D:\Program Files\Python39\python.exe" D:/myProjects/python/test_JPype/main.py
新年快乐

Process finished with exit code 0

Map

java中的Map下常见的是HashMap和LinkedHashMap。
分别对应jpype的java.util.HashMap、java.util.LinkedHashMap两个API。使用方法是相似的。
以HashMap为例子。
java:

   	public String test_Map(HashMap<String, Integer> params){
        int age = params.get("age");
        int rmb = params.get("RMB");
        return "age:"+age+" rmb:"+rmb;
    }

python:

def to_HashMap(param):
    return java.util.HashMap(param)
# 测试自HashMap类型转换
res = myJpypeTest.test_Map(to_HashMap({to_String("age"):to_int(18), to_String("RMB"):to_int(999999)}))
print(res)

"D:\Program Files\Python39\python.exe" D:/myProjects/python/test_JPype/main.py
age:18 rmb:999999

Process finished with exit code 0

Enum

java:

package params;

public enum testEnum {
    RED("红色"), GREEN("绿色"), BLANK("白色"), YELLO("黄色");

    private String color;
    testEnum(String color) {
        this.color = color;
    }

    public String getColor() {
        return color;
    }
}

    public String test_Enum(testEnum testenum){
        return testenum.getColor();
    }

python:

def to_Enum(cls, param):
    # 获得枚举类
    java_class = JClass(cls)
    # 获取枚举对象中的成员
    return getattr(java_class, param)
# 测试自Enum类型转换
res = myJpypeTest.test_Enum(to_Enum("params.testEnum", "RED"))
print(res)
"D:\Program Files\Python39\python.exe" D:/myProjects/python/test_JPype/main.py
红色

Process finished with exit code 0

总结

本文描述如何通过jpype完成python类型到java类型的转换。
包含了java原生类型,以及自定义对象类型、数组类型、枚举类型、List类型、Map类型。

示例源码:

https://github.com/linchao001/testJpype

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-08-01 14:22:10  更:2021-08-01 14:24:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/5 15:35:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码