访问匿名之外的变量 class

Accessing variables outside of anonymous class

我目前正在使用 IBM Watson java SDK 中包含的 IBM 语音转文本服务。我正在尝试将成绩单字符串设置为等于结果的成绩单。但是,当我 运行 此代码时,不会打印该值。我不确定为什么会这样,或者如何解决这个问题。任何帮助,将不胜感激。我曾尝试在 main 方法之外使用带有静态变量的外部 setter,但我没有成功。

final String[] transcript = {""};
    service.recognizeUsingWebSocket(options, new BaseRecognizeCallback() {
        @Override
        public void onTranscription(SpeechRecognitionResults speechResults) {
            for(int i = 0; i < speechResults.getResults().size(); i++){
                transcript[0] = transcript[0] + speechResults.getResults().get(i).getAlternatives().get(0).getTranscript() + "\n";
            }
        }
    });
    System.out.println(transcript[0]);

您可以将数组转录本包装在一个 class 中,它有自己的处理程序或使用者(一种处理异步请求的方法)。

像这样:

import java.util.function.Consumer;

public class ArrayWrapper {

    private Consumer consumer;

    private Object [] array;

    public ArrayWrapper(int size) {
        this.array = new Object [size];
    }

    public void addConsumer(Consumer consumer) {
        this.consumer = consumer;
    }

    public void add(Object o, int index) {
        array[index] = o;
        consumer.accept(o);
    }

    public Object [] get() {
        return array;
    }
}

然后您可以在 Consumer 中实现您的逻辑:

ArrayWrapper transcript = new ArrayWrapper(1);
transcript.addConsumer(new Consumer() {
    @Override
    public void accept(Object o) {
        // perform your operations 
        System.out.println(o);
    }
});

service.recognizeUsingWebSocket(options, new BaseRecognizeCallback() {
    @Override
    public void onTranscription(SpeechRecognitionResults speechResults) {
        for(int i = 0; i < speechResults.getResults().size(); i++){
            String newTranscript = transcript.get()[0] + speechResults.getResults().get(i).getAlternatives().get(0).getTranscript() + "\n";
            transcript.add(newTranscript, 0);
        }
    }
});

这只是一个示例,但想法是您必须在回调中使用一个函数,一些信号告诉您何时在回调中完成循环或类似的东西。

编辑:

或者您可以通过更简单的方式执行此操作(无需任何额外的 classes):

    final String[] transcript = {""};
    Consumer<String> consumer = new Consumer<String>() {
        @Override
        public void accept(String s) {
            //your operations
            System.out.println(s);
        }
    };
    service.recognizeUsingWebSocket(options, new BaseRecognizeCallback() {
        @Override
        public void onTranscription(SpeechRecognitionResults speechResults) {
            for(int i = 0; i < speechResults.getResults().size(); i++){
                transcript[0] = transcript[0] + speechResults.getResults().get(i).getAlternatives().get(0).getTranscript() + "\n";
                consumer.accept(transcript[0]);
            }
        }
    });
}

问题是recognizeUsingWebSocket是一个异步调用。因此,当您执行此操作时,System.out.println(transcript[0] 您对 IBM Watson 服务的调用很可能尚未完成。

当回调方法onTranscription被触发时,您将知道异步操作已完成。因此,在该方法内部和 for 循环之后,您可以确定 transcript 数组中已经有一些值。在那里,你可以对结果做任何你想做的事情。

如果您想在回调之外使用转录值,最简单的解决方案是在 class 中定义一个新方法并在 onTranscript 回调结束时调用它。

...
public void onTranscriptReceived(String[] transcript) {
     // Do whatever you want
}
...

final String[] transcript = {""};
service.recognizeUsingWebSocket(options, new BaseRecognizeCallback() {
    @Override
    public void onTranscription(SpeechRecognitionResults speechResults) {
        for(int i = 0; i < speechResults.getResults().size(); i++){
            transcript[0] = transcript[0] + speechResults.getResults().get(i).getAlternatives().get(0).getTranscript() + "\n";
        }
        onTranscriptReceived(transcript);
    }
});

还有许多其他解决方案可以处理异步调用。就个人而言,我喜欢 ReactiveX libraries, in your case RxJava specifically。可能需要一些时间来学习,但绝对值得。