注解和反射

# 1、 注解:
什么是注解
- Annotation是从JDK5.0开始引入的新技术
- Annotation的作用
- 不是程序本身,可以对程序做出解释(和注释作用差不多)
- 可以被其他程序(比如:编译器等)读取
- Annotation的格式
- 注释是以“@注释名”在代码中存在的,还可以添加一些参数值,例如:@SuppressWarmings(value = “unchecked”)
- Annotation在哪里可以使用
- 可以附加在package、class、method、field等上卖弄,相当于他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元素的的访问。
```java
package com.dong.annotation.lesson01;
//什么是注解
public class Test01 extends Object {
@Override
public String toString() {
return super.toString();
}
}
```
内置注解
- @Override:定义在java.lang.Override中,此注释只适用于修饰方法,表示一个方法声明打算重写超类中的另一个方法声明。
- @Deprecated:定义在java.lang.Deprecated中,此注释可以用于修辞方法,属性,类,表示不鼓励程序员使用这样的元素,通常是因为它很危险或者存在更好的选择。
- @Suppressedwarnings:定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息。
- 与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参数都是已经定义好了的,我们选择性的使用就好了。
- @
- @
- @
```java
package com.dong.annotation.lesson01;
import java.util.ArrayList;
//什么是注解
public class Test01 extends Object {
//@Override 重写的注解
@Override
public String toString() {
return super.toString();
}
//@Deprecated 不推荐程序员使用,但是可以用,或者存在更好的方法
@Deprecated
public static void test(){
System.out.println("Deprecated");
}
// @SuppressWarnings 镇压警告
@SuppressWarnings("all")
public void Test2(){
ArrayList
}
public static void main(String[] args) {
test();
}
}
```
元注解
- 元注解的作用就是负责注解其他注解,java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明
- 这些类型和他们所支持的类在java.lang.annotation包中可以找到(@Target,@Retention,@Documented,@Inherited)
- @Target:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
- @Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(SOURCE<CLASS<RUNTIME)
- @Documented:说明该注解将被包含在javadoc中
- @Inherited :说明子类可以继承父类中的该注解
```java
package com.dong.annotation.lesson01;
import java.lang.annotation.*;
public class Test02 {
@MyName
public static void main(String[] args) {
}
}
//Target 表示注解的目标范围
@Target(value = {ElementType.METHOD,ElementType.TYPE} )
//Retention 表示我们的注解在什么地方有效
//SOURCE< CLASS <RUNTIME
@Retention(value = RetentionPolicy.RUNTIME)
//表示生成的注解是在JAVADOC文件中
@Documented
//表示生成的注解可以被继承
@Inherited
//定义一个注解
@interface MyName{
}
```
自定义注解
- 使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口
- 分析
- @interface用来声明一个注解,格式:public @interface 注解名{定义内容}
- 其中的每一个方法实际上是声明了一个配置参数
- 方法的名字就是参数的类型(返回值只能是基本类型,Class,String,enum)
- 可以通过default来声明参数的默认值
- 如果只有一个参数成员,一餐参数名字为value
- 注解元素必须要有只,我们定义注解元素时,经常使用空字符串,0,作为默认值。
```java
package com.dong.annotation.lesson01;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@MyAnnotation(10)
public class Test03 {
@MyName2(name="xiao",age=10,ID=1,school = {"航空航天大学","卫生大学" })
public static void main(String[] args) {
}
}
@Target({ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@interface MyName2{
//注解的参数:参数类型 + 参数名();
String name() default "wang";
int age() default 100;
int ID() default 1;
String[] school();
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
@interface MyAnnotation{
int value();
}
```
## 2、反射
## 静态VS动态语言
### 动态语言:
- 是一类在运行时可以改变其结构的语言,例如:新的函数、对象甚至代码可以被引进,已有的函数可以被删除或是其他结构的变化。通俗点就是在运行时代码可以根据某些条件改变其自身结构。
- 主要动态语言:Object-C、C#、JavaScrip,PHP、Python等
### 静态语言:
- 与动态语言相对应的时静态语言,运行时结构不可以被改变。如java、c、c++
- java不是动态语言,但是java可以称之为“准动态语言”,即java有一定的动态性,我们可以利用反射机制获得类似动态语言的特性。java的动态性让编程的时候更加灵活。
### Java Reflection
- Reflection (反射),时Java被视为动态语言的关键,反射机制允许程序在执行期间借助于Reflection API取得任何类的的内部信息,并能直接操作任意对象的内部属性及方法。
```java
Class c = Class.forName("java.lang.String");
```
- 加载完类之后,在堆内存的方法取中就产生一个Class类型的对象,(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息,我们可以通过个对象看到类的结构。这个对象就像一个镜子,透过这个镜子我们看到了类的结构,所以,我们形象的称之为:反射。
注解和反射
### java反射机制提供的功能
- 在运行时,判断任意一个对象所属的类
- 在运行时,构造任意一个类的对象
- 在运行时,判断任意一个类所具有的成员变量和方法
- 在运行时,获取泛型信息
- 在运行时,调用任意一个对象的成员变量和方法
- 在运行时,处理注解
- 生成动态代理
优点:
- 可以事项动态的创建对象和编译,体现很大的灵活性
缺点:
- 对性能有影响,使用反射基本上是一种解释性操作,我们可以直接告诉JVM,我们希望做什么,并且它满足我们的要求。这类操作总是慢于直接执行相同的操作。
### 反射相关的主要API
- java.lang.Class:
- java.lang.reflect.Method:
- java.lang.reflect.Field:
- java.lang.reflect.Construtor:
Class类:
在Object类中,定义了一下的方法,此方法被所有子类继承:
```java
public final Class getClass()
```
- 以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓从程序的运行结果来看,也很好理解。即:通过对象反射求出类的名称。
```java
package com.dong.reflection;
public class Test02 {
public static void main(String[] args) throws ClassNotFoundException {
Class c1 = Class.forName("com.dong.reflection.User");
Class c2 = Class.forName("com.dong.reflection.User");
Class c3 = Class.forName("com.dong.reflection.User");
System.out.println(c1.hashCode());
System.out.println(c2.hashCode());
System.out.println(c3.hashCode());
}
}
class User{
private String name;
private int Id;
private int age;
public User() {
}
public User(String name, int id, int age) {
this.name = name;
Id = id;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return Id;
}
public void setId(int id) {
Id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name=‘" + name + ‘‘‘ +
", Id=" + Id +
", age=" + age +
‘}‘;
}
}
```
### Class类
对象照镜子后,可以得到的信息,某个类的属性、方法和构造器,某个类到底实现了哪些接口。对于每个类而言,JRE都为其保留了一个不练的Class类型的对象。一个Class对象包含了特定某个结构(class/interface/enum/annitation/primitive type/viod/[])的有关信息。
- Class 本身也是一个类
- Class对象只能由系统建立对象
- 一个加载的类在JVM中只会有一个Class实例
- 一个Class对象对应的是一个加载到JVM中的一个.class文件
- 每个类的实例都会记得自己是由那个Class实例所生成
- 通过Cla
ss可以完成地得到一个类中多有被加载的结构
- Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得相应的Class对象。
### Class类的常用方法:
a) 若为已经具体的类,通过类的class属性获取,该方法最为可靠,程序的性能最高。
```java
Class clazz = Person.class;
```
b) 已知某个类的实例,调用该实例的getClass()方法,获取该Class对象
```java
Class clazz = person.getClass();
```
c) 已经类的全名和路径,通过Class类的静态方法forName()获取,可能排除异常。
```java
Class clazz = Class.forName();
```
d) 内置的基本数据类型可以直接用类名的Type获取
```java
Class clazz = Integer.TYPE;
```
e) 还可以用ClassLoad
```java
```
```java
package com.dong.reflection;
public class Test03 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
System.out.println(person.name);
//方法1:用实例化对象获取Class类的名字
Class c1 = person.getClass();
System.out.println(c1.hashCode());
//方法2:用路径来获得
Class c2 = Class.forName("com.dong.reflection.Student");
System.out.println(c2.hashCode());
//方法3:用类本身获取类的名字
Class c3 = Student.class;
System.out.println(c3.hashCode());
//方法4:基本内置类型的包装类都有一个Type属性
Class c4 = Integer.TYPE;
System.out.println(c4);
//方法5:用父类的Class类
Class c5 = c2.getSuperclass();
System.out.println(c5);
}
}
class Person{
public String name;
public int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
class Student extends Person{
public Student() {
this.name = "学生";
}
}
class Teacher extends Person{
public Teacher() {
this.name = "老师";
}
}
```
### 那些类型可以有Class对象
- class:外部类,成员(成员内部类,静态内部类)
- interface:接口
- []:数组
- enum:枚举
- annotation:注解@interface
- primitive type:基本数据类型
- void
```java
package com.dong.reflection;
import java.lang.annotation.ElementType;
public class Test04 {
public static void main(String[] args) {
Class c1 = Object.class;
Class c2 = Comparable.class;
Class c3 = String[].class;
Class c4 = int[][].class;
Class c5 = Override.class;
Class c6 = ElementType.class;
Class c7 = Integer.class;
Class c8 = void.class;
Class c9 = Class.class;
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println(c5);
System.out.println(c6);
System.out.println(c7);
System.out.println(c8);
System.out.println(c9);
System.out.println("========");
//只要元素类型和维度一样,就是同一个class
int[] a = new int[10];
int[] b = new int[100];
System.out.println(a.getClass().hashCode());
System.out.println(b.getClass().hashCode());
}
}
```
### Java内存分析
堆:存放new的对象和数组,可以被所有线程共享,不会存放背的对象引用
栈:存放基本变量类型(会包含这个基本类型的具体数值)存放引用对象的变量(会存放这个引用在堆里面的具体地址)
方法区(原空间):可以被所有的线程共享,包含了所有的class和static变量
### 类的加载过程
类的加载(Load)----->类的链接(Link)---->类的初始化(Initialize)
- 加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象。
- 链接:将java类的二进制代码合并到JVM的运行状态之中的过程。
- 验证:确保加载的类信息符合JVM规范,没有安全方面的问题
- 准备:正式为类变量(static)分配内存并设置类变量模式初始值的阶段,这些内存都将在方法区中进行分配。
- 解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程。
- 初始化:
- 执行类构造器()方法的过程。类构造器()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造该类对象的构造器)
- 当初始化一个类的时候,如果发现其父类还没有初始化,则需要先触发父类的初始化。、
- 虚拟机会保证一个类的()方法在多线程环境中被正确加 锁和同步。
```java
package com.dong.reflection;
public class Test05 {
public static void main(String[] args) {
A a = new A();
System.out.println(a.m);
}
/*
1. 加载到内存,会产生一个类对象Class对象
2. 链接,链接结束后 m=0
3. 初始化
(){
System.out.println("A类静态代码块初始化");
m = 150;
m = 100
}
*/
}
class A{
static {
System.out.println("A类静态代码块初始化");
m = 150;
}
static int m = 100;
public A() {
System.out.println("A的无参构造器");
}
}
```
### 分析类的初始化:
- 类的主动引用(一定会发生类的初始化)
- 当虚拟机启动,先初始化main方法所在的类。
- new 一个类的对象
- 调用类的静态成员(除了final常量)和静态方法
- 使用java.lang.reflect包的方法对类进行反射调用
- 当初始化一个类,如果父类没有被初始化,则先会初始化它的父类。
- 类的被动引用(不会发生类的初始化)
- 当访问一个静态域时,只有真正声明这个域的类才会被初始化。(如:当通过子类引用父类的静态变量,不会导致子类的初始化)
- 通过数组定义类的引用,不会触发此类的初始化
- 引用常量不会触发此类的初始化。(常量在链接阶段就存入调用类的常量池中了)
```java
package com.dong.reflection;
//测试类在什么时候会初始化:
public class Test06 {
static {
System.out.println("main类被初始化");
}
public static void main(String[] args) throws ClassNotFoundException {
//1. 主动引用
// Son son = new Son();
//2. 反射也会产生主动引用
// Class c1 = Class.forName("com.dong.reflection.Father");
//3.
// System.out.println(Son.b);
//4. 数组不会导致初始化
// Son[] a = new Son[4];
//5. 常量,
System.out.println(Son.M);
}
}
class Father{
static int b = 2;
static {
System.out.println("父类被加载");
}
}
class Son extends Father{
static {
System.out.println("子类被初始化");
m = 250;
}
static int m = 100;
static final int M = 1;
}
```
### 类加载器的作用:
- 类加载器的作用:将class文件字节码内容加载到内存中,并将这些静态数据转变成方法区的运行时的数据结构,然后在堆中生成一个代表这个类的Java.lang.Class对象。作为方法区中类数据访问的入口。
- 类缓存:标准的javaSE类加载器,可以按照要求查找类,但一旦某个类被加载到类加载器中,他将维持加载(缓存)一段时间,不过JVM垃圾回收机制可以回收这些Class对象。
- JVM规范定义了如下类型的类的加载器。
- 引导类加载器:用C++编写的,时JVM自带的类加载器,负责java平台核心库,用来装载核心类库。该加载器无法直接获取。
- 扩展类加载器:负责jre/lib/ext目录下的jar包或- D java.ext.dirs指定目录下的jar包装入工作库。
- 系统类加载器:负责java-classpath或者- D java.class.path所只的目录下的类,与jar包装入工作,是最常用的加载器。
```java
package com.dong.reflection;
public class Test07 {
public static void main(String[] args) throws ClassNotFoundException {
//获取系统类的加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
//获得系统类加载器的父类加载器 --> 扩展类加载器
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent);
//获得扩展类加载器的父类加载器 ---> 根加载器(C++编写),java 获取不到
ClassLoader parent1 = parent.getParent();
System.out.println(parent1);
//测试当前类是那个加载器加载的
ClassLoader classLoader = Class.forName("com.dong.reflection.Test07").getClassLoader();
System.out.println(classLoader);
//测试JDK内部类是那个类加载器加载的
ClassLoader classLoader2 = Class.forName("java.lang.Object").getClassLoader();
System.out.println(classLoader2);
//获取类加载器可以加载的路径
System.out.println(System.getProperty("java.class.path"));
//双亲委派机制
}
}
```
### 获取运行时类的完整结构:
通过反射获取运行时类的完整结构:
Field、Method、Constructor、Superclass、Interface、Annotation
```java
package com.dong.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test08 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c = Class.forName("com.dong.reflection.User");
//获得类的名字
System.out.println(c.getName());
System.out.println(c.getSimpleName());
//获得类的属性
System.out.println("===============================");
Field[] field = c.getFields();//只能找到public属性
Field[] fields = c.getDeclaredFields();//能到到全部的属性
for (Field x : fields) {
System.out.println(x);
}
//获得指定属性的值
Field age = c.getDeclaredField("age");
System.out.println(age);
System.out.println("===================");
//获得方法
Method[] methods = c.getMethods();//获得本类和父类的所有public方法
for (Method method : methods) {
System.out.println(method);
}
System.out.println("==========================");
Method[] declaredMethods = c.getDeclaredMethods();//获得本类的所有方法
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
System.out.println("------------------------------");
//获得具体的方法
Method getName = c.getDeclaredMethod("getName");
System.out.println(getName);
Method setName = c.getDeclaredMethod("setName", String.class);
System.out.println(setName);
//获得构造器
System.out.println("*************************");
Constructor[] constructors = c.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
Constructor[] declaredConstructors = c.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
//获得指定的构造器
Constructor name = c.getDeclaredConstructor(String.class,int.class,int.class);
System.out.println(name);
}
}
```
### 小结:
- 在实际操作中,取得类的信息的操作代码,并不会经常开发
- 一定要熟悉java.lang.reflect包的作用,反射机制
- 如何获得属性、方法、构造器的名称,修饰符等
## Class对象的作用
- 创建类的对象,调用Class对象的newInstance()方法
- 1. 类必须要有一个无参构造器
2. 列的构造器的访问权限要足够
- 当类没有无参构造时,可以用有参构造器进行,创建类的对象
- 1. 通过Class类的getDeclaredConstructor(Class...parameterTypes)取得本类的指定形参类型的构造器
2. 向构造器的形参中传递一个对象数组进去,里面包含了构造器中所需的各个参数。
3. 通过Constructor实例化对象
```java
package com.dong.lesson01;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test01 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获取Class对象
Class c1 = Class.forName("com.dong.lesson01.User");
//通过Class对象来创建一个对象
// User user = (User)c1.newInstance();//本质是调用类的无参构造器
// System.out.println(user);
//通过Class获取构造器,来创建一个对象
// Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
// User user2 = (User) constructor.newInstance("小尼姑",001,10);
// System.out.println(user2);
//通过反射调用(操作)方法
User user3 = (User)c1.newInstance();
Method setName = c1.getDeclaredMethod("setName", String.class);
//invoke 激活
//Method.invoke(对象,"方法的值")
setName.invoke(user3,"小尼姑");
System.out.println(user3);
//通过反射调用属性
User user4 = (User)c1.newInstance();
Field name = c1.getDeclaredField("name");
//不能直接操作private属性,但是我们需要关闭安全检测,
// 即设置方法或者属性为可访问的;setAccessible(true)
name.setAccessible(true);
name.set(user4,"花蝴蝶");
System.out.println(user4.getName());
}
}
//===========================================
class User{
private String name ;
private int ID;
private int age;
public User() {
}
public User(String name, int ID, int age) {
this.name = name;
this.ID = ID;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getID() {
return ID;
}
public void setID(int ID) {
this.ID = ID;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name=‘" + name + ‘‘‘ +
", ID=" + ID +
", age=" + age +
‘}‘;
}
}
```
### 测试性能
```java
package com.dong.reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//测试代码运行时间
public class Test09 {
//直接调用
public void test1(){
User user = new User();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
user.getName();
}
long endTime = System.currentTimeMillis();
System.out.println("直接调用程序运行的时间:"+(endTime-startTime)+"ms");
}
//用反射调用程序
public void test2() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User user = new User();
Class c1 = user.getClass();
Method getName = c1.getDeclaredMethod("getName");
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(user,null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射调用程序运行的时间:"+(endTime-startTime)+"ms");
}
//用关闭检测后调用程序
public void test3() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User user = new User();
Class c1 = user.getClass();
Method getName = c1.getDeclaredMethod("getName");
getName.setAccessible(true);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(user,null);
}
long endTime = System.currentTimeMillis();
System.out.println("允许访问,调用程序运行的时间:"+(endTime-startTime)+"ms");
}
public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
new Test09().test1();
new Test09().test2();
new Test09().test3();
}
}
```
### 获取泛型信息
```java
package com.dong.reflection;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
//通过反射获取泛型的信息
public class Test10 {
//方法的参数为泛型
public void test1(Map<String,User> map, List list){
System.out.println("test1");
}
//
public Map<String,User> test2(){
System.out.println("test2");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method test1 = Test10.class.getDeclaredMethod("test1", Map.class, List.class);
Type[] genericParameterTypes = test1.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println("* "+genericParameterType+" *");
if (genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
Method test2 = Test10.class.getDeclaredMethod("test2",null);
Type genericReturnType = test2.getGenericReturnType();
if (genericReturnType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("####"+actualTypeArgument);
}
}
}
}
```
### 反射操作注解
- getAnnotations
- getAnnotation
```java
package com.dong.reflection;
import java.lang.annotation.*;
import java.lang.reflect.Field;
public class Test11 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.dong.reflection.Students");
//通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//获得注解的value的值
TableDong annotation = (TableDong)c1.getAnnotation(TableDong.class);
String value = annotation.value();
System.out.println(value);
//获得类的指定注解(此处获得 类的属性 --> 指定注解)
Field name = c1.getDeclaredField("age");
FieldDong fieldDong = name.getAnnotation(FieldDong.class);
System.out.println(fieldDong.columnName());
System.out.println(fieldDong.type());
System.out.println(fieldDong.length());
}
}
@TableDong("db_student")
class Students{
@FieldDong(columnName = "db_id", type = "int",length = 10)
private int id;
@FieldDong(columnName = "db_age", type = "int",length = 10)
private int age;
@FieldDong(columnName = "db_name", type = "varchar",length = 3)
private String name;
public Students() {
}
public Students(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Students{" +
"id=" + id +
", age=" + age +
", name=‘" + name + ‘‘‘ +
‘}‘;
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableDong{
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldDong{
String columnName();
String type();
int length();
}
```

注解和反射

上一篇:OSD启动流程分析


下一篇:Julia实现基于双序列比对(Pairwise sequence Alignment)计算蛋白序列间一致性(identity)