• Java 注释


    Java 注释

    标签 : Java基础


    五月份得知入职阿里云OS, 才开始学Java, 断断续续学习/使用半年, 越来越喜欢这个语言/工具. 后来被拥抱变化之后, 拿到的大部分offer是Java服务端研发; 一路走来, 踩了很多坑, 也有了一点小小的心得, 而且博客已经停更几个月, 今天就以博客形式把他记录下来吧.
    2015下半年第一篇博客, 从最基础的Java注释开始:


      程序员圈有一个笑话

    最讨厌在写代码的时候写注释, 最讨厌别人的代码里面不写注释.


    为什么写注释?

      我自己亲身经历:
      这段时间在微店实习, 第一个接手的项目是将原先北京团队的代码迁移到杭州, 由于底层技术架构的更换, 大部分代码需要重写, 前提是要理解原先的业务逻辑, 但当我在SVN上把代码拉下来, 看到意大利面似的一大坨代码里只有寥寥几行注释时, 整个人都不好了…
      另一个遇到场景, 有时自己的代码有Bug, 或者需要重构, 此时就需要Review代码, 可是突然发现自己已经很难理解原先逻辑了(很可能这段代码只是你前几天刚刚写的), 因为我们已经很难回到当时状态.
      还有一个重要的原因就是文档, 往往一个系统被开发出来, 文档要么不全, 要么更新落后, 如果后人要接手这一套系统, 就必须直接阅读源码, 如果此时在代码的关键逻辑之处能够有一两行注释提示, 新人就没有必要绞尽脑汁去猜测当时的设计方案了.
      后来自己写代码时就尽量写注释提示, 虽然不一定完全按照下面的注释规范, 但会尽量用 最简单的语言把问题阐述清楚, 在逻辑转折之处添加几行说明, 无论是自己还是未来的接手人, 都会对现在的你感激不尽.


    注释类型

      Java提供三种注释方式: 单行注释、多行注释、文档注释.

    • 单行/多行注释
      单行注释与多行注释的作用就不再赘, IDEA快捷键分别如下:
         command+/: 以//快速注释一行或多行 :
    //        Integer[] array = new Integer[10];
    //        for (int i = 0; i < array.length; ++i){
    //            array[i] = new Integer(i);
    //        }

       command+option+/: 以/**/快速注释一行或多行

    /*
            Integer[] array = new Integer[10];
            for (int i = 0; i < array.length; ++i){
                array[i] = new Integer(i);
            }
    */
    • 文档注释
        Java提供了一种功能非常强大的注释形式: 文档注释. 如果编写Java源代码时添加了文档注释, 然后通过JDK提供的javadoc工具就可以直接将代码里的注释提取成一份系统的API文档. 其注释形式为/** */
        /**
         * Initializes a newly created {@code String} object so that it represents
         * the same sequence of characters as the argument; in other words, the
         * newly created string is a copy of the argument string. Unless an
         * explicit copy of {@code original} is needed, use of this constructor is
         * unnecessary since Strings are immutable.
         *
         * @param  original
         *         A {@code String}
         */

    # javadoc 注释标签语法

    标签 作用域 说明
    @author 标明开发该类模块作者
    @version 标明该类模块的版本
    @see 类, 属性, 方法 参考转向(相关主题)
    @param 方法 对方法中某参数的说明
    @return 方法 对方法返回值的说明
    @exception 方法 抛出的异常类型
    @throws 方法 与@exception相同
    @deprecated 方法 不建议使用该方法

    注释原则

    下面是我自己看到和用过的注释原则:

    1. 注释准确简洁
      内容简单明了、含义准确, 尽量用最少的语言把问题阐述清楚, 防止注释的多义性,错误的注释不但无益反而有害.
    2. 避免复杂注释
      如果需要用复杂的注释来解释代码, 请检查此代码是否应该重写. 尽一切可能不注释难以理解的代码, 最好选择重构.
    3. TODO List
      为尚未完成的代码添加TODO注释, 提醒自己还需后续完善.
    4. 注释形式统一
      在整个项目中,使用一致的结构样式来构造注释.
    5. 注释与代码同步更新
      边写代码边注释,因为以后很可能没有时间来写注释了(可能在今天看来很明显的东西六周以后或许就不明显了). 通常描述性注释先于代码创建解释性注释在开发过程中创建提示性注释在代码完成之后创建. 修改代码的同时修改注释,保证代码与注释同步.
    6. 注释就近
      保证注释与其描述的代码相邻, 在代码上方或右方(最好上方)进行注释.
    7. 注释不要过多
      注释必不可少,但也不应过多,注释占程序代码的比例少于20%为宜.注释是对代码的“提示”,而不是文档. 如果代码本来就一目了然就不加注释.
    8. 删除无用注释
      在代码交付或部署发布之前, 删除临时或无关注释, 避免日后维护中产生混乱.
    9. 必加注释之处
      • 典型算法必有注释
      • 代码不明晰处必有注释
      • 在循环/逻辑分支组成的代码中加注释
      • 为他人提供的接口必有注释
      • 代码修改处加修改标识

    JDK注释参考:

    • 类/接口注释
    /**
     * The <code>String</code> class represents character strings. All
     * string literals in Java programs, such as <code>"abc"</code>, are
     * implemented as instances of this class.
     * (其他描述)
     * @author  Lee Boynton
     * @author  Arthur van Hoff
     * @author  Martin Buchholz
     * @author  Ulf Zibis
     * @see     java.lang.Object#toString()
     * @see     java.lang.StringBuffer
     * @see     java.lang.StringBuilder
     * @see     java.nio.charset.Charset
     * @since   JDK1.0
     */
    
     public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence {
        ...
    }
    • 构造器注释
        /**
         * Initializes a newly created {@code String} object so that it represents
         * the same sequence of characters as the argument; in other words, the
         * newly created string is a copy of the argument string. Unless an
         * explicit copy of {@code original} is needed, use of this constructor is
         * unnecessary since Strings are immutable.
         *
         * @param  original
         *         A {@code String}
         */
        public String(String original) {
            this.value = original.value;
            this.hash = original.hash;
        }
    • 方法注释
        /**
         * Returns <tt>true</tt> if, and only if, {@link #length()} is <tt>0</tt>.
         *
         * @return <tt>true</tt> if {@link #length()} is <tt>0</tt>, otherwise
         * <tt>false</tt>
         *
         * @since 1.6
         */
        public boolean isEmpty() {
            return value.length == 0;
        }
    • 字段/属性注释
        /** The value is used for character storage. */
        private final char value[];
    
        /** Cache the hash code for the string */
        private int hash; // Default to 0
    
        /** use serialVersionUID from JDK 1.0.2 for interoperability */
        private static final long serialVersionUID = -6849794470754667710L;
    
        /**
         * Class String is special cased within the Serialization Stream Protocol.
         *
         * A String instance is written initially into an ObjectOutputStream in the
         * following format:
         * <pre>
         *      <code>TC_STRING</code> (utf String)
         * </pre>
         * The String is written by method <code>DataOutput.writeUTF</code>.
         * A new handle is generated to  refer to all future references to the
         * string instance within the stream.
         */
        private static final ObjectStreamField[] serialPersistentFields =
                new ObjectStreamField[0];
    • 方法内注释
        public boolean regionMatches(boolean ignoreCase, int toffset,
                String other, int ooffset, int len) {
            char ta[] = value;
            int to = toffset;
            char pa[] = other.value;
            int po = ooffset;
            // Note: toffset, ooffset, or len might be near -1>>>1.
            if ((ooffset < 0) || (toffset < 0)
                    || (toffset > (long)value.length - len)
                    || (ooffset > (long)other.value.length - len)) {
                return false;
            }
            while (len-- > 0) {
                char c1 = ta[to++];
                char c2 = pa[po++];
                if (c1 == c2) {
                    continue;
                }
                if (ignoreCase) {
                    // If characters don't match but case may be ignored,
                    // try converting both characters to uppercase.
                    // If the results match, then the comparison scan should
                    // continue.
                    char u1 = Character.toUpperCase(c1);
                    char u2 = Character.toUpperCase(c2);
                    if (u1 == u2) {
                        continue;
                    }
                    // Unfortunately, conversion to uppercase does not work properly
                    // for the Georgian alphabet, which has strange rules about case
                    // conversion.  So we need to make one last check before
                    // exiting.
                    if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
                        continue;
                    }
                }
                return false;
            }
            return true;
        }
    
        String(char[] value, boolean share) {
            // assert share : "unshared not supported";
            this.value = value;
        }
    
        char[] val = value;   /* avoid getfield opcode */
    
        public boolean contentEquals(CharSequence cs) {
            if (value.length != cs.length())
                return false;
            // Argument is a StringBuffer, StringBuilder
            if (cs instanceof AbstractStringBuilder) {
                char v1[] = value;
                char v2[] = ((AbstractStringBuilder) cs).getValue();
                int i = 0;
                int n = value.length;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
            // Argument is a String
            if (cs.equals(this))
                return true;
            // Argument is a generic CharSequence
            char v1[] = value;
            int i = 0;
            int n = value.length;
            while (n-- != 0) {
                if (v1[i] != cs.charAt(i))
                    return false;
                i++;
            }
            return true;
        }

    附: 开发者工具

    • IDEA: 比较给力的Java IDE, 用过都说好(“自从用了IDEA, 写代码越来越有劲儿了”). 非常多很赞的功能, 如对Git、Maven的原生支持, 自动代码提示, 自带命令行, 黑色主题, UML类图生成… 而且现在IDEA家族也越来越强, Android开发的Android Studio、IOS的AppCode、C/C++的CLion、Python的PyCharm、PHP的PhpStorm、前端的WebStorm等等, 详细可查看Jet Brains官网.
    • Git&GitHub: Git就不用多做介绍了, 算是开发者居家旅行之必备吧. 这方面的书/视频很多, 但在此我只推荐一部文档: 廖雪峰的Git教程. 虽然Git内容繁多, 但这篇文档却直取要害, 非常实用, 读了很多遍.
    • Maven: Maven方面我也是新手, 在此我只推荐一部还不错的Maven方面的书, Maven实战, 一部国人写的实战类书籍.
    • SQLPro for MySQL: 一款MySQL-GUI客户端, 用过MySQL-WorkBench、Navicat、Sequel Pro, 但最后还是选择的SQLPro for MySQL.
    • ProcessOn: 免费绘图网站, UML、流程图、网络拓扑… 上手容易.
    • Markdown: 这方面我也是初学者, 推荐两个客户端Cmd MarkdownMWeb.
    • JSON查看&编辑
      这方面除了TextLab没有发现其他好用的客户端, 只能推荐几个网站:
      • qqe2.com: 对JSON数据排错提示功能很强大;
      • json.cn, 查看JSON数据非常美观, 支持代码折叠.
    • RegExRx
      Mac上非常好用的正则表达式匹配引擎, 用于测试正则表达式书写的正确与否.
    • iTerm2
      忘掉Mac自带的终端吧, iTerm你值得拥有.
    • Alfred
      最后, 推荐Mac效率神器Alfred, 推荐博客: 从零开始学习 Alfred(上):基础功能及设置, 其他功能还在探索.

    在此只推荐了我所知道和常用一些小工具, 欢迎同学补充.


  • 相关阅读:
    三:Redis连接池、JedisPool详解、Redisi分布式
    vmware workstation14永久激活密钥分享
    人工智能二:TensorFlow环境搭建
    消息队列二:关于消息队列
    消息队列一:为什么需要消息队列(MQ)?
    java基础进阶一:String源码和String常量池
    人工智能一:Al学习路线
    Python学习二:词典基础详解
    Python学习一:序列基础详解
    什么是Hive
  • 原文地址:https://www.cnblogs.com/itrena/p/5926925.html
Copyright © 2020-2023  润新知