Java 每次返回同一个对象实例

Java 每次返回同一个对象实例,java,object,static,Java,Object,Static,在这种情况下,我有一个param值,基于此,我需要返回一个类实例。我希望每次调用都返回相同的对象 obj1和obj2实现相同的接口 class Engine { public commonInterface getObj(int param) { switch(param) { case 1 : return obj1; case 2 : return obj2; } } } 我如何做到这一点?我知

在这种情况下,我有一个param值,基于此,我需要返回一个类实例。我希望每次调用都返回相同的对象

obj1和obj2实现相同的接口

class Engine {
    public commonInterface getObj(int param) {
        switch(param) {
            case 1 : return obj1;
            case 2 : return obj2;
        }
    }
}

我如何做到这一点?我知道它在JVM中。

将两个实例
设置为静态的
,实例化一次,然后只返回它们。这类似于设计模式

class Engine {
    private static commonInterface obj1 = ...
    private static commonInterface obj2 = ...
    public commonInterface getObj(int param) {
        switch(param) {
            case 1 : return obj1;
            case 2 : return obj2;
        }
    }
}
下面是一种方法,但它不是最优的: 这不是最好的方法,主要是因为对象的创建不受限制,为了达到最佳效果,
MyObject
构造函数必须是
private
,实例必须在自身上

静态{}
块中初始化引用比
内联
更好,因为在初始化引用之前可以处理
异常
和其他逻辑,这是最佳做法

但这是您在许多快速而肮脏的代码中看到的,这些代码大部分是不正确的,因为下面的原因是更好的解决方案

class Engine {

private static final MyObject OBJ1;
private static final MyObject OBJ2;

static
{
    OBJ1 = new MyObject();
    OBJ2 = new MyObject();
}

public MyObject getObj(final int param)
{
    switch (param)
    {
        case 1:
            return Engine.OBJ1;
        case 2:
            return Engine.OBJ2;
        default:
            throw new IllegalArgumentException(String.format("%d is not a valid object id", param));
    }
}
这里有一个更好的方法: 这更好,因为它隐藏了实现。拥有一个内部类可以使类
成为公共的
,但使构造函数
成为私有的
,并控制对
MyObject
实例创建的访问

public class Engine 
{
    private static final MyObject OBJ1;
    private static final MyObject OBJ2;

    static
    {
        OBJ1 = new MyObject1();
        OBJ2 = new MyObject2();
    }

    public MyObject getObj(final int param)
    {
        switch (param)
        {
            case 1:
                return Engine.OBJ1;
            case 2:
                return Engine.OBJ2;
            default:
                throw new IllegalArgumentException(String.format("%d is not a valid object id", param));
        }
    }

    public static class MyObject1 implements MyObject { private MyObject1() {} } 
    public static class MyObject2 implements MyObject { private MyObject2() {} } 

}
最佳长期解决方案,此时使用最现代的习惯用法: 这种解决方案更加冗长,但在强制执行
单例的语义方面也是最正确的。此方法保证
单例
在当前JVM中收缩。它还可以扩展到多个类加载器和多个JVM,但只允许您将
MBeanServer
更改为不同的实现,并在不更改任何其他代码的情况下远程查找引用。为了简单起见,这里有意忽略DI/IoC

使用JMX方法的附加好处是,您可以使用
JConsole
非常轻松地管理这些实例,在应用程序运行时,您可以免费获得这些实例


注意:为了方便起见,我使用了带有
接口的单个文件作为内部类,它们可以在自己的文件中,而不会出现问题。

一种方法是使用
enum
s:

public enum CommonInterfaceImpl implements CommonInterface {
    Obj1,
    Obj2;

