Java随笔(1)注解(上)

3 篇文章 0 订阅

转载请注意:http://blog.csdn.net/wjzj000/article/details/53227352


个人GitHub上的俩个小小开源项目,希望各位大佬可以支持star一下。

https://github.com/zhiaixinyang/PersonalCollect  (拆解GitHub上的优秀框架于一体,全部拆离不含任何额外的库导入) 

https://github.com/zhiaixinyang/MyFirstApp(Retrofit+RxJava+MVP)



开始之前咱们先简单梳理一下什么是注解:单纯说注解,注解本身没有任何的作用。简单说和注释没啥区别,而它有作用的原因是注解解释类。也就是相关对注解进行解释的特定类。一般这些类使用反射的方式完成注解的一些业务。


今天记录一下关于注解的一个demo,效果是通过注解的方式快速生成SQL语句。

首先是注解类:Table,Column(分别代表:表和列)


@Target(ElementType.TYPE)   
@Retention(RetentionPolicy.RUNTIME)   
public @interface Table {  
	String value();   
}   


@Target(ElementType.FIELD)   
@Retention(RetentionPolicy.RUNTIME)   
public @interface Column {   
	String value();   
} 

@Target:
   用于描述注解的使用范围(即:被描述的注解可以用在什么地方)注解(annotation)可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在注解类型的声明中使用了target可更加明晰其修饰的目标。
  取值(ElementType)有:
  • ElementType.ANNOTATION_TYPE 可以应用于注释类型。
  • ElementType.CONSTRUCTOR 可以应用于构造函数。
  • ElementType.FIELD 可以应用于字段或属性。
  • ElementType.LOCAL_VARIABLE 可以应用于局部变量。
  • ElementType.METHOD 可以应用于方法级注释。
  • ElementType.PACKAGE 可以应用于包声明。
  • ElementType.PARAMETER 可以应用于方法的参数。
  • ElementType.TYPE 可以应用于类的任何元素。


@Retention:
  @Retention定义了该注解被保留的时间长短:某些注解仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的注解可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为注解与class在使用上是被分离的)。使用这个meta-Annotation可以对注解的“生命周期”限制。
  作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
  取值(RetentionPoicy)有:
    1.SOURCE:在源文件中有效(即源文件保留)
    2.CLASS:在class文件中有效(即class保留)

    3.RUNTIME:在运行时有效(即运行时保留)


@Documented:

用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。


@Inherited:

是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。注意:当@Inherited的Retention是RetentionPolicy.RUNTIME,则反射API增强了这种继承性。如果我们使用java.lang.reflect去查询一个@Inherited annotation类型的annotation时,反射代码检查将展开工作:检查class和其父类,直到发现指定的annotation类型被发现。





PS:
解只有一个成员时,按规范写成value(),当然不这么写不会报错。

如果不设置默认这,那么使用注解时必须要传值

  1. 只有类可以被注解,因为接口或者抽象类并不能用new操作实例化;
  2. 被注解的类,必须至少提供一个公开的默认构造器(即没有参数的构造函数)。否者我们没法实例化一个对象。

紧接着是注解的使用类:Person(就是一个使用注解的Java bean)
@Table("person")
public class Person {
	@Column("name")
	private String name;
	@Column("user_name")
	private String useName;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getUseName() {
		return useName;
	}
	public void setUseName(String useName) {
		this.useName = useName;
	}
}

PS:
如果有两个以上参数:必须这么使用@Column(value="user_name")


最终是main()里的使用:
public static void main(String[] args) {
		// TODO Auto-generated method stub
		Person p1=new Person();
		//设置表名和列名。PS:这里的变量名取得有点奇葩,大家请无视。
		p1.setName("ai");
		p1.setUseName("aiai");
		
		String str=query(p1);
		System.out.println(str);
	}
	
	public static String query(Person person){
		StringBuilder sb=new StringBuilder();
		//通过反射,获取Class对象
		Class p=person.getClass();
		//判断此Class是不是注解类
		boolean exist=p.isAnnotationPresent(Table.class);
		if(!exist){
			return null;
		}
		//如果是,强制类型转换成Table
		Table table=(Table)p.getAnnotation(Table.class);
		String tableName=table.value();
		//接下来便是取值拼接sql语句,并且重复这个过程。
		sb.append("select * from ").append(tableName).append(" where 1=1");
		Field[]  fArray=p.getDeclaredFields();
		for(Field field :fArray){
			boolean fExist=field.isAnnotationPresent(Column.class);
			if(!fExist){
				return null;
			}
			Column column=field.getAnnotation(Column.class);
			String cloumnName=column.value();
			String fieldName=field.getName();
			Object fieldValue=null;
			//此处将生成getXX方法,用于下边通过反射执行对应的get方法拿到里边的返回值。
			String getMethodName="get"+fieldName.substring(0, 1).toUpperCase()+fieldName.substring(1);
			try {
				Method method=p.getMethod(getMethodName);
				fieldValue=method.invoke(person);
			} catch (Exception e) {
				e.printStackTrace();
			} 
			sb.append(" and ").append(cloumnName).append("=").append(fieldValue);
		}
		return sb.toString();
	}



PS:
可能这样写感觉没什么用。但是如果这是一个库。那么我们只需要按照库的要求。使用相应的注解,按照特定的格式完成注解。就可以直接获取到最终结果了。比如可以在库中写一个工具类,直接调用这个工具类,传递所需的参数,返回最终拼接的sql语句而且,不会出现任何的语句错误。

想想是不是还有点小激动呢?


最近有结合安卓中的ButterKnife写了一遍关于注解的梳理,有兴趣的看官可以去捧个场:

http://blog.csdn.net/wjzj000/article/details/54177914



运行效果:


最后希望各位看官可以star我的GitHub,三叩九拜,满地打滚求star: 
https://github.com/zhiaixinyang/PersonalCollect 
https://github.com/zhiaixinyang/MyFirstApp


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值