反射

什么是反射

  简单说,反射机制值得是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,那么就可
以通过反射机制来获得类的所有信息。
  JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个
对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为
java语言的反射机制。

静态编译和动态编译

  • 静态编译:在编译时确定类型,绑定对象
  • 动态编译:运行时确定类型,绑定对象

反射机制优缺点

  • 优点: 运行期类型的判断,动态加载类,提高代码灵活度。
  • 缺点: 性能瓶颈:反射相当于一系列解释操作,通知 JVM 要做的事情,性能比直接的java代码要慢很多。

反射机制的应用场景有哪些?

反射是框架设计的灵魂。
  在我们平时的项目开发过程中,基本上很少会直接使用到反射机制,但这不能说明反射机制没有用,实
际上有很多设计、开发都与反射机制有关,例如模块化的开发,通过反射去调用对应的字节码;动态代
理设计模式也采用了反射机制,还有我们日常使用的 Spring/Hibernate 等框架也大量使用到了反射机
制。
 
举例:
①我们在使用JDBC连接数据库时使用Class.forName()通过反射加载数据库的驱动程序;
②Spring框架也用到很多反射机制,最经典的就是xml的配置模式。
Spring 通过 XML 配置模式装载Bean 的过程:
1) 将程序内所有 XML 或 Properties 配置文件加载入内存中;
2)Java类里面解析xml或properties里面的内容,得到对应实体类的字节码字符串以及相关的属性信息;
3)使用反射机制,根据这个字符串获得某个类的Class实例;
4)动态配置实例的属性

 

Java获取反射的三种方法

1.通过new对象实现反射机制
2.通过路径实现反射机制
3.通过类名实现反射机制
public class Student {
private int id;
String name;
protected boolean sex;
public float score;
}
public class Get {
//获取反射机制三种方式
public static void main(String[] args) throws ClassNotFoundException {
//方式一(通过建立对象)
Student stu = new Student();
Class classobj1 = stu.getClass();
System.out.println(classobj1.getName());
//方式二(所在通过路径-相对路径)
Class classobj2 = Class.forName("fanshe.Student");
System.out.println(classobj2.getName());
//方式三(通过类名)
Class classobj3 = Student.class;
System.out.println(classobj3.getName());
}
}

哪里用到反射机制?

jdbc中有一行代码:Class.forName('com.MySQL.jdbc.Driver.class').newInstance();那个时候只知道生
成驱动对象实例,后来才知道,这就是反射,现在
很多框架都用到反射机制,hibernate,struts都是用反射机制实现的。
 

反射机制的优缺点?

静态编译:在编译时确定类型,绑定对象,即通过
动态编译:运行时确定类型,绑定对象。动态编译最大限度的发挥了java的灵活性,体现了多态的应用,有利于降低类之间的耦合性。
 
  一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中
它的灵活性就表现的十分明显。比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个
程序编译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版
本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实
现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实
现该功能。
  它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它
满足我们的要求。这类操作总是慢于只直接执行相同的操作。
 

反射的功能:

在运行时构造一个类的对象。
判断一个类所具有的成员变量和方法。
调用一个对象的方法。
生成动态代理。
反射的应用很多,很多框架都有用到:
反射的用途:
Spring 框架的 IoC 基于反射创建对象和设置依赖属性。
Spring MVC 的请求调用对应方法,也是通过反射。
JDBC 的 Class#forName(String className) 方法,也是使用反射。
 
 

1.反射机制介绍_Class 对象获取

1.1 反射机制是 Java 的动态性之一

动态语言:在程序运行时,可以改变程序的结构或变量的类型。

举例:JavaScript

 

 Java 代码

典型的动态语言”Python、ruby、JavaScrip

  •        C,C++,Java 不是动态语言,但具有一定的动态性,可以称为”准动态语言”,具备类似动态语言的特性。传一块代码来动态的执行,动态的处理,Java 也能做,可以利用反射来实现类似的功能。Java的动态性让编程变得更加的灵活,功能就更加的强大。

 

1.2 反射机制


程序在运行的过程中加载一些“只知道相关名字”的类,以下代码,在程序运行时加载 User 类。

一个类被加载后,JVM 会创建一个对应类的 Class 对象,
类的整个结构信息会被放到 Class 对象中。
这个 Class 对象就像镜子一样,通过这面镜子,可以得到
对应类的全部信息

