我们在处理完 IO 操作后,通常会在 finally 块中把打开的 IO 流资源手动关闭,以前一直用 Eclipse,今天用 IDEA 写了一个小例子,刚好写到处理流的关闭操作。IDEA 提示了我一个编码风格的问题,它认为我有两段代码重复了,代码内容如下:

    1. public class JavaSerializer implements ISerializer {
    2. @Override
    3. public <T> byte[] serialize(T obj) {
    4. ByteArrayOutputStream baos = new ByteArrayOutputStream();
    5. ObjectOutputStream oos = null;
    6. try {
    7. oos = new ObjectOutputStream(baos);
    8. oos.writeObject(obj);
    9. return baos.toByteArray();
    10. } catch (IOException e) {
    11. e.printStackTrace();
    12. } finally {
    13. if (oos != null) {
    14. try {
    15. oos.close();
    16. } catch (IOException e) {
    17. e.printStackTrace();
    18. }
    19. }
    20. if (baos != null) {
    21. try {
    22. baos.close();
    23. } catch (IOException e) {
    24. e.printStackTrace();
    25. }
    26. }
    27. }
    28. return new byte[0];
    29. }
    30. @Override
    31. public <T> T deserialize(byte[] data, Class<T> clazz) {
    32. ByteArrayInputStream bais = new ByteArrayInputStream(data);
    33. ObjectInputStream ois = null;
    34. try {
    35. ois = new ObjectInputStream(bais);
    36. return (T) ois.readObject();
    37. } catch (IOException e) {
    38. e.printStackTrace();
    39. } catch (ClassNotFoundException e) {
    40. e.printStackTrace();
    41. } finally {
    42. if(ois != null) {
    43. try {
    44. ois.close();
    45. } catch (IOException e) {
    46. e.printStackTrace();
    47. }
    48. }
    49. if(bais != null) {
    50. try {
    51. bais.close();
    52. } catch (IOException e) {
    53. e.printStackTrace();
    54. }
    55. }
    56. }
    57. return null;
    58. }
    59. }

    image.png

    IDEA 认为我上下这两段代码重复了。我觉得比较奇怪,确实两段代码都是处理 IO 流的关闭,写法也一样,但是我关闭的是不同的 IO 流资源啊,上面是关闭 ByteArrayOutputStream 和 ObjectOutputStream 这两个流的资源,下面是关闭 ByteArrayInputStream 和 ObjectInputStream 这两个流的资源,不能说代码是完全重复的吧,但是 IDEA 就给我提示了。

    这两处的提示比较碍眼,本来想在 IDEA 中关闭重复代码提示得了,也不用操心这类问题,突然比较好奇有没有什么好办法统一处理这个重复问题,是否能提炼一个公共的方法?

    琢磨了一会,这四个 IO 操作类是不同的类型,怎么能提炼呢?提供一个思路,我们想办法找找他们的交集,是不是有一个共用的继承类或者接口,并且这个共用类或者接口要有 close() 方法,否则也是白搭。

    我们来看下这四个类的类图,找找他们的继承体系,所幸的是 IDEA 可以看类图结构,非常方便:

    image.png

    猜测 Closeable 接口好像可以满足要求,我们进去看看该接口的内容:

    image.png

    1. 满足是这四个 IO 操作类的共用接口的条件。
    2. 满足需要提供 close() 方法的条件。

    接下来就是提炼一个公共的方法,代码结构如下:

    1. public class JavaSerializer implements ISerializer {
    2. @Override
    3. public <T> byte[] serialize(T obj) {
    4. ByteArrayOutputStream baos = new ByteArrayOutputStream();
    5. ObjectOutputStream oos = null;
    6. try {
    7. oos = new ObjectOutputStream(baos);
    8. oos.writeObject(obj);
    9. return baos.toByteArray();
    10. } catch (IOException e) {
    11. e.printStackTrace();
    12. } finally {
    13. close(oos, baos);
    14. }
    15. return new byte[0];
    16. }
    17. @Override
    18. public <T> T deserialize(byte[] data, Class<T> clazz) {
    19. ByteArrayInputStream bais = new ByteArrayInputStream(data);
    20. ObjectInputStream ois = null;
    21. try {
    22. ois = new ObjectInputStream(bais);
    23. return (T) ois.readObject();
    24. } catch (IOException e) {
    25. e.printStackTrace();
    26. } catch (ClassNotFoundException e) {
    27. e.printStackTrace();
    28. } finally {
    29. close(ois, bais);
    30. }
    31. return null;
    32. }
    33. /**
    34. * 关闭 IO 资源
    35. *
    36. * @param closeables IO 资源
    37. */
    38. private void close(Closeable... closeables) {
    39. for (Closeable closeable : closeables) {
    40. if (closeable != null) {
    41. try {
    42. closeable.close();
    43. } catch (IOException e) {
    44. e.printStackTrace();
    45. }
    46. }
    47. }
    48. }
    49. }

    这样 IDEA 就不会再提示了,整个类的代码量也压缩了一点,代码结构也清晰了一些。

    作者:殷建卫 链接:https://www.yuque.com/yinjianwei/vyrvkf/gwhiom 来源:殷建卫 - 架构笔记 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。