如何区分同一整数对象?

时间:2015-07-16 06:19:36

标签: java list integer

众所周知,java将Integer从-128范围缓存到127.现在,我有一个类容器,如下所示:

public class Container<T>{
    private List<T> elements;

    public boolean add(T t){
        //add the element to the container

        //if elements already contains t such that 
        //there is e from elements so e == t
        //the IllegalArgumentException should be thrown
    }
}

现在,当我尝试创建Container<Integer> container然后像那样添加一些

container.add(1);
container.add(2);
container.add(1); //here the IllegalArgumentException is being thrown.

我得到了例外。 那不是我想要的行为。我需要为添加到容器的任何整数创建不同的对象。我怎么能这样做?

6 个答案:

答案 0 :(得分:4)

使用Integer运算符明确创建new的新实例。

container.add(new Integer(1));
container.add(new Integer(2));
container.add(new Integer(1));

答案 1 :(得分:3)

如果您确实希望Integer有特殊行为,可以进行检查并手动创建新实例:

public boolean add(T t) {
    if (t instanceof Integer) {
        t = new Integer(((Integer)t).intValue());
    }

    // The rest of the code.
}

请记住,如果你想为其他原语做这件事,这会变得更加混乱。

答案 2 :(得分:2)

您在评论中指出,使用此功能的开发人员会将此称为错误。但正如Boxing Conversations in the Java Language Specification所述:

  

如果被装箱的值p是-128和127之间的int类型的整数文字(§3.10.1),或者布尔文字是真或假(§3.10.3),或者是'\之间的字符文字u0000'和'\ u007f'包含(§3.10.4),然后让a和b成为p的任意两次拳击转换的结果。 a == b。

总是如此

将有一个VM-Property来更改IntegerCache(-Djava.lang.Integer.IntegerCache.high)的大小,但是不允许您指定低于127的任何值或禁用它。如IntegerCache类中所示:assert IntegerCache.high >= 127;

所以使用new Integer()而不是自动装箱是这样做的唯一正确方法。我不会坚持使用instanceof和创建新对象的其他注释中指出的解决方案(正如他们所说的那样!),因为这些都不是干净的,也不是正确的方法。

请再看一下您的架构。如果一个元素被添加两次,你真的想要抛出异常吗?为什么不使用普通的java.util.Set并处理它的布尔返回值?这将是执行此操作的最标准的Java方式。不要重新发明轮子,坚持现有的,经过良好测试和明确定义的课程。

答案 3 :(得分:1)

如果TNumber,为什么不允许重复。

public class Container<T>{
    private List<T> elements;

    public boolean add(T t){
        //add the element to the container

        // <<<IF <T> IS NOT NUMBER>>> and if elements already contains t such that 
        //there is e from elements so e == t
        //the IllegalArgumentException should be thrown
    }
}

答案 4 :(得分:1)

如果您可以稍微更改公共API,我会这样做。我会创建一个子类:

public class IntegerContainer extends Container<Integer> {
    public boolean add(Integer integer) {
        return super.add(new Integer(integer));
    }
}

然后我会使Container的构造函数受到保护,并添加一个静态工厂参加一个类:

public class Container<T>  {
    protected Container() {}

    public static <T> Container<T> of(Class<T> type) {
        if (type.isAssignableFrom(Integer.class)) {
            return (Container<T>) new IntegerContainer();
        }
        return new Container<T>();
    }

    private List<T> elements = new ArrayList<T>();

    public boolean add(T t){
        for (T e : elements) {
            if (t == e)
                throw new IllegalArgumentException();
        }
        return elements.add(t);
    }

    public static void main(String args[]) {
        Container<Integer> integerContainer = Container.of(Integer.class);
        integerContainer.add(1);
        integerContainer.add(2);
        integerContainer.add(1); // Doesn't throw

        Container<String> stringContainer = Container.of(String.class);
        String same = "hi";
        stringContainer.add(same);
        stringContainer.add(same); // Throws
        return;
    }
}

请注意,这会改变API用户创建Container的方式;他们必须使用他们想要的类型调用Container.of

答案 5 :(得分:1)

我不知道你要做什么,但这不是你的方法。

Integer是一个不可变的类。因此,您认为拥有两个对象x&amp; y(x!=y && x.equals(y))未正确使用该类。它是允许的,但绝不应该是有用的或希望的。

这就是允许(但不是必须)允许从重复(显式或隐式)调用valueOf(.)返回相同对象的原因。