1.3 反射机制的常见作用

  • 1) 动态的加载类、动态的获取类的信息(属性,方法,构造
  • 器)
  • 2) 动态构造对象
  • 3) 动态调用类和对象的任意方法、构造器
  • 4) 动态调用和处理属性
  • 5) 获取泛型信息
  • 6) 处理注解

1.4 获取 Class 对象的方式

  • 1) 通过字节码文件
  • 2) 对象的 getClass()方法
  • 3) Class 类的静态方法 forName(….)
package com.bjsxt.entity;

public class User {
    //类的属性
    private int userId;
    private String userName;
    private String password;
    //公有的取值,赋值方法
    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    //构造方法
    public User() {
        // TODO Auto-generated constructor stub
    }
    public User(int userId, String userName, String password) {
        super();
        this.userId = userId;
        this.userName = userName;
        this.password = password;
    }
    
    
}
View Code
package com.bjsxt.test;

import com.bjsxt.entity.User;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        System.out.println(int.class);
        System.out.println(void.class);
        int []arrA=new int[10];
        int[] arrB=new int[30];
        /**维数相同和类型相同的数组共享同一个Class对象*/
        System.out.println(arrA.getClass()==arrB.getClass());
        
        /**同一个类的N多对象,共享同一个Class对象*/
        User u1=new User();
        User u2=new User();
        System.out.println(u1.getClass()==u2.getClass());
        
        
        /**获取Class对象的三种方式*/
        //(1)通过对象的getClass()方法获取
        Class c1=u1.getClass();
        //(2)通过字节码文件获取
        Class c2=User.class;
        //(3)通过Class类的静态方法获取
        Class c3=Class.forName("com.bjsxt.entity.User");
        
        System.out.println((c1==c2)+"\t"+(c1==c3));
        
        
    }
}
View Code

 

2.反射机制动态操作_方法_属性_构造器

2.1 获取类的名字

 

2.2 获得类的属性

 

公共的指的是public类型的

 

 

2.3 获得类的方法

 

2.4 获得构造方法

    

JAVA 反射机制中,Field的getModifiers()方法返回int类型值表示该字段的修饰符。

其中,该修饰符是java.lang.reflect.Modifier的静态属性。

对应表如下:

PUBLIC: 1
PRIVATE: 2
PROTECTED: 4
STATIC: 8
FINAL: 16
SYNCHRONIZED: 32
VOLATILE: 64
TRANSIENT: 128
NATIVE: 256
INTERFACE: 512
ABSTRACT: 1024
STRICT: 2048

 

2.5 动态的操作属性、方法、构造方法

package reflect;

public class User {
    //类的属性
    private int userId;
    private String userName;
    private String password;
    //公有的取值,赋值方法
    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    //构造方法
    public User() {
        // TODO Auto-generated constructor stub
    }
    public User(int userId, String userName, String password) {
        super();
        this.userId = userId;
        this.userName = userName;
        this.password = password;
    }
    
    
}
View Code
package reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, NoSuchMethodException {
        String path="reflect.User";
        //(1)获取类的名称
        Class c=Class.forName(path);
        System.out.println("类的全名称:"+c.getName());
        System.out.println("类的名称:"+c.getSimpleName());
        //(2)获取父类的class对象
        Class cSuper=c.getSuperclass();
        System.out.println(cSuper.getName());
        System.out.println(cSuper.getSimpleName());
        //获取类的属性信息
        //Field f=c.getField("userId");//只能获取公共属性
        //System.out.println(f);
        Field[] fields=c.getFields();//只能获取公共属性
        System.out.println(fields.length);
        
        Field[] fields2=c.getDeclaredFields();
        //System.out.println(fields2.length);
         for (Field field : fields2) {
            //System.out.println(field);//调用了tostring方法
            System.out.println(field.getModifiers()+"\t"+field.getType()+"\t"+field.getName());
                    
            
            
        }
        //获取类的方法信息
         Method[] methods=c.getDeclaredMethods();//本类中的公共方法对象
         System.out.println(methods.length);
         for(Method method:methods){
             //System.out.println(method);
             System.out.println("访问权限:"+method.getModifiers());
             System.out.println("返回值类型:"+method.getReturnType());
             System.out.println("方法的名称:"+method.getName());
             //方法的参数
             Class<?>[] cPara = method.getParameterTypes();
             for (Class c1 : cPara) {
                System.out.println(c1.getTypeName()+"\t");
            }
             System.out.println("\n-----------");
             
         }
         
        //获取类的构造器
         Constructor[] cons = c.getConstructors();
         for(Constructor constructor:cons){
             System.out.println(constructor);
         }
         //获取指定的构造方法
         Constructor con = c.getConstructor(null);
         
         System.out.println(con);
         Constructor con2=c.getConstructor(int.class,String.class,String.class);
         System.out.println(con2);
         
         
    }
}
View Code
package reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test2 {
  public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
    //获取class类的对象
      Class c=Class.forName("reflect.User");
      //(1)得到无参构造方法的对象
      Constructor cons = c.getConstructor(null);
      //通过无参构造方法的对象,创建User类的对象
    User user =(User) cons.newInstance();
      
    
    //(2)动态操作属性
    Field field=c.getDeclaredField("userId");
    field.setAccessible(true);//这个属性不需要做安全检查了,可以直接访问
    field.set(user, 1001);
    System.out.println("取出userid这个属性的值"+field.get(user));//通过反射直接取值
    
    //(3)动态操作方法
    Method m = c.getDeclaredMethod("setUserName", String.class);
    //执行setUserName这个方法
      m.invoke(user, "张三");
      Method m2=c.getDeclaredMethod("getUserName", null);
      System.out.println(m2.invoke(user));
      
}
}
View Code

 

