原始类型或非原始类型应该在Java接口中首选吗?

时间:2010-03-31 11:34:27

标签: java interface

(我以为我曾经在一本书中读过这个,但现在我不知道在哪里可以找到它。如果这个问题提醒你一些你读过的材料,请发表参考文献!)

接口中原语的优点和缺点是什么?

换句话说,其中一个优于另一个,为什么?在某些情况下,也许一个人比另一个更好?

public interface Foo {
    int getBar();
}

public interface Foo {
    Integer getBar();
}

类似地:

public interface Boz {
    void someOperation(int parameter);
}

public interface Boz {
    void someOperation(Integer parameter);
}

显然,在非原始情况下必须处理null s的问题,但有更深层次的关注吗?

6 个答案:

答案 0 :(得分:11)

除非有特定原因要使用对象类型(例如,您需要null),否则应使用原始类型来提高效率和简单性。使用对象类型可能会导致各种细微错误,例如错误地比较两个引用是否属于同一个对象,而不是具有相同的值。观察Java自己的库如何使用除容器之外的基本类型,它采用Object s。

答案 1 :(得分:2)

我会说对于基元,通常没有理由使用基元包装器作为返回类型。一个论点就是内存要求。使用原始返回值,您只需要返回值的X字节与您拥有对象开销的包装器。您可以保存的唯一位置是Integer.valueOf(1)之类的缓存值,但是例如使用整数,这仅适用于值-128 - > 127。

虽然lexicore使用null作为特殊情况返回值确实产生了一个有效点,但是很多时候你可以使用primitve值执行相同的操作(例如API中的某些内容“当返回Integer.MIN_VALUE时返回结果不能被计算“。在许多情况下,除了布尔值之外,所有基元都是可行的。

也总是存在异常选项,因为有人可能认为接口应始终为所有可能的输入定义良好,并且导致返回值未确定的输入是异常情况的定义(以及这可能是IllegalArgumentException的好例子。

最终(非常不那么重要)解决方案是在接口上添加某种状态检查方法,可以在调用可能无法按预期执行的方法后对其进行测试:

boolean b = (interface).doFoo();
if((interface).wasError()){
  //doFoo did not complete normally
}else{
  //do something fooish
}

其中wasError可以以Thread的中断标志的样式自动清除(注意这种方法在多线程代码中容易出错)。

答案 2 :(得分:2)

除了极少数情况下原语很麻烦(我对CORBA有一些“好的”经验),我建议使用原语。

答案 3 :(得分:1)

我也在考虑这样的事情:

假设我们有这种类型:

public interface Foo {
    int getID();
}

然后,无论出于何种原因,都会引入ID类型:

public interface Foo {
    FooID getID();
}

现在,假设在更改之前编写了一些客户端,并且客户端包含如下代码:

if (A.getID() == B.getID()) {
    someBehavior();
}

ABFoos

这个代码在更改后会被破坏,因为==之间的原始相等比较(int)在更改之前是正确的,现在错误地比较了参考值而不是调用{{ 1}}关于标识符。

如果equals(Object)从一开始就产生了getID(),那么正确的客户端代码就已经存在(好吧,正确的客户端代码可能就是这样。装箱转换会有已经应用Integer以便也可以使用):

==

软件发展后,这仍然是正确的。

如果改变是“相反的”,换句话说,如果if (A.getID().equals(B.getID())) { someBehavior(); } 最初产生了一些getID()类型,那么如果将其更改为生成FooID,则编译器会抱怨关于在基元上调用int并且客户端代码已被更正。

似乎有一些非原始类型的“未来证明”的感觉。同意?不同意?

答案 4 :(得分:1)

使用原语。自动装箱/自动装箱会将int转换为Integer,依此类推。基元也分配在堆栈上,而不是堆。通过使用包装器类,您使用更多内存并产生更多开销;你为什么要那样做?

答案 5 :(得分:0)

是的,当您通过网络传输对象时,您可以看到的主要用途。  **使用序列化。 **