您的位置 首页 java

如何写好java注释

什么是 java注释

要回答这个问题,先提出一个说法:我们写的代码是给人看的,不是给机器看的.
如果你不认可这个说法,下面关于代码注释的一些总结想必对你也没啥帮助.
如果你认可这个说法, 那么下面的文章希望会给你一些帮助.

回到本段的主题,什么是java注释呢?

  1. 首先,注释是面向代码维护者的: 注释是对代码逻辑的一段说明, 方便后续的代码维护者能够快速地了解这段代码的含义,并依次为基础能够在现有代码的基础上做修改与维护.
  2. 其次,注释是面向系统使用者的: 要知道类似于 java ,或者 spring 这样偏向于底层,框架类的代码.全世界有数以万计的使用者的,这些人没精力也没有必要在调用api的时候去了解这段代码的底层实现逻辑,所以这段代码的api说明文档就显得很重要了.而代码上的注释就是相关api文档的主要来源.
  3. 通过 javadoc 命令,可以将注释抽离生成html文档,比如官方的java16API文档

如何写好java注释

想要写好代码的注释,我们要从注释的面向用户来考虑.不同的用户关注点还是有点差异的.

面向代码维护者

作为一名代码的维护者,当我们拿到一份没有任何注释的代码的时候,相信大家内心的感受是相同的.毕竟人类的悲欢并不相通, 除非看到没有注释的代码.

如果有了解设计模式的朋友,相信一定听说过一个设计原则:开闭原则, 对扩展开发,对修改关闭. 那么大家有没有想过为啥会有这个原则呢?

翻译一下: 修改现有的代码是有风险的,但是如果是扩展写新代码的话,作为开发者的你,是了解当前功能的前后背景的,而且你无论怎么写都不会对历史功能产生影响.所以对我们的代码设计能力提出来要求.

再翻译一下: 原来的代码既然跑得好好的,为啥要修改它呢, 改出问题来算谁的?

再翻译一下: 为啥我们不敢改以前的代码呢?谁知道当时为啥要写这段逻辑,谁知道这段逻辑有谁在用?改好了没有夸, 改崩了有锅背.

这就是我们维护老代码的困境!

作为一名 程序员 ,我们要有一个概念,我们的代码是我们某个时刻的思维逻辑的固化.
如果是一个比较简单的逻辑,注释可以简单写写.
如果是一段比较复杂的逻辑,那么我们的注释要能够描述清楚我们当时的这段逻辑的背景(为什么要写这段逻辑), 意图(这段逻辑要实现什么效果), 用法(这段逻辑改如何使用,以及谁在用), 最好能有修改建议.

在业界开源的代码里有很多比较好的例子,来个spring的:

 /**
 *  AOP  Alliance MethodInterceptor for declarative  transaction 
 * management using the common Spring transaction infrastructure
 * ({@link org.springframework.transaction.PlatformTransactionManager}/
 * {@link org.springframework.transaction.ReactiveTransactionManager}).
 *
 * <p>Derives from the {@link TransactionAspectSupport} class which
 * contains the integration with Spring's underlying transaction API.
 * TransactionInterceptor simply calls the relevant superclass methods
 * such as {@link #invokeWithinTransaction} in the correct order.
 *
 * <p>TransactionInterceptors are thread-safe.
 *
 * @author  Rod Johnson 
 * @author Juergen Hoeller
 * @see TransactionProxyFactoryBean
 * @see org.springframework.aop.framework.ProxyFactoryBean
 * @see org.springframework.aop.framework.ProxyFactory
 */
  

面向api使用者

对于api的使用者,注释文档的要求相对简单些.

他们只关心这个方法的功能是什么, 以及入参有哪些,出参会有哪些, 会不会抛异常等, 会不会返回 null 等. 他们不关心这个方法的内部实现逻辑是啥, 比如一个排序方法, 使用者不关心这个方法内部使用 冒泡排序 ,还是快排, 只要能完成诉求就行.

所以,面向api的使用者的注释,原则就是让他知道这个方法怎么使用就行了.

 /**
* Returns an Image object that can then be painted on the screen. 
* The url argument must specify an absolute <a href="#{@link}">{@link URL}</a>. The name
* argument is a specifier that is relative to the url argument. 
* <p>
* This method always returns immediately, whether or not the 
* image  exists . When this  applet  attempts to draw the image on
* the screen, the data will be loaded. The graphics primitives 
* that draw the image will incrementally paint on the screen. 
*
* @param  url  an absolute URL giving the base location of the image
* @param  name the location of the image, relative to the url argument
* @return      the image at the specified URL
* @see         Image
*/
public Image getImage(URL url,  String  name) {
try {
return getImage(new URL(url, name));
} catch (MalformedURL exception  e) {
return null;
}
}
  

写好java注释常用的技巧

