开发插件 findbugs提示:May expose internal representation by incorporating reference to mutable object 的理解.

全部提示如下:
May expose internal representation by incorporating reference to mutable object
This code stores a reference to an externally mutable object into the internal representation of the object.  If instances are accessed by untrusted code, and unchecked changes to the mutable object would compromise security or other important properties, you will need to do something different. Storing a copy of the object is better approach in many situations.

然后,看他分析的这个代码,如下:

 
  1. package com.lxk.model;

  2.  
  3. import java.text.SimpleDateFormat;

  4. import java.util.Date;

  5.  
  6. /**

  7. * 测试 SimpleDateFormat 声明为静态变量能在toString中使用吗(能用但是线程不安全,这么声明不合适。)

  8. * <p>

  9. * Created by lxk on 2017/2/28

  10. */

  11. public class TimeFormatModel {

    扫描二维码关注公众号,回复: 2407653 查看本文章
  12. private Date date;

  13.  
  14. public TimeFormatModel() {

  15. }

  16.  
  17. public TimeFormatModel(Date date) {

  18. this.date = date;

  19. }

  20.  
  21. public Date getDate() {

  22. return date;

  23. }

  24.  
  25. public void setDate(Date date) {

  26. this.date = date;

  27. }

  28.  
  29. @Override

  30. public String toString() {

  31. return "TimeFormatModel{" +

  32. "data=" + formatTime() +

  33. '}';

  34. }

  35.  
  36. private String formatTime() {

  37. SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

  38. return format.format(date.getTime());

  39. }

  40. }

然后是分析的现场截图:

然后,看他的意思,来给你示范下,这么写的话是怎么出现意想不到的结果的。看下面main方法测试

 
  1. package com.lxk.findBugs;

  2.  
  3. import com.lxk.model.TimeFormatModel;

  4.  
  5. import java.util.Date;

  6.  
  7. /**

  8. * May expose internal representation by incorporating reference to mutable object

  9. * This code stores a reference to an externally mutable object into the internal representation of the object. 

  10. * If instances are accessed by untrusted code, and unchecked changes to the mutable object would compromise

  11. * security or other important properties, you will need to do something different. Storing a copy of the

  12. * object is better approach in many situations.

  13. * <p>

  14. * Created by lxk on 2017/3/23

  15. */

  16. public class Bug1 {

  17. public static void main(String[] args) {

  18. TimeFormatModel timeFormatModel = new TimeFormatModel();

  19. Date now = new Date();

  20. timeFormatModel.setDate(now);

  21. //Calendar calendar = Calendar.getInstance();

  22. //timeFormatModel.setDate(calendar.getTime());

  23. System.out.println(timeFormatModel.toString());

  24. now.setYear(4000);

  25. //calendar.set(Calendar.YEAR, 4000 + 1900);

  26. System.out.println(timeFormatModel.toString());

  27. }

  28. }


下面看执行结果:

看图里面的代码和执行结果,有这么几个注意的地方,可以看到。
1,代码里面有个方法是被撇弃的
now.setYear(4000);
我注释掉的部分就是它推荐替代被撇弃的代码,可见new Data(),这种写法,估计是 整体被抛弃啦,以后得少用。
2,分析,对比,代码两次打印的结果。
看到,日期竟然被修改了,当然这个就涉及到了引用传递值的问题。
这个也就是上面findbugs分析提出来的问题。他会有这么一种情况存在。

然后,再看怎么回避这个问题。

对原来的代码做修改。(我就整个贴了,反正你是观众,又不用写,耐心看嘛。)

 
  1. package com.lxk.model;

  2.  
  3. import java.text.SimpleDateFormat;

  4. import java.util.Date;

  5.  
  6. /**

  7. * 测试 SimpleDateFormat 声明为静态变量能在toString中使用吗(能用但是线程不安全,这么声明不合适。)

  8. * <p>

  9. * Created by lxk on 2017/2/28

  10. */

  11. public class TimeFormatModel {

  12. private Date date;

  13.  
  14.  
  15. public TimeFormatModel() {

  16. }

  17.  
  18. public TimeFormatModel(Date date) {

  19. this.date = (Date)date.clone();

  20. }

  21.  
  22. public Date getDate() {

  23. return (Date)date.clone();

  24. }

  25.  
  26. public void setDate(Date date) {

  27. this.date = (Date)date.clone();

  28. }

  29.  
  30. @Override

  31. public String toString() {

  32. return "TimeFormatModel{" +

  33. "data=" + formatTime() +

  34. '}';

  35. }

  36.  
  37. private String formatTime() {

  38. SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

  39. return format.format(date.getTime());

  40. }

  41. }


这个时候,再分析以下。

就没有问题啦。

然后,上面的问题就解决啦。

思考:

说实话,以前我真没在意过这个bean的写法,这些个getter和setter都是编辑器自动生成的,都压根都考虑过这个事情。
当然,像上面的这个问题,我还真的遇到过。就是Java里面的clone的实现,有个深克隆和浅克隆的区别。
当然 ,实际情况中,bean里面的代码不都是这么简单的实现getter和setter的嘛,不会说像上面那样处理。
因为你在使用的过程中,肯定是把数据处理OK之后,再set到对应属性里面去。之后是不会操作的。
要是像上面的main测试方法一样,这么改的话,那代码就真不知道怎么写了。
只是,这个提示起到一个惊醒的作用。
让你知道,在Java里面有值转递和引用传递的存在。而且,因为这个,可能会发生一些莫名其妙的bug。
当你知道啦这些莫名其妙的bug之后,就会在实际遇到的时候,就有个思考的方向。
也算是涨姿势啦

猜你喜欢

转载自blog.csdn.net/michael_hm/article/details/81181713
今日推荐