反射是动态语言的关键.
为什么需要反射呢?
一个已经开发完全的程序,如果需要对功能进行升级、更新,虽然可以通过修改源代码进行编写,从而升级java程序的功能.但实际开发的时候这并不是一个好的办法.
实际开发中,不会去修改原先的程序代码,而是创建一个新类,将升级的功能封装在新类的方法中,通过反射来解刨这个心累的class文件,然后去调用新类的成员和方法.
获取Class类对象
例子:
public class Person {//创建一个Person类 public String name; public int id; public Person()//无参构造方法 { } public Person(String name, int id) { super(); this.name = name; this.id = id; } public void display() { System.out.println("姓名为:"+name+"id为:"+id); } }
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Demo { public static void main(String args[]) throws Exception { //获取Class类的对象的三种方法 通过类名.class、对象名.getClass()、forName方法来获取类的对象 Class class1=Person.class;
Person p1=new Person("小张",1); Class class2=p1.getClass(); Class class3=Class.forName("反射练习.Person"); //每一个类都存在一个类对象,用于描述该类有什么方法、成员 System.out.println(class1); }
}
Class类对象创建常用类对象:
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Demo { public static void main(String args[]) throws Exception { //获取Class类的对象的三种方法 通过类名、对象名、forName方法来获取类的对象 Class class1=Person.class; Person p1=new Person("小张",1); Class class2=p1.getClass(); Class class3=Class.forName("反射练习.Person"); //每一个类都存在一个类对象,用于描述该类有什么方法、成员 System.out.println(class1); //用Class对象来创建新的对象 //第一步:首先先获取Constructor对象,这是该类的公共构造函数 Constructor con1=class1.getConstructor(); //获取该类的无参构造函数. Constructor con2=class2.getConstructor(String.class,int.class);//这是获取该类的有参构造函数在getConstructor方法括号中加上构造方法参数类型.class; //使用con1获取的无参构造函数来创建对象 使用Constructor类的newInstance方法. Person p2=(Person) con1.newInstance();//想获得无参构造函数的时候,如果想获取的无参构造函数是隐式的会发生错误,需要将无参构造函数添加进类 p2.id=20; p2.name="小张"; p2.display(); //newInstance方法返回的是Object对象,所以需要强制类型转换 //Constructor是用于存储构造方法的类型. //使用 con2获取的有参构造函数来创建对象 Person p3=(Person) con2.newInstance("小李",30); p3.display(); System.out.println(p2+""+p3);
}
}
获取和设置成员变量
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Demo { public static void main(String args[]) throws Exception { //获取Class类的对象的三种方法 通过类名、对象名、forName方法来获取类的对象 Class class1=Person.class; Person p1=new Person("小张",1); Class class2=p1.getClass(); Class class3=Class.forName("反射练习.Person"); //每一个类都存在一个类对象,用于描述该类有什么方法、成员 System.out.println(class1); //用Class对象来创建新的对象 //第一步:首先先获取Constructor对象,这是该类的公共构造函数 Constructor con1=class1.getConstructor(); //获取该类的无参构造函数. Constructor con2=class2.getConstructor(String.class,int.class);//这是获取该类的有参构造函数在getConstructor方法括号中加上构造方法参数类型.class; //使用con1获取的无参构造函数来创建对象 使用Constructor类的newInstance方法. Person p2=(Person) con1.newInstance();//想获得无参构造函数的时候,如果想获取的无参构造函数是隐式的会发生错误,需要将无参构造函数添加进类 p2.id=20; p2.name="小张"; p2.display(); //newInstance方法返回的是Object对象,所以需要强制类型转换 //Constructor是用于存储构造方法的类型. //使用 con2获取的有参构造函数来创建对象 Person p3=(Person) con2.newInstance("小李",30); p3.display(); System.out.println(p2+""+p3); //获取和设置成员变量 //Field用于存储成员变量信息 Class的getFields方法能够获取公有成员变量信息(如果想要获得私有字段的名称 得使用getDeclared-Fields()方法) Field[] filed1=class1.getFields(); for(Field filed:filed1)//加强型for循环,即for-each循环 for(数据类型 变量名:数组、集合名){ \执行语句 } { System.out.println(filed.getName()); //Field的getName方法获得字段的名称 } //那如何设置某个字段的值呢? Constructor con3=class1.getConstructor();//获取无参构造函数 Object obj=con3.newInstance();//新建一个Object类型的变量来指向con3所存储的构造函数所新建的对象 Field name=class1.getField("name");//获得name的Field类的对象 name.set(obj, "张三");//这个时候name获取 //值为想要设置的字段的Field类型的对象.set(想要设置成员属性所属的对象,属性值); Field id=class1.getField("id"); id.set(obj, 02); System.out.println(name.get(obj)+" "+id.get(obj)); } }
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Demo { public static void main(String args[]) throws Exception { //获取Class类的对象的三种方法 通过类名、对象名、forName方法来获取类的对象 Class class1=Person.class; Person p1=new Person("小张",1); Class class2=p1.getClass(); Class class3=Class.forName("反射练习.Person"); //每一个类都存在一个类对象,用于描述该类有什么方法、成员 System.out.println(class1); //用Class对象来创建新的对象 //第一步:首先先获取Constructor对象,这是该类的公共构造函数 Constructor con1=class1.getConstructor(); //获取该类的无参构造函数. Constructor con2=class2.getConstructor(String.class,int.class);//这是获取该类的有参构造函数在getConstructor方法括号中加上构造方法参数类型.class; //使用con1获取的无参构造函数来创建对象 使用Constructor类的newInstance方法. Person p2=(Person) con1.newInstance();//想获得无参构造函数的时候,如果想获取的无参构造函数是隐式的会发生错误,需要将无参构造函数添加进类 p2.id=20; p2.name="小张"; p2.display(); //newInstance方法返回的是Object对象,所以需要强制类型转换 //Constructor是用于存储构造方法的类型. //使用 con2获取的有参构造函数来创建对象 Person p3=(Person) con2.newInstance("小李",30); p3.display(); System.out.println(p2+""+p3); //获取和设置成员变量 //Field用于存储成员变量信息 Class的getFields方法能够获取公有成员变量信息(如果想要获得私有字段的名称 得使用getDeclared-Fields()方法) Field[] filed1=class1.getFields(); for(Field filed:filed1)//加强型for循环,即for-each循环 for(数据类型 变量名:数组、集合名){ \执行语句 } { System.out.println(filed.getName()); //Field的getName方法获得字段的名称 } //那如何设置某个字段的值呢? Constructor con3=class1.getConstructor();//获取无参构造函数 Object obj=con3.newInstance();//新建一个Object类型的变量来指向con3所存储的构造函数所新建的对象 Field name=class1.getField("name");//获得name的Field类的对象 name.set(obj, "张三");//这个时候name获取 //值为想要设置的字段的Field类型的对象.set(想要设置成员属性所属的对象,属性值); Field id=class1.getField("id"); id.set(obj, 02); System.out.println(name.get(obj)+" "+id.get(obj)); //Class类如何获取和调用方法? Method method1=class1.getMethod("display");//1、获取指定字符串的方法,//如果想获取的方法需要参数,方法名后面就跟上 参数类型.class 用逗号分隔 Object object1= con2.newInstance("小张",03);//2、使用con2存储的有参构造函数来创建一个Object对象 method1.invoke(object1);//执行无参的方法,如果该方法需要参数,直接按照顺序将参数用逗号分隔加上即可. } }
课后习题:
1、获取Class类的常用方法是什么?
有三种,1、通过类名.class来获得Class类对象
2、通过该类型的对象.getClass()方法来获取该类型的Class类对象
3、使用Class.forName("包名.类名")方法来获取字符串中描述的类Class类对象
2、如何获取Class类的构造方法?
使用getConstructor()方法,如果想获取无参构造函数,则不需要填写参数,如果想获取有参数的构造函数,括号中需要class.参数类型 多个参数类型之间使用逗号分隔.