JAVA基础——java动态性之反射,
JAVA基础——java动态性之反射,
一、简介:
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中非常有力的一个功能,当然反射也有自己的一些缺陷,在运用中需要权衡好其利弊,尽量做到将其利益最大化。
相关文章
- 暂无相关文章
用户点评