反射
Class.newInstance()方法用来创造实例
例如TargetObject targetObject = (TargetObject) tagetClass.newInstance();就创造出了TargetObject的实例
2. java
targetClass.getDeclaredMethods();如果未填入参数,则获取该类中的所有方法。
for (Method method : methods) {
System.out.println(method.getName());
}
可通过增强for循环依次输出类中的方法名
Method publicMethod = targetClass.getDeclaredMethod("publicMethod",
String.class);
java.lang.Class.getDeclaredMethod(String name,class......)方法返回一个Method对象,它反映此Class对象所表示的类或接口的指定已声明方法。
如果填入参数,则第一个参数为方法名字,第二个参数开始即为该方法的形参列表。
则判断getDeclaredMethod的形参个数为 所调用方法的形参个数+1
4.在3的条件下:publicMethod.invoke(targetObject, "JavaGuide");
targetObject为某个对象的实例,“、JavaGuide”即为传入publicMethod方法的参数,若该方法无参,则invoke()中只用填写实例对象
field.setAccessible(true);
field.set(targetObject, "JavaGuide");
/**
* 调用 private 方法
*/
Method privateMethod = targetClass.getDeclaredMethod("privateMethod");
//为了调用private方法我们取消安全检查
privateMethod.setAccessible(true);
privateMethod.invoke(targetObject);
详见javaguide反射部分。
下面是尚硅谷视频的反射的具体实现
大的要来了(一定要吃透下面的代码)
下面的代码都基于此Person类
public class Person {
private String name;
public int age;
public void show(){
System.out.println("你好,我是一个人");
}
private String showNation(String nation){
System.out.println("你好,我的国籍是"+ nation);
return nation;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
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;
}
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
private Person(String name) {
this.name = name;
}
}
反射前创建公共对象,调用属性,方法
//反射之前,对于Person类的操作
@Test
public void test(){
//1.创建Person类的对象
Person p1 = new Person("Tom",12);
//2.通过对象,调用其内部属性,方法
p1.age=10;
System.out.println(p1.toString());//Person{name='Tom', age=10}
p1.show();//你好,我是一个人
//由于封装性的限制:
// 在Person类外部,不可以通过Person类的对象调用其内部私有结构
//比如:name,showNation(),以及私有的构造器
}
反射后创建公共对象,调用属性,方法
@Test
public void test1() throws Exception{
Class<Person> clazz = Person.class;
//调用公共属性方法
//1.通过反射,创建Person类的对象
Constructor<Person> cons = clazz.getConstructor(String.class, int.class);
Object obj = cons.newInstance("Tom", 12);
Person p = (Person) obj;
System.out.println(p.toString());//Person{name='Tom', age=12}
//2.通过反射,调用对象指定的属性,方法
//通过反射对属性进行修改
Field age = clazz.getDeclaredField("age");
age.set(p,10);
System.out.println(p.toString());//Person{name='Tom', age=10}
//调用方法
Method show = clazz.getDeclaredMethod("show");
Object invoke = show.invoke(p);//你好,我是一个人
反射后创建私有对象,调用属性,方法
@Test
public void test1() throws Exception{
Class<Person> clazz = Person.class;
//调用公共属性方法
//1.通过反射,创建Person类的对象
Constructor<Person> cons = clazz.getConstructor(String.class, int.class);
Object obj = cons.newInstance("Tom", 12);
Person p = (Person) obj;
System.out.println(p.toString());//Person{name='Tom', age=12}
//2.通过反射,调用对象指定的属性,方法
//通过反射对属性进行修改
Field age = clazz.getDeclaredField("age");
age.set(p,10);
System.out.println(p.toString());//Person{name='Tom', age=10}
//调用方法
Method show = clazz.getDeclaredMethod("show");
Object invoke = show.invoke(p);//你好,我是一个人
System.out.println("**********");
//调用私有属性方法
//通过反射,可以调用Person类的私有结构,比如私有的构造器,方法,属性
Constructor<Person> cons1 = clazz.getDeclaredConstructor(String.class);
cons1.setAccessible(true);
Person p1 = cons1.newInstance("Jerry");
System.out.println(p1.toString());//Person{name='Jerry', age=0}
//调用私有属性
Field name = clazz.getDeclaredField("name");
name.setAccessible(true);
name.set(p1,"xiaokasidi");
System.out.println(p1.toString());//Person{name='xiaokasidi', age=0}
//调用私有方法
Method showNation = clazz.getDeclaredMethod("showNation",String.class);
showNation.setAccessible(true);
Object invoke1 = showNation.invoke(p1, "中国");//你好,我的国籍是中国
System.out.println(invoke1);//此时的返回值为形参列表
那么,在上述例子中我们想必会产生一些疑问
1.通过直接new的方式或反射的方式都可以调用公共结构,那么在实际需求时应该使用哪种?
建议:直接new的方式。
什么时候会使用反射呢?
回答:首先,反射具有动态性。那么如果在编译期时无法确定要new哪个对象,那么就可以使用反射的方式创建对象。即在登录,注册,找回密码等等无法确定用户要干什么的时候,这个时候使用反射获取前端发来的具体的类来创建对象。
2.反射的机制与面向对象的封装性是不是矛盾的?
答案:不矛盾。封装性更多是主观上不让你去调用,简单来说就是用反射调用了也没什么用。