0

我正在尝试使用 oscP5 库将两个变量从一个草图发送到另一个草图。我发送的消息是这样创建的:

 OscMessage myMessage = new OscMessage("/test");
 myMessage.add(title);
 myMessage.add("Zeit");
 oscP5.send(myMessage, remoteLocation);

在第二个草图中,我收到这样的数据:

 void oscEvent(OscMessage theOscMessage) {
   if(theOscMessage.checkAddrPattern("/test")) {
     String title = theOscMessage.get(0).stringValue();
     String layoutType = theOscMessage.get(1).stringValue();

     addToQueue(title, layoutType);
   }
 }

这里是我简化的 addToQueue 函数:

 void addToQueue(String title, String layoutType) {
   if(!existsInQueues(title)) {
     upcomingHeadlines.add(new Headline(title, printAxis, scrollSpeed, layoutType));
   } 
 }

每次我开始草图时,我都会收到错误消息:

错误@OscP5 错误。将 OscMessage 转发到程序中的方法时发生错误。请检查您的代码是否存在在解析传入 OscMessage 的方法中可能发生的任何错误,例如检查转换错误、可能的空指针、数组溢出...。负责方法:oscEvent java.lang.reflect.InvocationTargetException

我已经能够将问题layoutType追溯到-Variable。如果我改变

  String layoutType = theOscMessage.get(1).stringValue();

  String layoutType = "Zeit";

没有错误发生。这很令人困惑,因为两个版本应该有相同的结果。错误消息对我没有任何帮助。


编辑

我已经比较了两个可能的变量:

String layoutType = theOscMessage.get(1).stringValue();
String layoutTypeB = "Zeit";
if(layoutType.equals(layoutTypeB)) println("Same String!");

由于打印到控制台,两者必须相同......我真的不知道在哪里搜索错误了。


编辑 2

我已经把我的第二幅草图try {...} catch(Exception ex) {ex.printStackTrace();}这样包裹起来了:

void oscEvent(OscMessage theOscMessage) {
  try {  
    if(theOscMessage.checkAddrPattern("/test")) {
      if(debug && debugFeed) println("Received message from other sketch.");

      String title = theOscMessage.get(0).stringValue();
      String layoutTypeO = (String)theOscMessage.get(1).stringValue();
      String layoutType = "Zeit";
      if(debug && debugTemp) {
        if(layoutType.equals(layoutTypeO)) println("IS DOCH GLEICH!");
      }
      if(debug && debugFeed) println("Parsed Information.");
      if(debug && debugFeed) println("-----");
      addToQueue(title, layoutTypeO);
    }
  } catch(Exception ex) {ex.printStackTrace();}
}

结果给了我这个错误:

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0  
    at java.util.ArrayList.rangeCheck(ArrayList.java:635)  
    at java.util.ArrayList.get(ArrayList.java:411)  
    at printer$Headline.useLayout(printer.java:260)  
    at printer$Headline.<init>(printer.java:188)  
    at printer.addToQueue(printer.java:407)  
    at printer.oscEvent(printer.java:395)  
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)  
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)  
    at java.lang.reflect.Method.invoke(Method.java:606)  
    at oscP5.OscP5.invoke(Unknown Source)  
    at oscP5.OscP5.callMethod(Unknown Source)  
    at oscP5.OscP5.process(Unknown Source)  
    at oscP5.OscNetManager.process(Unknown Source)  
    at netP5.AbstractUdpServer.run(Unknown Source)  
    at java.lang.Thread.run(Thread.java:744)

编辑 4

我的Headline-Class的构造函数:

class Headline {

  //Define Variables
  Layout layout;
  String title, lastHeadline;
  float yPos, speed;
  float transparency = 255;
  boolean fullyPrinted = false;
  int boundingBoxHeight;