3.提高反射效率

  • 反射机制对程序的运行在性能上有一定的影响,速度慢

3.1 如何提高反射的性能

1) 通过 setAccessible 提高性能

  • a) setAccessible 启用和禁用访问安全检查的开关,值为true 则指示反射的对象在使用时应该取消 Java 语言访问检查,值为 false 则指示反射的对象不实施 Java 语言访问检查,并不是为 true 就能访问为 false 就不能访问
  • b) 禁止安全检查,可以提高反射的运行速度
package reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestAccessbile {

    public static void test01(){
        //User u=new User();
        Object obj=new Object();
        long startTime=System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            obj.hashCode();
        }
        long endTime=System.currentTimeMillis();
        System.out.println("调用普通方法,循环执行一亿次"+(endTime-startTime)+"ms");
    }
    public static void test02() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
        Object obj=new Object();
        Class c=obj.getClass();
        //获取指定的方法
        Method m=c.getDeclaredMethod("hashCode",null);
        long startTime=System.currentTimeMillis();
        for(int i=0;i<1000000000;i++){
            //执行这个方法
            m.invoke(obj, null);
            
        }
        long endTime=System.currentTimeMillis();
        System.out.println("调用反射,循环执行一亿次"+(endTime-startTime)+"ms");
    }
    public static void test03() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
        Object obj=new Object();
        Class c=obj.getClass();
        //获取指定的方法
        Method m=c.getDeclaredMethod("hashCode",null);
        m.setAccessible(true);//不执行安全检查
        long startTime=System.currentTimeMillis();
        for(int i=0;i<1000000000;i++){
            //执行这个方法
            m.invoke(obj, null);
            
        }
        long endTime=System.currentTimeMillis();
        System.out.println("调用反射,不启用安全检查循环执行一亿次"+(endTime-startTime)+"ms");
    }
    public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        test01();
        test02();
        test03();
    }

}
View Code

 

4.反射操作泛型

4.1 泛型

      Java 中的泛型仅仅是给编译器 javac 使用的,确保数据的安全性和免去强制类型转换的麻烦,但是一旦编译完成,所有与泛型有关的类型全部擦除。使用泛型直接读取泛型,是读取不到的,因为反射是操作加载以后的类的。

4.2Java 新增的数据类型

