首页 文章

访问匿名类之外的变量

提问于
浏览
1

我目前正在使用IBM Watson java SDK中包含的IBM的Speech to Text服务 . 我试图将transcript String设置为等于结果'transcript . 但是,当我运行此代码时,不会打印该值 . 我不确定为什么会这样,或者如何解决问题 . 任何帮助,将不胜感激 . 我尝试在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]);

2 回答

  • 1

    您可以将数组脚本包装在具有自己的处理程序或使用者的类中(处理异步请求的方法) .

    像这样:

    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);
            }
        }
    });
    

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

    编辑:

    或者您可以以更简单的方式执行此操作(无需任何其他类):

    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]);
                }
            }
        });
    }
    
  • 0

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

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

    如果要在回调之外使用transcript值,最简单的解决方案是在类中定义一个新方法,并在 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库,在你的情况下RxJava specifically . 学习可能需要一些时间,但绝对值得 .

相关问题