常用的注释tag

  1. @param 方法参数
  2. @return 方法返回值
  3. @throws 方法抛出的异常, java1.2后添加
  4. @exception 同@throws
  5. @see 查看参考代码
  6. @author 标识作者
  7. @version 代码版本
  8. @since 从某个版本开始引入
  9. @serial( @serialField @serialData)
  10. @deprecated 废弃某个版本的代码

常用的内联tag

  1. {@code} : 代码高亮,等同于 {@literal}
 <code>{@literal}</code>
  
  1. {@docRoot} : 标记文档的根路径,用来实现 相对路径
 /**
* See the <ahref="{@docRoot}/copyright.html">Copyright</a>.
*/
  
  1. {@inheritDoc} : 继承某个文档,嵌套文档使用
  2. {@link url} : 在注释文本区域内, 内联一个链接
 Use the {@link #getComponentAt(int, int) getComponentAt} method.

  
  1. {@linkplain url label} 相对于{@link}, 支持自定义label文案来代指这段url
 Refer to {@linkplain add() the overridden method}.
会显示为
Refer to 'the overridden method'.

  
  1. {@literal} 转义用, 方便显示一些特殊字符
  2. {@value} 常量时, 会直接显示标注代码的值

注释语句中的小技巧

@param @return @throws

一个正常方法必然会用到的注释tag,
@param 代表方法的入参,
@return 代表方法的返回值.
@throws 代表可能引发方法中断的异常. 等同与 @exception
这里需要特别说明一下, 有些人可能觉得只有那些受检异常(也就是必须在方法签名里声明的异常)才需要在注释里声明@throws. 其实不是的. 所有引发程序中断的异常, 包括运行时异常都可以在注释里说明, 也可以在方法签名里添加. 尤其是自定义的异常.
举个例子:

  /**
  * Return the underlying ThreadPoolExecutor for native access.
  * @return the underlying ThreadPoolExecutor (never {@code null})
  * @throws Illegal state Exception if the ThreadPoolTaskExecutor hasn't been initialized yet
  */
 public ThreadPoolExecutor getThreadPoolExecutor() throws IllegalStateException {
  Assert.state(this.threadPoolExecutor != null, "ThreadPoolTaskExecutor not initialized");
  return this.threadPoolExecutor;
 }
  

这里的IllegalStateException 是一个RuntimeException异常, 我们在方法里可能抛出这个异常, 最好是在方法签名里声明一下, 然后在代码注释里说明一下.

@see

当前代码可以参考的其他代码, 后面跟代码的全路径,可以是类,方法,属性等.具体参考如下:

 @see #field
@see # Constructor (Type, Type...)
@see #Constructor(Type id, Type id...)
@see #method(Type,  Type ,...)
@see #method(Type id, Type, id...)
@see Class
@see Class#field
@see Class#Constructor(Type, Type...)
@see Class#Constructor(Type id, Type id)
@see Class#method(Type, Type,...)
@see Class#method(Type id, Type id,...)
@see package.Class
@see package.Class#field
@see package.Class#Constructor(Type, Type...)
@see package.Class#Constructor(Type id, Type id)
@see package.Class#method(Type, Type,...)
@see package.Class#method(Type id, Type, id)
@see package
  

@author

标识当前代码的作者是谁, 可以一个,也可以有多个.

@version @since

都是版本相关的tag
@version 标识当前版本好, 编译的时候会用到. 符合SCCS规范.
@since 标识这段代码的引入版本

@serial @serialField @serialData

序列化 相关的属性, 标识哪些字段可以序列化,哪些不行.

@deprecated

废弃某段代码,表示不再维护,并在一段时间后会被删除. 标记后, 相关的引用位置会被标记为删除线.
个人认为这个tag还是很有用的:

  1. 创建代码容易删除难, 这个tag能够很好的帮忙我们去下线不再维护的代码,减轻维护压力.(愿世界上屎山越来越少)
  2. 方便我们代码升级. 如果我们要升级一段代码,先将老代码废弃,然后通过@see,引导用户使用新的方法.
 /**
* @deprecated  As of JDK 1.1, replaced by 
*               
 setBounds
* @see #setBounds(int,int,int,int)
*/
  

html 标签来排版

 <p> : 新起一段
<br> : 换行
  

代码块样式

想在JAVA的注释中添加一段代码,并且可以优雅的编译出来还是挺麻烦的.下面提供一种方法

    /**
     * 下面的代码注释可以按代码格式编译
     * <pre class=code>
     *     citys : [
     *         beijing,
     *         shanghai
     *      ]
     * </pre>
     *
     */
     private  List<String>> citys;

  

参考

文章来源:智云一二三科技

文章标题:如何写好java注释

文章地址:https://www.zhihuclub.com/181748.shtml

关于作者: 智云科技

热门文章

网站地图