如何在Java代码中保留注释?

前言: 这学期学习了编译原理,了解了代码中的注释是在编译的时候会被过滤——因为它是给人读的,不是给机器读的。所以,就自然想到了如何才能在代码中保留注释,但是又不影响到程序的执行?虽然,这个想法其实没有多大的作用,但是感觉很有趣,就简单的实现了一下。这里我们借助Java语言的一个功能——Annotation注解来实现。

注:关于注解,因为平常很少自己定义,主要就是使用。所以我对于它也只是有一点了解。但是对于这篇博客,需要的知识也不多,主要在CSDN上看几篇相关的博客就行了。

定义注解

说明:该注解的作用范围是 方法和实例变量。
注解在代码中保留的时间是运行时。

它主要有两个属性,第一个是String类型的 comment,我就使用它来给代码添加注解,这样的话,我就可以在代码中保留注释了。但是只有一个功能太单调了,然后我又添加了一个String类型的value,使用它来给被标注的变量赋值,如果是方法的话,那么就使用默认值即可。(当然了,这里我没有在方法上使用它。)

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(value = {ElementType.METHOD, ElementType.FIELD})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Comment {
    String comment();
    String value() default "";
}

定义一个使用注解的类

/**
 * 这是一个Java的注释,这里只是作为测试使用。
 * 下面是一个 Boy 类,它具有name、age、isSingle属性。
 * */
public class Boy {
    @Comment(comment = "boy的姓名", value = "龙林夕")
    private String name;
    @Comment(comment = "boy的年龄", value = "22")
    private int age;
    @Comment(comment = "boy的感情状况,是否单身", value="true")
    private boolean isSingle;

	//省略了getter和setter,不过似乎也没有用到,哈哈!

    @Override
    public String toString() {
        return "Boy{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", isSingle=" + isSingle +
                '}';
    }
}

编写注解处理工具

注解并不会主动生效,必须使用相应的工具来处理,这些工具称之为——Annotation Process Tool(APT)。使用它来处理被注解标注的代码,并对之进行处理。我们这里来简单定义一个APT,它的功能很简单——读取注解中的注释和值,并将值赋给相应的变量。这个注释读取出来也没有用,只是简单的打印出来,但是我们的目的就是为了能在运行期看到它!

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class APT {
    public static Boy process() throws NoSuchMethodException,
            IllegalAccessException,
            InvocationTargetException,
            InstantiationException {
        Class<?> clazz = Boy.class;                     //获取 Class 对象
        Constructor con = clazz.getConstructor(null);   //获取默认的空构造器
        Boy obj = (Boy) con.newInstance(null);          //使用空构造器创建对象,并强制类型转换为Boy类型
        Field[] fields = clazz.getDeclaredFields();     //获取所有声明的实例变量(包括私有的示例变量),注意不能使用 getFields(),否则无法获取到私有的实例变量。

		/**
		* 循环处理每一个field,如果它的类型是String类型,就直接把value值赋给它;
		* 如果它的类型是 int 类型,就把value转为int类型;
		* 如果它的类型是 boolean 类型,就把value转为 boolean 类型。
		* 注意:这里处理引用类型和基本数据类型的区别。
		* 对于引用类型,我使用了 Class 对象的 isInstance() 方法
		* 对于基本数据类型,我使用了 == 的判断方式。
		*/
        for (Field field : fields) {                    
            Comment comment = field.getAnnotation(Comment.class);
            String strComment = comment.comment();
            System.out.println(strComment);
            String value = comment.value();
            Class<?> cla = field.getType();
            field.setAccessible(true);            //设置可访问权限,否则无法修改私有变量
            if (cla.isInstance("")) {
                field.set(obj, value);
            } else if (cla == int.class) {      //基本类型无法使用 isInstance 方法
                field.setInt(obj, Integer.parseInt(value));
            } else if (cla == boolean.class) {
                field.setBoolean(obj, Boolean.parseBoolean(value));
            }
        }
        return obj;
    }
}

测试代码

public class Test {
    public static void main(String[] args) {
        try {
            Boy boy = APT.process();             //使用自定义APT处理注解。
            System.out.println(boy.toString());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
}

运行截图

在这里插入图片描述

PS:在JD-GUI中打开 APT.class文件,可以看见见过反编译的文件是没有注释的。
在这里插入图片描述
注解中的信息是属于代码的,所以可以得到保留,因此就间接实现了注释的保留。
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值