好处:
1、可以在运行过程中,操作这些对象
2、可以解耦,提高程序的可扩展性
要对反射有一个比较深刻的理解,首先要了解Java代码在计算机中经历的三个阶段
1、Class.forName(“包名.类名”):
将字节码文件加载进内存,返回Class对象(编译阶段)
2、类名.class:
通过类名的属性class获取 (类加载阶段)
3、对象.getClass():
getClass()方法在Object类中定义 (RunTime运行阶段)
public static void main(String[] args) throws Exception {
//1、Class.forName(“包名.类名”)
Class cls = Class.forName("com.csx.bean.Person");
System.out.println(cls); //class com.csx.bean.Person
//2、类名.class
Class cls2=Person.class;
System.out.println(cls2);//class com.csx.bean.Person
//3、对象名.getClass()
Person p=new Person();
Class cls3=p.getClass();
System.out.println(cls3);//class com.csx.bean.Person
//==比较三个对象,三种获得的Class是一样的
System.out.println(cls==cls2);//true
System.out.println(cls==cls3);//true
//不同的Class是不一样的
Class c= Student.class;
System.out.println(c==cls); //false
}
1、获取成员变量们
Field[] getFields() 获取public修饰的,所有成员变量
Field getField(String name) 获取获取public修饰的,指定的成员变量
Field[] getDeclaredFields() 获取所有的成员变量,忽略修饰符
Field getDeclaredField(String name)
setAccessible(true)方法 设置为true表示可以访问其中的私有变量,(变量,构造器,方法都可以设置此方法)
public static void main(String[] args) throws Exception {
//使用第一种方式,在编译阶段获取Class对象
Class cls = Class.forName("com.csx.bean.Person");
//获取成员变量们 只能获取public修饰的成员变量
Field[] fields = cls.getFields();
for (Field field : fields) {
System.out.println(field);
}
//获取指定的成员变量 只能获取public修饰的,指定的成员变量
Field field = cls.getField("a");
System.out.println(field);
System.out.println("--------------------------------------");
//获取成员变量,忽略修饰符
Field[] declaredFields = cls.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//获取指定的成员变量,忽略修饰符
Field d = cls.getDeclaredField("d");
System.out.println(d);
//利用反射为私有的成员变量赋值
d.setAccessible(true); //设置为true表示可以访问其中的私有变量
Person person = new Person();
d.set(person,"张三"); //设置值
Object value = d.get(person); //获取值
System.out.println(value);
String name = d.getName(); //获取成员变量名字
System.out.println(name);
}
2、获取构造方法们
Constructor>[] getConstructors() 获取public修饰的,所有构造方法
Constructor getConstructor(类>... parameterTypes) 获取public修饰的指定的构造方法
Constructor>[] getDeclaredConstructors() 获取所有构造方法,忽略修饰符
Constructor getDeclaredConstructor(类>... parameterTypes) 获取指定的构造方法,忽略修饰符
public static void main(String[] args) throws Exception {
//使用第二种方式,在类加载阶段获取Class对象
Class cls = Person.class;
//获取构造方法们
Constructor[] constructors = cls.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("----------------------------------");
//获取指定的构造方法
//获取指定的构造方法,需要传入构造方法对应位置数据类型的class
Constructor constructor = cls.getConstructor(String.class,int.class);
System.out.println(constructor);
System.out.println("----------------------------------");
//用获取的构造方法创建对象
Object person1 = constructor.newInstance("张三",23);
System.out.println(person1);
System.out.println("----------------------------------");
//如果获取的是默认的构造方法,简便方式
Object pserson2 = cls.newInstance();
System.out.println(pserson2);
String name = constructor.getName(); //获取构造方法的全限定类名
System.out.println(name);
}
3、获取成员方法们
Method[] getMethods() 获取所有public修饰的方法,包括Object类的
Method getMethod(String name, 类>... parameterTypes) 获取public修饰的指定的方法
Method [] getDeclaredMethods() 获取所有方法,忽略修饰符
Method getDeclaredMethod(String name, 类>... parameterTypes) 获取指定的方法,忽略修饰符
4、获取类名
String getName()
public static void main(String[] args) throws Exception {
//用第三种方式,在运行阶段获取Class类
Person person = new Person();
Class cls = person.getClass();
//2、获取指定名称的方法
Method sleep = cls.getMethod("sleep");
Person p=new Person();
sleep.invoke(p);
Method sleep2=cls.getMethod("sleep", String.class);
sleep2.invoke(p,"饭");
System.out.println("-----------");
//获取所有public修饰的方法
Method[] methods=cls.getMethods();
for(Method method:methods){
System.out.println(method);
//获取方法的名字,包括Object类的public修饰的方法
String name=method.getName();
System.out.println(name);
}
//获取类名
String className=cls.getName();
System.out.println(className);
}
获取成员方法的运行结果
今天看到的一个另外的用法,反射机制可以绕过泛型的检查
public class TestfansheArray {
public static void main(String[] args) throws Exception {
ArrayList<String> list = new ArrayList<String>();
list.add("张三");
list.add("李四");
Class cls = list.getClass();
Method m = cls.getMethod("add", Object.class);
m.invoke(list, 1);
for (Object s : list) {
System.out.println(s);
}
}
}