反射对于开发是很有帮助的。自己找时间学了学,介绍反射的一些用法;
这里自己写了两个类,用于对后来的结果作实例。把字段贴出来方便看,get和set方法就不贴了。
public class Base {
private String sj;
public String date;
}
public class Student extends Base {
private String name;
public String id;
private String address;
protected String age;
public Student() {
super();
}
public Student(String name, String id, String address, String age) {
super();
this.name = name;
this.id = id;
this.address = address;
this.age = age;
}
}
类的加载
三种方法:
Student stu=new Student();
Class a=Class.forName("reflectt.Student");
System.out.println(a);//1
System.out.println(stu.getClass());//2
System.out.println(Student.class);//3
结果:
class reflectt.Student
class reflectt.Student
class reflectt.Student
new一个对象
记住我们反射的是一个类名,创建他的对象需要实例化。而且这个类必须有空构造器,否则会报错。这个类我写了两个构造器,看看下面的结果
Object ss=Student.class.newInstance();//得有空构造器
System.out.println(ss);
结果其实两个构造器都显示了,有一个是空构造器:
Student [name=null, id=null, address=null, age=null]
方法介绍
getName() 获取包名下下类名
getSimpleName() 获取不带包名的类名
getFields() 获取此类及其及其父类和接口所能访问的字段,也就是public修饰的
getDeclaredFields()获得该类所有类型修饰的字段
System.out.println("获取不带包名的类名 "+stu.getClass().getSimpleName());
System.out.println("获取包名下的类的名称"+stu.getClass().getName());
Field []c=stu.getClass().getDeclaredFields();
for(int i=0;i<c.length;i++){
System.out.print("本类字段名称"+c[i].getName()+",");
}
System.out.println();
Field []c1=stu.getClass().getFields();
for(int i=0;i<c1.length;i++){
System.out.print("可访问的公共字段"+c1[i].getName()+",");
}
输出结果:
获取不带包名的类名 Student
获取包名下的类的名称reflectt.Student
本类字段名称name,本类字段名称id,本类字段名称address,本类字段名称age,
可访问的公共字段id,可访问的公共字段date,
getMethods() 获的该类以及父类和接口所有的公共方法(无序)
getDeclaredMethods() 该类自己的方法,不包含继承的方法(无序)
getConstructors() 该类公共的(public)构造方法(无序)
getDeclaredConstructors 该类所有类型的构造方法 public,protected,默认的,private (无序)
getReturnType()获得方法的返回值类型
getParameterTypes() 获取方法的参数类型
Method method[]=stu.getClass().getMethods();
for(int i=0;i<method.length;i++){
System.out.print("方法名"+method[i].getName()+",");
System.out.println("方法返回值类型"+method[i].getReturnType().getName());
}
部分结果显示:
方法名toString,方法返回值类型java.lang.String
方法名getAddress,方法返回值类型java.lang.String
方法名getName,方法返回值类型java.lang.String
Constructor []con=stu.getClass().getConstructors();
for(int i=0;i<con.length;i++){
System.out.print("构造器"+con[i].getName()+"参数类型");
//构造器参数的类型
Class[] parameterTypes = con[i].getParameterTypes();
for (Class class1 : parameterTypes) {
System.out.print(class1.getSimpleName()+",");
}
System.out.println();
}
结果显示:
构造器reflectt.Student参数类型String,String,String,String,
构造器reflectt.Student参数类型
方法的操作
举一个例子:
Method met=stu.getClass().getMethod("setName", String.class);
//第一个是调用此方法的对象 第二个是 参数 和stu.setName("dcz")一样
met.invoke(stu, "dcz");
//参数没有就不写
Method mer=stu.getClass().getMethod("getName");
//参数没有就不写 也可以写成null
Object invoke = mer.invoke(stu);
System.out.println(invoke);
结果:
dcz
根据反射自己写了个添加条件查询的通用方法,有兴趣的可以研究研究。
//添加条件查询的通用方法
public static void print(Object obj) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
//获取此类的所有方法
Method method[]=obj.getClass().getDeclaredMethods();
StringBuilder sb=new StringBuilder();
for(int i=0;i<method.length;i++){
//System.out.println(method[i].getName());
//返回值不是void 都是get方法 而且方法名不等于toString
if(!method[i].getReturnType().getSimpleName().equals("void")&&!method[i].getName().equals("toString")){
//执行get方法 invoke是返回结果
Object invoke = method[i].invoke(obj);
System.out.println(invoke);
if(invoke!=null){
Stringstr=String.valueOf(method[i].getName()).substring(3).toLowerCase();
sb.append(" and "+str+"="+invoke);
}
}
}
}
}