【问题标题】:Singleton constructor throws exception throwed by it's init method单例构造函数抛出其 init 方法抛出的异常
【发布时间】:2015-05-04 22:13:06
【问题描述】:

我尝试在 init() 方法中捕获块。 但我想把它们扔给消费阶层。

但是,如果我删除 try catch 块并为该方法添加 throws 声明。 我必须为构造函数和 getInstance 方法添加它。

但是再次运行我的应用程序会导致我在删除 try catch 块的位置出现错误。 我以前没有遇到这些错误。 而对于其他有异常抛出的方法,没有在构造函数中调用,也没有问题。

知道如何正确处理这个问题吗?提前致谢。

我也已经看过这里了:Singleton and Exception

但这并没有帮助。

public class Communicator {
    private static Communicator instance = null;

    protected Communicator() {
        init();
    }

    public static Communicator getInstance() {
        if (instance == null) {
            instance = new Communicator();
        }
        return instance;
    }

    public void init() {
        // set up connections
    }
}

好的,因为需要更多细节:这是完整的代码,没有可能引发异常的额外方法=>

public class WindowsMidiCommunicator {
    private MidiDevice.Info[] devices;
    private MidiDevice outputDevice = null;
    private Receiver recvr = null;
    private MidiDevice inputDevice = null;
    private Transmitter trans = null;
    private DumpReceiver outputReceiverDump;
    private Logger log;
    private MessageQueue<Message> queue = null;
    private static WindowsMidiCommunicator instance=null;
    protected WindowsMidiCommunicator() {
        init();
    }
    public static WindowsMidiCommunicator getInstance(){
        if(instance==null){
            instance=new WindowsMidiCommunicator();
        }
        return instance;
    }
    public void init() {
        devices = MidiSystem.getMidiDeviceInfo();
        outputReceiverDump = new DumpReceiver(System.out);
        queue = new MessageQueue<Message>();
        outputReceiverDump.setMessageQueue(queue);
        Logger log = LogManager.getLogger(Saffiretest.class.getName());

        for (MidiDevice.Info info : devices) {
            if (info.getName().contains("Saffire")) {
                MidiDevice device = null;
                try {
                    device = MidiSystem.getMidiDevice(info);
                } catch (MidiUnavailableException e1) {
                    log.error("MidiUnavailableException");
                    e1.printStackTrace();
                }
                if (!device.isOpen()) {
                    try {
                        device.open();
                    } catch (MidiUnavailableException e) {
                        log.error("MidiUnavailableException");
                        e.printStackTrace();
                    }
                }
                if (device instanceof Sequencer) {
                    log.info("Device is a Sequencer");
                }
                if (device instanceof Synthesizer) {
                    log.info("Device is a Synthesizer");
                }
                log.info("Max receivers:" + device.getMaxReceivers());
                if (device.getMaxReceivers() == -1) {
                    outputDevice = device;
                    log.info(device.getDeviceInfo().getName()
                            + "obtained as outputDevice");
                }
                if (device.getMaxTransmitters() == -1) {
                    inputDevice = device;
                    log.info(device.getDeviceInfo().getName()
                            + "obtained as inputDevice");
                }
                log.info("Max transmitters:" + device.getMaxTransmitters());
                log.info("Open receivers:");
                List<Receiver> receivers = device.getReceivers();
                for (Receiver r : receivers) {
                    log.info(r.toString());
                }
                try {
                    log.info("Default receiver: "
                            + device.getReceiver().toString());

                    log.info("Open receivers now:");
                    receivers = device.getReceivers();
                    for (Receiver r : receivers) {
                        log.info(r.toString());
                    }
                } catch (MidiUnavailableException e) {
                    log.info("No default receiver");
                }

                log.info("Open transmitters:");
                List<Transmitter> transmitters = device.getTransmitters();
                for (Transmitter t : transmitters) {
                    log.info(t.toString());
                }
                try {
                    log.info("Default transmitter: "
                            + device.getTransmitter().toString());

                    log.info("Open transmitters now:");
                    transmitters = device.getTransmitters();
                    for (Transmitter t : transmitters) {
                        log.info(t.toString());
                    }
                } catch (MidiUnavailableException e) {
                    log.error("No default transmitter");
                }
            }
        }
        try {
            recvr = outputDevice.getReceiver();
        } catch (MidiUnavailableException e) {
            log.error("no receiver available");
            e.printStackTrace();
        }
        try {
            trans = inputDevice.getTransmitter();
            trans.setReceiver(outputReceiverDump);
        } catch (MidiUnavailableException e) {
            log.error("no transmitter available");
            e.printStackTrace();
        }

    }

现在,当删除所有这些 try catch 块时,我最终会变成这样:

protected WindowsMidiCommunicator() throws MidiUnavailableException {
        init();
    }
    public static WindowsMidiCommunicator getInstance() throws MidiUnavailableException{
        if(instance==null){
            instance=new WindowsMidiCommunicator();
        }
        return instance;
    }
    public void init() throws MidiUnavailableException {
        devices = MidiSystem.getMidiDeviceInfo();
        outputReceiverDump = new DumpReceiver(System.out);
        queue = new MessageQueue<Message>();
        outputReceiverDump.setMessageQueue(queue);
        Logger log = LogManager.getLogger(Saffiretest.class.getName());

        for (MidiDevice.Info info : devices) {
            if (info.getName().contains("Saffire")) {
                MidiDevice device = null;

                    device = MidiSystem.getMidiDevice(info);

                if (!device.isOpen()) {

                        device.open();

                }
                if (device instanceof Sequencer) {
                    log.info("Device is a Sequencer");
                }
                if (device instanceof Synthesizer) {
                    log.info("Device is a Synthesizer");
                }
                log.info("Max receivers:" + device.getMaxReceivers());
                if (device.getMaxReceivers() == -1) {
                    outputDevice = device;
                    log.info(device.getDeviceInfo().getName()
                            + "obtained as outputDevice");
                }
                if (device.getMaxTransmitters() == -1) {
                    inputDevice = device;
                    log.info(device.getDeviceInfo().getName()
                            + "obtained as inputDevice");
                }
                log.info("Max transmitters:" + device.getMaxTransmitters());
                log.info("Open receivers:");
                List<Receiver> receivers = device.getReceivers();
                for (Receiver r : receivers) {
                    log.info(r.toString());
                }

                    log.info("Default receiver: "
                            + device.getReceiver().toString());

                    log.info("Open receivers now:");
                    receivers = device.getReceivers();
                    for (Receiver r : receivers) {
                        log.info(r.toString());
                    }


                log.info("Open transmitters:");
                List<Transmitter> transmitters = device.getTransmitters();
                for (Transmitter t : transmitters) {
                    log.info(t.toString());
                }

                    log.info("Default transmitter: "
                            + device.getTransmitter().toString());

                    log.info("Open transmitters now:");
                    transmitters = device.getTransmitters();
                    for (Transmitter t : transmitters) {
                        log.info(t.toString());
                    }

            }
        }

            recvr = outputDevice.getReceiver();
            trans = inputDevice.getTransmitter();
            trans.setReceiver(outputReceiverDump);

    }

这是主要的方法:

public static void main(String[] args) {
        try {
            WindowsMidiCommunicator.getInstance().testConnectivity();
        } catch (InvalidMidiDataException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (MidiUnavailableException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            WindowsMidiCommunicator.getInstance().sendCurrentPresetRequest();
        } catch (InvalidMidiDataException | MidiUnavailableException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        new java.util.Timer().schedule( 
                new java.util.TimerTask() {
                    @Override
                    public void run() {
                        try {
                            WindowsMidiCommunicator.getInstance().closeDevices();
                        } catch (MidiUnavailableException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }, 
                5000 
        );
    }

运行时,这是堆栈跟踪:

INFO ] 2015-05-05 11:08:32.572 [main] Saffiretest - Max receivers:0
javax.sound.midi.MidiUnavailableException: MIDI IN receiver not available
    at com.sun.media.sound.AbstractMidiDevice.createReceiver(Unknown Source)
    at com.sun.media.sound.AbstractMidiDevice.getReceiver(Unknown Source)
    at WindowsMidiCommunicator.init(WindowsMidiCommunicator.java:79)
    at WindowsMidiCommunicator.<init>(WindowsMidiCommunicator.java:28)
    at WindowsMidiCommunicator.getInstance(WindowsMidiCommunicator.java:32)
    at SafferOrganizedTest.main(SafferOrganizedTest.java:9)
[INFO ] 2015-05-05 11:08:32.573 [main] Saffiretest - 2- Saffire 6USBobtained as inputDevice
[INFO ] 2015-05-05 11:08:32.574 [main] Saffiretest - Max transmitters:-1
[INFO ] 2015-05-05 11:08:32.574 [main] Saffiretest - Open receivers:
[INFO ] 2015-05-05 11:08:32.577 [main] Saffiretest - Max receivers:0
[INFO ] 2015-05-05 11:08:32.577 [main] Saffiretest - 2- Saffire 6USBobtained as inputDevice
[INFO ] 2015-05-05 11:08:32.577 [main] Saffiretest - Max transmitters:-1
[INFO ] 2015-05-05 11:08:32.577 [main] Saffiretest - Open receivers:
javax.sound.midi.MidiUnavailableException: MIDI IN receiver not available
    at com.sun.media.sound.AbstractMidiDevice.createReceiver(Unknown Source)
    at com.sun.media.sound.AbstractMidiDevice.getReceiver(Unknown Source)
    at WindowsMidiCommunicator.init(WindowsMidiCommunicator.java:79)
    at WindowsMidiCommunicator.<init>(WindowsMidiCommunicator.java:28)
    at WindowsMidiCommunicator.getInstance(WindowsMidiCommunicator.java:32)
    at SafferOrganizedTest.main(SafferOrganizedTest.java:18)
[INFO ] 2015-05-05 11:08:37.583 [Timer-0] Saffiretest - Max receivers:0
javax.sound.midi.MidiUnavailableException: MIDI IN receiver not available
[INFO ] 2015-05-05 11:08:37.584 [Timer-0] Saffiretest - 2- Saffire 6USBobtained as inputDevice
[INFO ] 2015-05-05 11:08:37.584 [Timer-0] Saffiretest - Max transmitters:-1
[INFO ] 2015-05-05 11:08:37.584 [Timer-0] Saffiretest - Open receivers:
    at com.sun.media.sound.AbstractMidiDevice.createReceiver(Unknown Source)
    at com.sun.media.sound.AbstractMidiDevice.getReceiver(Unknown Source)
    at WindowsMidiCommunicator.init(WindowsMidiCommunicator.java:79)
    at WindowsMidiCommunicator.<init>(WindowsMidiCommunicator.java:28)
    at WindowsMidiCommunicator.getInstance(WindowsMidiCommunicator.java:32)
    at SafferOrganizedTest$1.run(SafferOrganizedTest.java:28)
    at java.util.TimerThread.mainLoop(Unknown Source)
    at java.util.TimerThread.run(Unknown Source)

【问题讨论】:

  • 您遇到了什么错误?您提到您没有使用 try-catch 块收到这些错误。这些错误是否有可能被 try-catch 块静默消耗掉。换句话说,对于捕获的每个异常,您是否都有 printStackTrace() 或类似的?
  • 澄清 nullPointer 评论:“我之前没有遇到这些错误” 也许您确实遇到了这些错误,具体取决于您如何捕获它们。使用 try/catch 块发布之前的代码,特别是你在 catch 中所做的事情。

标签: java exception constructor exception-handling singleton


【解决方案1】:

不清楚您的实际问题是什么,因为您没有发布错误消息。但是,您的单例实现并不是真正地道或正确,主要是因为您的类的构造函数是protected。这意味着任何子类化您的类的人都可以创建它的其他实例——使该类不再是单例。

在 Java 5 及更高版本中实现单例的最简单方法是使用具有单个值的枚举:

public enum Communicator {
    INSTANCE;

    private Connection conn;

    Communicator() {
        // set up the Connection here
    }

    /* public methods */
    public void doSomething() {
        //...
    }
}

这样,您可以简单地使用 Communicator.INSTANCE.doSomething() 调用您的单例。

【讨论】:

  • 在我的例子中,init 方法将在第一次调用 get 实例时执行。何时使用单例枚举实现执行?
  • 基于单例的实现也是lazily-initialized
猜你喜欢
  • 2011-11-04
  • 1970-01-01
  • 2014-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-11
  • 2013-03-25
  • 1970-01-01
相关资源
最近更新 更多