    @Override
    public void foo() {
        System.out.println("this is foo implementation");
    }
}
并在方法中返回所需的
枚举

class Engine {
    public commonInterface getObj(int param) {
        switch(param) {
            case 1 : return CommonInterfaceImpl.Obj1;
            case 2 : return CommonInterfaceImpl.Obj2;
        }
    }
}
另一种方法是使用
静态最终映射
,您可以在其中设置所有对象,然后根据需要在方法中检索它。这种方法甚至比使用预定义的
静态
变量的
enum
s更灵活:

class Engine {
    static final Map<Integer, CommonInterface> mapHolder = new HashMap<Integer, CommonInterface>();

    static {
        //bare example...
        //note that all this code can be replaced to load the classes dynamically
        CommonInterface obj1 = ...;
        CommonInterface obj2 = ...;
        mapHolder.put(1, obj1);
        mapHolder.put(2, obj2);
    }

    //note that the map can be filled in other methods of the Engine class...
    private void loadParameters() {
        CommonInterface obj3 = ...;
        CommonInterface obj4 = ...;
        mapHolder.put(3, obj3);
        mapHolder.put(4, obj4);
    }

    public commonInterface getObj(int param) {
        return mapHolder.get(param);
    }
}
类引擎{
静态最终映射mapHolder=新HashMap();
静止的{
//赤裸裸的例子。。。
//请注意,可以替换所有这些代码以动态加载类
公共接口obj1=。。。;
公共接口obj2=。。。;
地图持有者。放置(1,obj1);
放(2,obj2);
}
//请注意,映射可以在Engine类的其他方法中填充。。。
私有void loadParameters(){
公共接口obj3=。。。;
公共接口obj4=。。。;
地图持有者。put(3,obj3);
地图持有者。put(4,obj4);
}
公共公共接口getObj(int参数){
返回mapHolder.get(参数);
}
}

是否希望返回相同的实例?或者这就像一个工厂,它每次都创建一个新实例?应该返回同一个实例。@dasblinkenlight的人可以自由发表自己的观点,如果他们觉得单例模式不合适,那么可以使用向下投票来表达这一点(我碰巧认为单例是合适的,但这不是重点)。通知人们应该如何投票是不恰当的,只需省略:static{OBJ2=new Object();OBJ2=new Object();}谢谢..这看起来不错..现在如果这些Obj1和Obj2需要参数..在引擎类的构造函数中设置的参数呢?@user1071840然后使用我建议的方法,使用
静态最终映射
,而不是将字段标记为
静态最终
。内部类方法对我不起作用,因为Obj1和Obj2是不同的类型(它们实现同一个接口)。内部类方法将起作用,您只需将它们都设置为内部类。请参阅我对更好方法的编辑。
map
的建议很可怕,它不是线程安全的,也不是一成不变的,它不是一个好的解决方案。2表示第一,表示简单-1.因为评论中的愚蠢。总计=+1.|=^)@穆罕默德。有人(事实上,我认为至少有两名成员)浏览了所有答案,未经阅读就投了反对票(有一个被删除的答案在发布后几秒钟内就被投了反对票)。我正在写一个关于meta的问题来讨论这种情况。祝你好运。我在meta上问了一个类似的问题,结果在几分钟内就被20多人投票否决了。“我想你可以说这个网站充斥着白痴。”穆罕默德。好吧,不管怎样,我还是会试试:谁在乎rep,尤其是在元站点上,对吗?我同意你的观点,所以我会支持你。只是小心地说出来(不要像我那样急躁地愤怒)。
class Engine {
    static final Map<Integer, CommonInterface> mapHolder = new HashMap<Integer, CommonInterface>();

    static {
        //bare example...
        //note that all this code can be replaced to load the classes dynamically
        CommonInterface obj1 = ...;
        CommonInterface obj2 = ...;
        mapHolder.put(1, obj1);
        mapHolder.put(2, obj2);
    }

    //note that the map can be filled in other methods of the Engine class...
    private void loadParameters() {
        CommonInterface obj3 = ...;
        CommonInterface obj4 = ...;
        mapHolder.put(3, obj3);
        mapHolder.put(4, obj4);
    }

    public commonInterface getObj(int param) {
        return mapHolder.get(param);
    }
}