  // Initialize Class Function
  Headline(String t, float y, float s, String lay) {
    title = t;
    yPos = y;
    speed = s;
    layout = useLayout(lay);
    boundingBoxHeight = calculateTextHeight(title);
  }

您可能也想知道useLayout(),所以这里是:

Layout useLayout(String name) {
    ArrayList layoutVariants = new ArrayList<Layout>();
    int existingLayouts = layouts.size();
    Layout chosenLayout;

    for(int i = 0; i < existingLayouts; i++) {
      Layout currentLayout = (Layout)layouts.get(i);
      if(currentLayout.layoutType == name) {
        layoutVariants.add(currentLayout);
      }
    }

    if(layoutVariants != null) {
      int rand = (int)(Math.random() * layoutVariants.size());
      chosenLayout = (Layout)layoutVariants.get(rand);
    } else {
      chosenLayout = (Layout)layouts.get((int)(Math.random() * existingLayouts)); 
    }
  return chosenLayout;
}
4

1 回答 1

3

您的代码有两个问题,并且它们都在您的useLayout方法中。

第一个问题是您没有Strings在这一行正确比较 s:

    if(currentLayout.layoutType == name) {

name是 a String,我认为currentLayout.layoutType也是。两个String相等但不相同的 s 在 下不会比较相等==。因此,您的layoutVariants列表很可能在for循环结束时为空。

此行应为:

    if(currentLayout.layoutType.equals(name)) {

另请参阅此问题

第二个问题是您没有正确处理layoutVariants列表为空的情况。问题出在这一行:

    if(layoutVariants != null) {

layoutVariants永远不会为空,因此该语句的else分支永远不会执行。if因为layoutVariants.size()会为零,所以rand永远都是零。尝试在空的 ArrayList 中获取索引 0 处的元素将准确地为您提供IndexOutOfBoundsException您所看到的。

我想else如果给定的布局名称未被识别,换句话说,如果layoutVariants列表是的,而不是空的,你希望块执行。在这种情况下,将此行更改为

    if(!layoutVariants.isEmpty()) {

注意!之前的 (not-operator) layoutVariants。如果元素为空,您希望if语句下的代码运行。layoutVariants

编辑以回应您的评论:nullArrayList 与空的非常不同。 null是一个特殊值,表示该变量没有给定类型的对象。

让我们尝试一个现实世界的类比:一个购物袋。如果你有一个空袋子,或者根本没有袋子,那么无论哪种方式,你都没有购物。但是,您可以将物品放入一个空袋子中,并计算其中包含的物品数量。如果您没有袋子,那么将物品放入其中是没有意义的,因为没有袋子可以放入物品。 null代表没有包的情况。

同样,aString是字符的集合,字符的集合即使不包含任何字符也可以存在。

isEmpty()可用于任何集合,如果您使用的是 Java 6 或更高版本,还可以用于字符串。在我的脑海中,我无法命名任何其他具有isEmpty方法的类。您只需查阅这些类的文档即可找到答案。

我没有过多地使用Processing,但我知道Processing 是基于Java 构建的,所以我希望任何标准的Java 方法都可以工作。此外,我不会担心“清除”变量:JVM 通常非常擅长在您之后进行清除。在这方面,您的代码肯定没有任何问题。

编辑 2以回应您的进一步评论:ArrayList arr;声明类型的变量ArrayList。但是,该变量arr初始化:它没有值(甚至没有null),并且在您为其赋值之前尝试读取该变量的值是错误的:

ArrayList arr;
System.out.println(arr);     // compiler error: arr might not have been initialised.

分配null,然后代码编译:

ArrayList arr = null;
System.out.println(arr);     // prints 'null'.

if您通常不需要声明一个变量而不给它一个名称,但一种常见的情况是您希望在语句的两侧为同一个变量分配不同的值。以下代码无法编译:

int y = getMeSomeInteger();   // assume this function exists
if (y == 4) {
    int x = 2;
} else {
    int x = 5;
}
System.out.println(x);        // compiler error: cannot find symbol x

它不编译的原因是每个变量x仅在大括号内可用{并且}包含它。在底部,这两个变量x都不可用,因此您会收到编译器错误。

我们需要x进一步声明。我们可以改为编写以下内容;

int y = getMeSomeInteger();   // assume this function exists
int x = 0;
if (y == 4) {
    x = 2;
} else {
    x = 5;
}
System.out.println(x);

此代码编译并运行,但0最初分配给的值x从未使用过。这样做没有多大意义,我们可以通过声明变量而不是立即给它一个值来摆脱这个未使用的值。

int y = getMeSomeInteger();   // assume this function exists
int x;
if (y == 4) {
    x = 2;
} else {
    x = 5;
}
System.out.println(x);
于 2014-01-24T20:49:45.023 回答