反射是java的动态性之一
反射机制:
- 程序在运行的过程中加载一些“只知道相关名字”的类,以下代码,在程序运行时加载User类。一个类被加载后,JVM会创建一个对应类的Class对象,类的整个结构信息会被放到Class对象中。这个Class对象就像镜子一样,通过这面镜子,可以得到对应类的全部信息。
Class c=Class.forName("com.test.reflect.User");
反射机制的作用:
- 1)动态的加载类、动态的获取类的信息(属性,方法,构造器)
- 2)动态构造对象
- 3)动态调用类和对象的任意方法、构造器
- 4)动态调用和处理属性
- 5)获取泛型信息
- 6)处理注解
测试用反射获取类的信息:
首先呢我们创建一个User类
package cn.test.oo;
public class User {
private int id;
private String name;
private int age;
public User(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
public User() {
super();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
使用反射技术获取相关的信息:
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 , NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException{
// 获取Class对象
Class c = Class.forName("cn.test.oo.User");
// 得到Class对象的名字
System.out.println("类的全名称:" + c.getName() + "t" + "类的名称:" + c.getSimpleName());
// 获取类的属性,得到的是一个field的数组
Field[] fies = c.getDeclaredFields();
System.out.println("================");
// 遍历数组得到属性的名称和属性
for (Field fie : fies) {
System.out.println(fie.getName() + "t" + fie.getType());
}
System.out.println("================");
// 获取类的所有方法的名字
Method[] mets = c.getDeclaredMethods();
for (Method met : mets) {
System.out.println("方法的访问权限:" + met.getModifiers());
System.out.println("方法返回值类型:" + met.getReturnType());
System.out.println("方法名称:" + met.getName());
// 获取方法的参数的类型
Class[] pars = met.getParameterTypes();
for (Class par : pars) {
System.out.println(par.getTypeName());
}
System.out.println("===============");
}
// 获取构造器
Constructor[] cons = c.getDeclaredConstructors();
for (Constructor con : cons) {
System.out.println("构造方法:" + con);
}
//使用反射技术创建User对象,null相当于调用无参构造函数
Constructor cs = c.getConstructor(null);
//通过无参构造函数创建对象
User user = (User) cs.newInstance();
//动态给属性赋值
Field fie = c.getDeclaredField("name");
fie.setAccessible(true);//不用安全检查
fie.set(user, "lili");
System.out.println(fie.get(user));
//动态调用赋值方法给对象赋值
//调用赋值方法给对象赋值
Method met = c.getDeclaredMethod("setAge", int.class);
met.invoke(user, 18);
//调用取值的方法取出对象
Method mes = c.getDeclaredMethod("getAge",null);
System.out.println(mes.invoke(user));
}
}
反射操作泛型:
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import cn.test.oo.User;
public class Test {
public void test(Map<String, Integer> map, List<String> list, String str) {
}
public List<String> test1() {
return null;
}
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
// 获取参数信息,首先创建Class类获取泛型对象
Class c = Test.class;
// 获取方法
Method met = c.getDeclaredMethod("test", Map.class, List.class, String.class);
// 获取到方法参数的数组
Type[] types = met.getGenericParameterTypes();
for (Type type : types) {
// 因为我们只要有泛型的数组
if (type instanceof ParameterizedType) {
// 获取到真实的泛型数组
Type[] realType = ((ParameterizedType) type).getActualTypeArguments();
for (Type r : realType) {
System.out.println("泛型的类型" + r);
}
}
}
// 判断返回值的泛型
Method mets = c.getDeclaredMethod("test1", null);
// 返回值是一个Type类型
Type reType = mets.getGenericReturnType();
// 判断是否有真实的泛型
if (reType instanceof ParameterizedType) {
Type[] reaType = ((ParameterizedType) reType).getActualTypeArguments();
for (Type a : reaType) {
System.out.println("返回值的类型:" + a);
}
}
}
}
利用反射技术拼接一个SQL语句
目的呢是创建一个学生表,包含ID,名字和年龄的属性
首先呢创建一个类的注解
package cn.test.oo;
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 Stutable {
String value();
}
再创建一个属性注解
package cn.test.oo;
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 StuField {
String columnName();//行的名称
String type();//行的数据类型
int length();//类型的长度
}
创建学生类
package cn.test.oo;
/**
* 创建Student类
* @author yaoya
*
*/
@Stutable("tb_student")
public class Student {
@StuField(columnName="age",type="int",length=10)
private int age;
@StuField(columnName="name",type="varchar",length=20)
private String name;
@StuField(columnName="id",type="int",length=10)
private int id;
public Student(int age, String name, int id) {
super();
this.age = age;
this.name = name;
this.id = id;
}
public Student() {
super();
}
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;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
创建测试类
package cn.test.oo.test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import cn.test.oo.StuField;
import cn.test.oo.Stutable;
public class TestAnn {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException {
// 创建Class对象
Class c = Class.forName("cn.test.oo.Student");
//创建SQL语句的字符串
String result = "creat table ";
// 获取到注解的信息
Annotation[] annos = c.getDeclaredAnnotations();
for (Annotation anno : annos) {
System.out.println(anno);
}
// 获取到指定的注解
Stutable stb = (Stutable) c.getDeclaredAnnotation(Stutable.class);
//拼接表名
result += stb.value() + "(n";
// 拼接剩下的SQL语句
Field[] fies = c.getDeclaredFields();
for (int i = 0; i < fies.length; i++) {
StuField anns = fies[i].getDeclaredAnnotation(StuField.class);
if (i == fies.length - 1) {//判断是否是最后一个属性
result += "t" + anns.columnName() + " " + anns.type() + "(" + anns.length() + ")" + "n)";
} else {
result += "t" + anns.columnName() + " " + anns.type() + "(" + anns.length() + ")" + ",n";
}
}
System.out.println(result);
}
}