在 MATLAB 中编组 Java 结构 (Structs)
结构(或 structs)是 MATLAB® 数组,其元素通过文本字段指示符访问。
结构由称为字段的数据容器组成。每个字段存储某种 MATLAB 数据类型的数组。每个字段都有一个唯一的名称。
结构体中的字段可以具有与任何 MATLAB 数据类型兼容的值,包括元胞数组或其他结构体。
在 MATLAB 中,创建一个结构体如下:
S.name = 'Ed Plum'; S.score = 83; S.grade = 'B+'
S): S =
name: 'Ed Plum'
score: 83
grade: 'B+'S(2).name = 'Toni Miller'; S(2).score = 91; S(2).grade = 'A-';
(1,2) 的结构体数组。还支持具有附加维度的结构。由于 Java® 本身不支持 MATLAB 结构体,服务器和客户端之间的编组结构体需要额外的编码。
在客户端和服务器之间编组结构
MATLAB 结构体是名称-值对的有序列表。您可以使用由相同区分大小写的名称组成的字段在 Java 中表示它们。
Java 类还必须为每个字段定义 public get 和 set 方法。该类是否同时需要 get 和 set 方法取决于它是用作输入还是输出,或者两者兼而有之。
下面是一个简单示例,说明如何在 MATLAB 客户端和服务器之间编组 Java 结构体。
在这个示例中,MATLAB 函数 sortstudents 接受一个结构体数组(详情请参阅 在 MATLAB 中编组 Java 结构 (Structs))。
结构体数组中的每个元素代表学生的不同信息。sortstudents 按每个学生的分数对输入数组进行升序排序,如下所示:
function sorted = sortstudents(unsorted)
% Receive a vector of students as input
% Get scores of all the students
scores = {unsorted.score};
% Convert the cell array containing scores into a numeric array or doubles
scores = cell2mat(scores);
% Sort the scores array
[s i] = sort(scores);
% Sort the students array based on the sorted scores array
sorted = unsorted(i);注意
尽管此示例仅使用输入结构体的 scores 字段,但您也可以以类似的方式使用 name 和 grade 字段。
您使用 Production Server Compiler 将 sortstudents 打包成可部署存档(scoresorter.ctf)(详情请参阅 针对 MATLAB Production Server 创建可部署存档),并使其在服务器 http://localhost:9910/scoresorter 上可用,以供 Java 客户端访问(请参阅 将存档部署至 MATLAB Production Server)。
在定义客户端所需的 Java 接口之前,使用 MATLAB 类定义 Java 结构体 Student。
Student 用适当的类型声明字段 name、score 和 grade。它还包含 public get 和 set 函数来访问这些字段。
接下来,定义 Java 接口 StudentSorter,它调用方法 sortstudents 并使用 Student 类来编组输入和输出。
由于您正在使用结构类型,因此 Student 必须包含在注解 MWStructureList 中。
interface StudentSorter {
@MWStructureList({Student.class})
Student[] sortstudents(Student[] students)
throws IOException, MATLABException;
}
最后,为客户端编写 Java 应用程序(MPSClientExample):
创建
MWHttpClient和相关代理(使用createProxy),如使用 MWHttpClient 类创建 MATLABProduction ServerJava 客户端所示。在 Java 中创建一个未排序的学生结构体数组,其命名、输入和输出数量以及 MATLAB 中的类型有效性模仿 MATLAB 结构。有关详细信息,请参阅Java 客户端编码最佳实践。
对学生数组进行排序并显示。
import java.net.URL;
import java.io.IOException;
import com.mathworks.mps.client.MWClient;
import com.mathworks.mps.client.MWHttpClient;
import com.mathworks.mps.client.MATLABException;
import com.mathworks.mps.client.annotations.MWStructureList;
interface StudentSorter {
@MWStructureList({Student.class})
Student[] sortstudents(Student[] students)
throws IOException, MATLABException;
}
public class ClientExample {
public static void main(String[] args){
MWClient client = new MWHttpClient();
try{
StudentSorter s =
client.createProxy(new URL("http://localhost:9910/scoresorter"),
StudentSorter.class );
Student[] students = new Student[]{new Student("Toni Miller", 90, "A"),
new Student("Ed Plum", 80, "B+"),
new Student("Mark Jones", 85, "A-")};
Student[] sorted = s.sortstudents(students);
System.out.println("Student list sorted in the
ascending order of scores : ");
for(Student st:sorted){
System.out.println(st);
}
}catch(IOException ex){
System.out.println(ex);
}catch(MATLABException ex){
System.out.println(ex);
}finally{
client.close();
}
}
}
将 Java 字段名称映射到 MATLAB 字段名称
表示 Java 结构体的 MATLAB 类使用 Java Beans Introspector 类 (https://docs.oracle.com/javase/6/docs/api/java/beans/Introspector.html) 将属性映射到字段,并使用其默认命名约定。
这意味着默认使用其 decapitalize() 方法。这将 Java 字段的首字母映射为小写字母。默认情况下,无法定义一个 Java 字段来映射到以大写字母开头的 MATLAB 字段。
您可以通过使用自定义 BeanInfo 方法实现 getPropertyDescriptors() 类来覆盖此行为。例如:
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.beans.SimpleBeanInfo;
public class StudentBeanInfo extends SimpleBeanInfo
{
@Override
public PropertyDescriptor[] getPropertyDescriptors()
{
PropertyDescriptor[] props = new PropertyDescriptor[3];
try
{
// name uses default naming conventions so we do not need to
// explicitly specify the accessor names.
props[0] = new PropertyDescriptor("name",MyStruct.class);
// score uses default naming conventions so we do not need to
// explicitly specify the accessor names.
props[1] = new PropertyDescriptor("score",MyStruct.class);
// Grade uses a custom naming convention so we do need to
// explicitly specify the accessor names.
props[1] = new PropertyDescriptor("Grade",MyStruct.class,
"getGrade","setGrade");
return props;
}
catch (IntrospectionException e)
{
e.printStackTrace();
}
return null;
}
}定义仅用作输入的 MATLAB 结构
将 Java 结构定义为输入时,请遵循以下准则:
确保 Java 类中的字段与 MATLAB 结构中的字段名称完全匹配。字段名称区分大小写。
在 Java 类中的字段上使用
public get方法。该类是否需要字段的get和set方法取决于它是用作输入还是输出,或者两者兼而有之。在此示例中,请注意,当student作为输入传递给方法sortstudents时,数据编组算法仅使用其字段的get方法。
因此,如果为仅用作输入值的 Java 结构体定义了 MATLAB 类,则不需要 set 方法。此版本的 Student 类仅代表输入值:
public class Student{
private String name;
private int score;
private String grade;
public Student(String name, int score, String grade){
this.name = name;
this.score = score;
this.grade = grade;
}
public String getName(){
return name;
}
public int getScore(){
return score;
}
public String getGrade(){
return grade;
}
}
定义仅用作输出的 MATLAB 结构
将 Java 结构定义为输出时,请遵循以下准则:
确保 Java 类中的字段与 MATLAB 结构中的字段名称完全匹配。字段名称区分大小写。
使用从 Java 接收的结构体创建 MATLAB 类的新实例。通过使用
set方法或 Java 提供的@ConstructorProperties注解来实现。在定义仅输出的 Java 结构体时,MATLAB 类不需要get方法。
使用 Student 方法的仅输出 set 类如下:
public class Student{
private String name;
private int score;
private String grade;
public void setName(String name){
this.name = name;
}
public void setScore(int score){
this.score = score;
}
public void setGrade(String grade){
this.grade = grade;
}
}
使用 Student 的仅输出 @ConstructorProperties 类如下:
public class Student{
private String name;
private int score;
private String grade;
@ConstructorProperties({"name","score","grade"})
public Student(String n, int s, String g){
this.name = n;
this.score = s;
this.grade = g;
}
}注意
如果同时提供了 set 方法和 @ConstructorProperties 注解,则 set 方法优先于 @ConstructorProperties 注解。
定义用作输入和输出的 MATLAB 结构
如果 Student 类同时用作输入和输出,则需要提供 get 方法来执行对 MATLAB 的编组。要从 MATLAB 进行编组,请使用 set 方法或 @ConstructorProperties 注解。