为了通过反射操作这些类型以迎合实际开发的需要

 

  • 1) ParameterizedType: 表 示 一 种 参 数 化 的 类 型 ,比 如Collection<String>,可以获取 String 信息
  • 2) GenericArrayType:泛型数组类型
  • 3) TypeVariable:各种类型变量的公共父接口
  • 4) WildcardType:代表一种通配符类型表达式,比如? extends Number,? super Integer(Wildcard 是一个单词,就是通配符)
    • package com.bjsxt.entity;
      
      public class User {
      
      }
      View Code
      package com.bjsxt.generice;
      
      import java.lang.reflect.InvocationTargetException;
      import java.lang.reflect.Method;
      import java.util.ArrayList;
      import java.util.List;
      
      public class Test {
          public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
              List<String> alist=new ArrayList<String>();
              Class c=alist.getClass();//得到Class对象
              Method m=c.getDeclaredMethod("add", Object.class);
              //执行添加方法
              m.invoke(alist, 123);
              //输出集合中元素的个数
              System.out.println(alist.size());
              
          }
      }
      View Code
      package com.bjsxt.generice;
      
      import java.lang.reflect.Method;
      import java.lang.reflect.ParameterizedType;
      import java.lang.reflect.Type;
      import java.util.List;
      import java.util.Map;
      
      import com.bjsxt.entity.User;
      
      public class TestGeneric {
          public void test01(Map<String,User> map,List<User> list,String s){
              System.out.println("TestGeneric.test01()");
          }
          public Map<Integer,User> test02(){
              System.out.println("TestGeneric.test02()");
              return null;
          }
          public String test03(){
              System.out.println("TestGeneric.test03()");
              return null;
          }
          public static void main(String[] args) throws NoSuchMethodException, SecurityException {
              //获取test01方法的泛型参数信息
              Class c=TestGeneric.class;
              Method test01=c.getMethod("test01", Map.class,List.class,String.class);
              
              //获取带泛型参数的类型
              Type [] tytes=test01.getGenericParameterTypes();
              System.out.println(tytes.length);
              for (Type type : tytes) {
                  //System.out.println("#"+type);
                  if (type instanceof ParameterizedType) {
                      Type[] genericType= ((ParameterizedType) type).getActualTypeArguments();
                      //遍历每一个泛型参数中泛型的类型  
                      for (Type genType : genericType) {
                          System.out.println("泛型类型:"+genType);
                      }
                      System.out.println("\n--------------------------");
                  }
              }
              
              System.out.println("\n----------------------------\n");
              //获取test02方法返回值的泛型信息
              Method m2=c.getMethod("test02", null);
              Type returnType=m2.getGenericReturnType();
              //判断是否带有泛型
              if(returnType instanceof ParameterizedType){
                  Type [] types=((ParameterizedType) returnType).getActualTypeArguments();
                  for (Type type : types) {
                      System.out.println("返回值的泛型类型:"+type);
                  }
              }
              
              System.out.println("\n------------------------------\n");
              Method m3=c.getMethod("test03", null);
              Type returnType3=m3.getGenericReturnType();
              //System.out.println(returnType3);
              System.out.println(returnType3 instanceof ParameterizedType);
          }
          
      }
      View Code

       

5.注解

5.1 注解的作用

 

  • 1) 不是程序本身,可以对程序作出解释。(这一点跟注释没什么区别)
  • 2) 可以被其他程序(比如:编译器等)读取。(注解信息处理流程,是注解和注释的重大区别,如果没有注解信息处理流程,则注解毫无意义)


5.2 注解的格式

  • 1) 注解是以”@注释名”在代码中存在,还可以添加一些参数值,例如@SuppressWarnings(value=”unchecked”)。


5.3 注解在哪里使用

  • 1) 可以附加在 package,class,method,field 等上面,相当于给它们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元素的访问。


5.4 内置的注解

  • 1) @Override :标识方法是重写的方法
  • 2) @Deprecated :标识的方法不建议使用
  • 3) @SuppressWarnings:用来抑制编译时的警告信息
  • @SuppressWarinings 需要提供参数才能正常使用,这些参数都是已经定义好的,我们只需要选择就可以了。

举例:

  • @SuppressWarnings("unchecked")
  • @SuppressWarnings(value={"unchecked","deprecation"}
  • package com.bjsxt.annotation;
    
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    
    public class TestAnnotation {
        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return super.toString();
        }
        
        @Deprecated
        public void show(){ 
            Date d=new Date();
            System.out.println(d.getYear());
        }
        @SuppressWarnings("all")
        public void method(){
            List list=new ArrayList();
        }
        @SuppressWarnings(value={"unchecked","path"})
        public static void main(String[] args) {
            new TestAnnotation().show();
        }
    }
    View Code

     

6.自定义注解

6.1 自定义注解的语法

使 用 @interface 定 义 自 定 义 注 解 时 , 自 动 继 承 了java.lang.annotation.Annotation 接口

  • 1) @interface 用来声明一个注解
  • 2) 其中的每一个方法实际上是声明了一个配置参数

  • a) 方法的名称就是参数的名称
  • b) 返回值类型就是参数类型(返回值类型只能是基本类型、Class、String、enum)
  • c) 可以通过 default 来声明参数的默认值
  • d) 如果只有一个成员,一般参数名为 value

注意事项:注解元素必须要有值。我们定义注解元素时,经
常使用空字符串,0 作为默认值。
也经常使用负数(比如-1)表示不存在的含义

 

