用Long 还是long

在维护一个系统的时候,发现以前的程序员在设计程序的时候,对于实体类的id都设计为对象类型的Long,而不是原始类型的long,据说这样设计是因为对象类型的Long没有值的时候时NULL,因此可以通过其值是否为null来判断所表示的实体类是否已经在在数据库中存在,也就是在添加和更新时做判断使用,因为大多数程序员都习惯用一个save方法,来处理add和update操作,而通过id是否有值来判断是add还是update.就是为了这个小小的功能,而选择Long,我个人不是很喜欢,因为用其作为id,会带来一些缺点,可以说缺点大于优点。

1.  容易引发难易发现的空指针异常

用对象型的Long,经常需要其是否为null,否则经常抛空指针异常,因为Jdk支持Long 到long的隐式转换,也就是说,方法定义的参数类型为long,传入对象型的Long也是可以的,运行时系统会自动将对象型的Long转换为long,但是如果发现对象型的Long为null时就会抛空指针异常。而这种缺陷通常不易被发现。

参考代码如下:

public class TestLong

{

    public static void main(String args[])

    {

       TestLong testLong = new TestLong();

       Long id = null;

       testLong.test(id);

    }

   

    public void test(long id)

    {

       System.out.println("原始类型的long");

    }

}

运行就会发生空指针异常,这里我们直接赋值为null,你可能说很容易看出来,但实际项目中,是很难发现的。

2. Longid作为对象是否相等判断依据时,用在集合中容易出现垃圾数据。

经常我们用id作为对象唯一的表示,对应于数据库的唯一key.在设计类的时候,我们通过重写Object类的equals方法和hashCode方法从而实现从业务上正确区分不同的对象。通常的equals方法我们这么写,比如User类的部分代码如下:

private long id = 0L;

public long getId()

{

    return id;

}

public void setId(long id)

{

    this.id = id;

}

public boolean equals(Object obj)

{

    if(this.getClass()!=obj.getClass())

    {

       return false;

    }

    return obj!=null && ((User)obj).getId() == this.id;

}

但是如果我们把这里的id设计成Long型,则这里的equals方法通常这么写。

public boolean equals(Object obj)

{

    if(this.getClass()!=obj.getClass())

    {

       return false;

    }

    return obj!=null && this.id.equals(((User)obj).getId());

}

这里看似没什么问题。但是当我们需要把User对象放入一个集合中时,如HashSet中,我们希望里边的数据不重复,当然也不能有垃圾数据。

这时,如果我们的User对象的id为null时,本来设计者是不希望这类‘不合法‘的数据不能被插入,但是由于这里的equals方法执行结果为false,因为HashSet认为里边不存在,所以将其加入set,导致垃圾数据诞生。因为我们通常对于集合中的数据要进行各类维护操作,有这个垃圾数据的存在往往导致很多不爽的问题,这些问题本人可以亲历过。

 

另外,关于用long和Long型数据作为参数的重载方法的代码,可读性不是很强,参考如下代码:

public class TestLong

{

    public static void main(String args[])

    {

       TestLong testLong = new TestLong();

       long id = 1L;

       testLong.test(id);

       Long id2 = 2L;

       testLong.test(id2);

    }

   

    public void test(long id)

    {

       System.out.println("原始类型:" + id);

    }

   

    public void test(Long id)

    {

       System.out.println("封装类型:" + id);

    }

}

对于用long作为参数的方法调用,究竟调用的是哪个方法呢,既然是Long和long可以隐式转换,应该都可以。但是我们知道,方法的调用分派是静态分派,也就是说,这里参数是long的调用选择test(long id)方法,而参数是Long的调用选择test(Long id)方法。执行结果如下:

原始类型:1

封装类型:2

证明了我们的分析时正确的。

但是如果我们注释掉重载方法中的任何一个,如:

 

public class TestLong

{

    public static void main(String args[])

    {

       TestLong testLong = new TestLong();

       long id = 1L;

       testLong.test(id);

       Long id2 = 2L;

       testLong.test(id2);

    }

   

//  public void test(long id)

//  {

//     System.out.println("原始类型:" + id);

//  }

   

    public void test(Long id)

    {

       System.out.println("封装类型:" + id);

    }

}

输出结果:

封装类型:1

封装类型:2

 

或者注释掉第2个重载方法,保留第一个重载方法,如下:

public class TestLong

{

    public static void main(String args[])

    {

       TestLong testLong = new TestLong();

       long id = 1L;

       testLong.test(id);

       Long id2 = 2L;

       testLong.test(id2);

    }

   

    public void test(long id)

    {

       System.out.println("原始类型:" + id);

    }

   

//  public void test(Long id)

//  {

//     System.out.println("封装类型:" + id);

//  }

}

运行输出:

原始类型:1

原始类型:2

 

总结:我个人认为在设计id作为实体类id,并且映射到数据库的主键时,最好用long ,这样避免了一些不必要的麻烦,除非特别需要对象类型,另外,关于用对象Long来判断是add 还是update,也可以将long id初始值为-1来实现其功能。

转载于:https://my.oschina.net/u/3393246/blog/920017

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值