主要内容

本页采用了机器翻译。点击此处可查看最新英文版本。

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 getset 方法。该类是否同时需要 getset 方法取决于它是用作输入还是输出,或者两者兼而有之。

下面是一个简单示例,说明如何在 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 字段,但您也可以以类似的方式使用 namegrade 字段。

您使用 Production Server Compiler 将 sortstudents 打包成可部署存档(scoresorter.ctf)(详情请参阅 针对 MATLAB Production Server 创建可部署存档),并使其在服务器 http://localhost:9910/scoresorter 上可用,以供 Java 客户端访问(请参阅 将存档部署至 MATLAB Production Server)。

在定义客户端所需的 Java 接口之前,使用 MATLAB 类定义 Java 结构体 Student

Student 用适当的类型声明字段 namescoregrade。它还包含 public getset 函数来访问这些字段。

 Java Class Student

接下来,定义 Java 接口 StudentSorter,它调用方法 sortstudents 并使用 Student 类来编组输入和输出。

由于您正在使用结构类型,因此 Student 必须包含在注解 MWStructureList 中。

interface StudentSorter {
    @MWStructureList({Student.class})
    Student[] sortstudents(Student[] students) 
            throws IOException, MATLABException;
}

最后,为客户端编写 Java 应用程序(MPSClientExample):

  1. 创建 MWHttpClient 和相关代理(使用 createProxy),如使用 MWHttpClient 类创建 MATLABProduction ServerJava 客户端所示。

  2. 在 Java 中创建一个未排序的学生结构体数组,其命名、输入和输出数量以及 MATLAB 中的类型有效性模仿 MATLAB 结构。有关详细信息,请参阅Java 客户端编码最佳实践

  3. 对学生数组进行排序并显示。

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 方法。该类是否需要字段的 getset 方法取决于它是用作输入还是输出,或者两者兼而有之。在此示例中,请注意,当 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 注解