6.2 元注解


元注解的作用就是负责注解其他注解。在 Java 中定义了 4
个标准的 meta-annotation 类型,它们被用来提供对其它
annotation 类型作说明
这些类型和它们所支持的类在 java.lang.annotation 包中可
以找到

 

  • 1) @Target
  • 2) @Retention
  • 3) @Documented
  • 4) @Inherited

6.3 @Target


作用:用于描述注解的使用范围(即被描述的注解可以用在什
么地方)

 

举例:
@Target(value=ElementType.TYPE)

6.4 @Retention


作用:表示需要在什么级别保存该注解信息,用于描述注解的
生命周期

package com.bjsxt.annotation;

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

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
        String stuName() default "";
        int age() default 0;
        String [] school () default {"清华大学","北京大学"};
}
View Code
package com.bjsxt.annotation;

//@MyAnnotation 该注解只能应用到方法上
//@MyAnnotation2(value="aaaa")
@MyAnnotation2("aaa")
public class Test {
    @MyAnnotation(stuName="张小三")
    public void show(){
        
    }
    @MyAnnotation(stuName="王一一",age=23,school={"北京交通大学","北京广播学院"})
    public void method(){
        
    }
}
View Code
package com.bjsxt.annotation;

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

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation2 {
    String value();
}
View Code

 

7.反射读取注解信息

7.1ORM (Object Relationship Mapping)

ORM:对象关系映射

  • 1) 类与表结构对应
  • 2) 属性和字段对应
  • 3) 对象和记录对应

使用注解完成类和表结构的映射关系


7.2 功能描述

将Java中的Student类使用第三方程序通过读取注解生成数据库中的表

7.3 实现步骤

  • 1) 编写 Student 类
  • 2) 编写注解
  • 3) 在类中使用注解
  • 4) 通过解析程序将注解读取出来 (通过框架解析)
  • 5) 拼接 SQL 语句,使用 JDBC 到数据库中执行创建表
  • package com.bjsxt.entity;
    
    import com.bjsxt.annotation.SxtField;
    import com.bjsxt.annotation.SxtTable;
    
    @SxtTable("tb_student")
    public class Student {
        //私有属性
        @SxtField(columnName="id",type="int",length=10)
        private int id;
        
        @SxtField(columnName="stuname",type="varchar",length=20)
        private String stuName;
        
        @SxtField(columnName="age",type="int",length=10)
        private int age;
        
        
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getStuName() {
            return stuName;
        }
        public void setStuName(String stuName) {
            this.stuName = stuName;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public Student(int id, String stuName, int age) {
            super();
            this.id = id;
            this.stuName = stuName;
            this.age = age;
        }
        public Student() {
            super();
        }
        
    }
    View Code
    package com.bjsxt.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface SxtField {//属性的注解
        String columnName(); //数据库中列的名称
        String type();  //数据库中列的类型
        int length();   //类型的长度
    }
    View Code
    package com.bjsxt.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.TYPE) //注解的使用范围
    @Retention(RetentionPolicy.RUNTIME) //在运行时起作用
    public @interface SxtTable {
        String value();
    }
    View Code
    package com.bjsxt.annotation.test;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Field;
    
    import com.bjsxt.annotation.SxtField;
    import com.bjsxt.annotation.SxtTable;
    
    public class Test {
        public static void main(String[] args) throws Exception {
            //(1)创建Student类的Class对象
            Class clazz=Class.forName("com.bjsxt.entity.Student");
            //(2)得到Student类的所有注解
            Annotation [] annotations=clazz.getDeclaredAnnotations();
            for (Annotation a : annotations) {
                System.out.println(a);
            }
            System.out.println("\n----------------------------");
            //(3)获取指定的注解
            SxtTable st=(SxtTable) clazz.getDeclaredAnnotation(SxtTable.class);
            System.out.println(st);
            System.out.println("\n----------------------------");
            
            //(4)获取属性的注解
        
            Field field=clazz.getDeclaredField("stuName");
            SxtField sf=field.getDeclaredAnnotation(SxtField.class);
            System.out.println(sf.columnName()+"--"+sf.type()+"--"+sf.length());
            
            /**拼接SQL语句  DDL ,使用JDBC在数据库中执行,创建出了一张表,tb_student,表中的列就为id,stuname,age*/
            
        }
    }
    View Code

     

posted @ 2019-02-15 11:39  wq9  阅读(199)  评论(0编辑  收藏  举报