JAVA基础——java动态性之反射

来源:互联网 发布:mac文献管理软件 编辑:程序博客网 时间:2024/05/13 12:11

一、简介:

    java不算是动态语言,但是却含有一些动态性机制功能。体现java动态性的有:反射机制、动态编译、动态执行javascript代码和动态字节码操作等。在这里介绍一下java动态性中的反射机制。反射机制是在java程序运行状态中,可以动态的记载类,对于已经加载的类,可以知道这个类的所有属性和方法,也可以操作其对象的相关属性和方法。加载类之后会在堆内存中生成该类的一个Class类型的对象,该对象中包含该类的结构信息,结构信息和类的相关信息形成一种映射关系,这就体现了类本身和Class对象的反射关系。

二、操作:

    1、Class类型对象的获取:

    获取Class类型对象有三种方法,如下语句:

<pre class="java" name="code">Class clazz = Class.forName(path);
Class strClazz = String.class;Class strClazz2 = path.getClass(); 

    其中常用的还是Class.forName(对象名)这个方法。

    2、利用反射API获取和操作类的相关信息。

    其核心代码如下:

Class<User> clazz = (Class<User>) Class.forName(path);//通过反射API调用构造方法,构造对象//1、调用User无参构造方法生成新对象User u = clazz.newInstance();//2、调用User指定参数的构造方法生成新对象。Constructor<User> c = clazz.getDeclaredConstructor(int.class,int.class,String.class);User u2 = c.newInstance(1001,18,"高淇二");//通过反射API调用普通方法User u3 = clazz.newInstance();Method method = clazz.getDeclaredMethod("setUname", String.class);method.invoke(u3, "高淇三");   //相当于u3.setUname("高淇三");//通过反射API操作属性User u4 = clazz.newInstance();Field f = clazz.getDeclaredField("uname");f.setAccessible(true); //指定属性不需要做安全检查了,可以直接访问f.set(u4, "高淇四");//通过反射直接写属性

    下边说明有关setAccessible方法,一般情况下反射只可以访问类中的非静态成员,如果要访问类中的静态成员,需要通过setAccessible方法设置该属性可以直接访问不需要做安全检查;反射的一大缺点就是需要速度慢,主要就是在于每次访问都需要做安全检查,因此如果需要避免反射速度慢的缺点,必要时候也会牺牲安全因素,提高运行速度,这时就需要通过setAccessible方法进行设置。

    3、通过反射获取泛型:

    核心代码如下:

//获得指定方法参数泛型信息Method m = Demo04.class.getMethod("test01", Map.class,List.class);Type[] t = m.getGenericParameterTypes();for (Type paramType : t) {System.out.println("#"+paramType);if(paramType instanceof ParameterizedType){Type[] genericTypes = ((ParameterizedType) paramType).getActualTypeArguments();for (Type genericType : genericTypes) {System.out.println("泛型类型:"+genericType);}}}//获得指定方法返回值泛型信息Method m2 = Demo04.class.getMethod("test02", null);Type returnType = m2.getGenericReturnType();if(returnType instanceof ParameterizedType){Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments();for (Type genericType : genericTypes) {System.out.println("返回值,泛型类型:"+genericType);}}

    4、反射操作注解:

    有关操作注解:这里定义了两个自定义的注解和一个操作类,SxtTable、SxtField以及Demo类,用于模拟代码信息生成数据库对应表信息的过程,其相关代码如下:

    自定义注解SxtTable:

@Target(value={ElementType.TYPE}) //修饰范围为类或接口等。@Retention(RetentionPolicy.RUNTIME) //定义注解的生命周期。public @interface SxtTable {String value();}

    自定义注解SxtField:

@Target(value={ElementType.FIELD}) //修饰范围为类型成员。@Retention(RetentionPolicy.RUNTIME) //定义注解的生命周期。public @interface SxtField {String columnName();String type();int length();}

    操作类:

@SxtTable("tb_student")public class SxtStudent {@SxtField(columnName="id",type="int",length=10)private int id;@SxtField(columnName="sname",type="varchar",length=10)private String studentName;@SxtField(columnName="age",type="int",length=3)private int age;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getStudentName() {return studentName;}public void setStudentName(String studentName) {this.studentName = studentName;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}


三、总结:

    通过反射初步认识了有关java动态性的一些操作,但是有关反射的运用远远不止这些,反射是java中非常有力的一个功能,当然反射也有自己的一些缺陷,在运用中需要权衡好其利弊,尽量做到将其利益最大化。


0 0