众所周知,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.
我得到了例外。 那不是我想要的行为。我需要为添加到容器的任何整数创建不同的对象。我怎么能这样做?
答案 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)
如果T
为Number
,为什么不允许重复。
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(.)
返回相同对象的原因。