有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如果初始化对象涉及检查异常处理,如何使用enum创建单例

编辑

请注意,如果有任何最佳实践,我的问题更容易理解。我描述的问题可以通过多种方式解决,事实上,我是通过抛出运行时异常来处理它的。但这是最佳实践吗?或者我们应该回到更传统的单例创建方式,使用静态方法并将异常与对象创建分离

我正在使用enum来实例化一个单例,正如Java中所规定的那样

public enum MailApp { 
INSTANCE;   
private Gmail mailService;

private MailApp() {
    try {
        mailService = GoogleMailAppFactory.getGmailService();
    } catch (IOException e) {
        throw new AssertionError(e);
    }
}

问题是如果我添加如下抛出

public enum MailApp {

INSTANCE;

 /** Application name. */

private Gmail mailService;

private MailApp() throws IOException {
    mailService = GoogleMailAppFactory.getGmailService();
}

这不会编译为未处理的异常

我看了How to throw an exception from an enum constructor?

我找不到任何结论性的答案。所以我的问题是:这方面的最佳实践是什么?抛出断言错误是唯一的出路吗

谢谢你的帮助

编辑

我的“MailApp”只有在我们有有效的电子邮件服务时才有效。简而言之,我不想创建一个空对象。你能解释一下为什么这可能是个坏主意,以及应该如何处理这个问题吗


共 (2) 个答案

  1. # 1 楼答案

    复杂的例子:

    import android.content.Context;
    
    import java.util.HashMap;
    import java.util.Map;
    
    
    public enum Gender {
    
         /** non mather */
         NONE(0,R.string.any),
    
        /** Male */
        MALE(1,R.string.male);
    
        private final int _rId;
        private final int _id;
    
        private Context _context;
    
        public void  setContext(Context context) {
            _context = context;
        }
    
        private Gender(int id, int rId) {
            _id = id;
            _rId = rId;
    
            /** get context from setter */
            if(_context==null) {
                throw new NullPointerException("Exception");
            }
    
        }
    
        /**
         * @return The string representation of this element in the enumeration.
         */
        public int getResId() {
            return _rId;
        }
    
        public int getId() {
            return _id;
        }
    
        public static Gender getById(int id ) {
            return byId.get(id);
        }
    
        public String getName(){
            return _context.getResources().getString(_rId);
        }
    
        @Override
        public String toString(){
            return getName();
        }
    
        private static final Map<Integer, Gender> byId = new HashMap<>();
        static {
            for (Gender gender : Gender.values()) {
                if (byId.put(gender.getId(), gender) != null) {
                    throw new IllegalArgumentException("duplicate id: " +gender.getId()); 
                }
            }
        }
    }
    

    编辑:

    • 尝试通过简单地用一个元素创建一个枚举类型来实现单例
    • enum singleton保证它的实例将在每个VM上运行一次

    基本的

    public final class ISingleton {
        public final static ISingleton INSTANCE = new ISingleton(); 
    }
    
  2. # 2 楼答案

    实际上,我不同意这种方法,特别是因为你正在处理的问题

    如果必须在SE环境中实现单件,我会如下所示:

    public final class SingletonClass {
        private static SingletonClass INSTANCE;
    
        public SingletonClass getInstance() {
            return INSTANCE;
        }
    
        private SingletonClass() throws WhateverException {
           ...
        }
        static {
           try {
               INSTANCE = new SingletonClass();
           } catch (WhateverException e) {
               throw new RuntimeException(e);
           }
        }
    }

    如果我必须的话,我之所以强调,是因为我一开始就试图避免它,因为我很少只会有其中一种。使用CDI或Picocontainer进行依赖注入的概念也适用于SE环境,尽管CDI与Picocontainer相比有很多麻烦,诊断起来也更混乱

    在JEE6环境中,我会使用@javax.ejb.Singleton注释。这保证了集群部署中只有一个实例,不会有太多麻烦

    为了阐明上述方法的作用: