上一章小结
在实际的操作中,取得类的信息的操作代码,并不会经常开发。一定要熟悉java.lang.reflect包的作用,反射机制。
如何取得属性、方法、构造器的名称,修饰符等。
有了Class对象,能做什么?
创建类的对象:调用Class对象的newlnstance()方法
1)类必须有一个无参数的构造器。
2)类的构造器的访问权限需要足够
思考?难道没有无参的构造器就不能创建对象了吗?只要在操作的时候明确的调用类中的构造器,并将参数传递进去之后,才可以实例化操作。
步骤如下:
1)通过Class类的getDeclaredConstructor(Class ... parameterTypes)取得本类的指定形参类型的构造器
2)向构造器的形参中传递一个对象数组进去,里面包含了构造器中所需的各个参数。3)通过Constructor实例化对象
调用指定的方法
通过反射,调用类中的方法,通过Method类完成。
通过Class类的getMethod(String name,Class...parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型。
之后使用Object invoke(Object obj, Object[] args)进行调用,并向方法中传递要设置的obj对象的参数信息。
1.实例化Class Class.forName()--->Person
2.找到sayHello() getMethod("sayHello");--->+ sayHello() void
3.invoke() 调用方法----》+ sayHello() void
Object invoke(Object obj, Object ... args)
Object 对应原方法的返回值,若原方法无返回值,此时返回null若原方法若为静态方法,此时形参Object obj可为null
若原方法形参列表为空,则Object[] args为null
若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的setAccessible(true)方法,将可访问private的方法。
setAccessible:安全检查开头,关闭后可以访问私有属性
Method和Field、Constructor对象都有setAccessible()方法。setAccessible作用是启动和禁用访问安全检查的开关。
参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。
提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true。使得原本无法访问的私有成员也可以访问
≥参数值为false则指示反射的对象应该实施Java语言访问检查
package 反射;//动态创建对象,通过反射
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Text2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchFieldException {
//获得class对象
Class c1=Class.forName("反射.User1");
//构造一个对象
try {
//输出的值都为空,因为本质上我们调用的是无参构造器,所以我们创建类的对象必须要有一个无参构造器
User1 user =(User1)c1.newInstance();//他给的是Object类型,但是我们知道他是什么类型的,所以这里强转成了User
System.out.println(user);
} catch(Exception e) {
System.out.println("InstantiationException");
} finally {
}
//通过构造器创建对象,没有空参构造器也可以用,因为我们是指定了构造器
Constructor constructor= c1.getDeclaredConstructor(String.class,int.class,int.class);
//操作对象
User1 user1 =(User1)constructor.newInstance("开心",001,24);
System.out.println(user1);
//通过反射调用普通方法
User1 user3 =(User1)c1.newInstance(); //对象
//通过反射获取一个方法
Method setName= c1.getDeclaredMethod("setName",String.class);//对象
//invoke:激活的意思
//参数列表:(对象,"方法的值"):方法是那个对象的,那我们就只需要传那个对象即可
//操作方法
setName.invoke(user3,"小怪");//给user3对象的,setName方法传递一个String的值
System.out.println(user3.getName());
//通过反射操作属性
User1 user4 =(User1)c1.newInstance(); //对象
Field name=c1.getDeclaredField("name");
//操作name
//不能直接操作私有属性,我们需要关闭程序的安全检测,通过方法/属性,把setAccessible(true),设置为true即为关闭
name.setAccessible(true);//关闭权限检查,这样我们就可以设置私有的属性了和方法了,无关闭这个检查检查的话,我们就没有权限去修改私有的方法和属性了
name.set(user4,"小开心");//给user4对象设置值
System.out.println(user4.getName());
}
}
//实体类:pojo,entity:来表示实体类
class User1{
private String name;
private int id;
private int age;
public User1(){
}
public User1(String name,int id,int age){
this.name=name;
this.id=id;
this.age=age;
}
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
//------------------
public void setId(int id){
this.id=id;
}
public int getId(){
return id;
}
//--------------
public void setAge(int age){
this.age=age;
}
public int getAge(){
return age;
}
//输出方法
public String toString(){
return "User{"+"name="+name+"id="+id+"age="+age+"}";
}
}