反射

⚫ 如何通过反射创建对象?
答:
 方法 1:通过类对象调用 newInstance()方法,例如:
String.class.newInstance()
 方法 2:通过类对象的 getConstructor()或 getDeclaredConstructor()
方法获得构造器(Constructor)对象并调用其 newInstance()方法创建对象,
例如:String.class.getConstructor(String.class).newInstance(“Hello”);

⚫ 获取Class对象的三种方式
/*
获取一个类的Class对象的三种方式:
1. 通过对象调用getClass方法获取。
Class getClass():可以通过对象获取类的Class
2. 通过类的class属性获取。 每一个数据类型都有一个隐藏的属性叫做class, 可以获取对应的Class对象
类名.class
3. 通过Class的静态方法forName获取
static Class forName(String className): 参数要传递一个全类名(包含包的类名), 并获取该类的Class对象。

一个类只有一个Class类型的对象,无论怎么获取,获取的都是同一个Class

*/
public class Demo01GetClass {
public static void main(String[] args) throws ClassNotFoundException {
//1. 通过对象调用getClass方法获取。
Person p = new Person();
Class clazz = p.getClass();//获取到的Class对象里面保存的是Person类的信息,是用来描述Person类的。
System.out.println(clazz);

    //2. 通过类的class属性获取。
    Class clazz2 = Person.class;
    System.out.println(clazz2);

    //3. 通过Class的静态方法forName获取
    Class clazz3 = Class.forName("cn.itcast.demo02_reflect.Person");
    System.out.println(clazz3);

    System.out.println(clazz == clazz2);
}

}

⚫ Class中的常见方法
String getName(): 获取类的名字(含有包的类名)
String getSimpleName(): 获取简单的类名(不含包的类名)
T newInstance():直接创建该类的对象(使用的空参构造创建对象)
*/
public class Demo02ClassMethod {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
//获取Person类的Class对象
//该Class对象保存了Person类的信息。
Class clazz = Class.forName("cn.itcast.demo02_reflect.Person");
//String getName(): 获取类的名字(含有包的类名)
System.out.println(clazz.getName()); //cn.itcast.demo02_reflect.Person
//String getSimpleName(): 获取简单的类名(不含包的类名)
System.out.println(clazz.getSimpleName());//Person
System.out.println("=====================================================");

    //(重要)T newInstance():直接创建该类的对象(使用的空参构造创建对象)
    Object obj = clazz.newInstance(); //因为clazz是Person的Class对象,所以使用newInstance方法创建的是Person对象。
    //System.out.println(obj);
    Person p = (Person) obj;
    System.out.println(p.getName() + "-" + p.getAge());
}

}

⚫ 反射获取空参构造方法并使用
在Class中,有一个方法叫做getConstructor,可以获取一个类中的构造方法
Constructor[] getConstructors(): 获取类的中的所有的构造方法。
Constructor getConstructor(Class... parameterTypes): 获取一个类中指定的构造方法。 参数为构造方法的参数列表。
上面两个方法只能获取public权限的方法,其他权限的无法获取。

Constructor表示构造方法, 里面的功能有:
    T newInstance(Object... initargs): 使用该构造方法创建对象, 参数为调用构造方法时传递的实际参数。

*/
public class Demo03ReflectConstructor {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
method2();
}

/*
    Constructor getConstructor(Class... parameterTypes): 获取一个类中指定的构造方法。
    获取Person类中的空参数的构造方法, 然后根据这个空参数的构造方法创建对象。
 */
public static void method2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
    //获取Person类的Class对象
    Class clazz = Class.forName("cn.itcast.demo02_reflect.Person");
    //获取类中的空参数构造方法
    //Constructor getConstructor(Class... parameterTypes): 获取一个类中指定的构造方法。 参数是要获取的构造方法的参数列表
    Constructor c = clazz.getConstructor();//如果getConstructor不写任何参数,表示的是获取空参数的构造方法。
    //使用空参构造方法创建对象
    Object obj = c.newInstance();//因为获取的是空参数构造方法,所以不需要传递参数, 所以newInstance省略参数。
    System.out.println(obj);
}

/*
    Constructor[] getConstructors(): 获取类的中的所有的构造方法。
 */
public static void method() throws ClassNotFoundException {
    //获取Person类的Class对象
    Class clazz = Class.forName("cn.itcast.demo02_reflect.Person");
    //Constructor[] getConstructors(): 获取类的中的所有的构造方法。
    Constructor[] cs = clazz.getConstructors();
    //遍历数组,打印里面的每一个内容
    for(Constructor c : cs) {
        System.out.println(c);
    }
}

}

⚫ 反射获取有参构造方法并使用
Class中获取Constructor的方法
Constructor[] getConstructors(): 获取类的中的所有的构造方法。
Constructor getConstructor(Class... parameterTypes): 获取一个类中指定的构造方法。 参数为构造方法的参数列表。
上面两个方法只能获取public权限的方法,其他权限的无法获取。

Constructor表示构造方法, 里面的功能有:
    T newInstance(Object... initargs): 使用该构造方法创建对象, 参数为调用构造方法时传递的实际参数。

注意: 所有的数据类型都有class属性,包括基本类型。


反射主要就三个步骤:
    1. 获取类的Class对象。
    2. 通过Class对象获取类的内容(构造方法,成员方法, 成员变量)
    3. 使用这个内容。

*/
public class Demo04ReflectConstructor {
//通过反射获取有参构造,并根据有参构造创建对象。
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取类的Class对象
Class clazz = Class.forName("cn.itcast.demo02_reflect.Person");
//获取有参构造
//public Person(String name, int age)
Constructor c = clazz.getConstructor(String.class, int.class);//表示要获取的构造方法第一个参数是String,第二个参数是int。
//T newInstance(Object... initargs): 使用该构造方法创建对象。参数表示调用构造方法时传递的实际参数。
Object obj = c.newInstance("老王", 20);//因为c表示的是两个参数的构造方法,所以使用该构造方法创建对象时,必须要传递两个实际参数。
System.out.println(obj);
}
}

⚫ 反射获取空参成员方法并执行

反射获取成员方法。

Class中有一些方法,可以获取到一个类中的成员方法:
    Method[] getMethods(): 获取到类中所有的成员方法。
    Method getMethod(String name, Class... parameterTypes):获取到的类中的指定的成员方法。 第一个参数是方法名, 第二个参数是该方法的参数列表。
    上面两个方法只能获取到一个类中public权限的成员方法。

Method表示的是成员方法,Method有一些功能:
    Object invoke(Object obj, Object... args): 让该方法执行。
        参数obj: 表示调用者对象。  如果调用的是静态方法,该参数传递null。
        参数args: 表示调用方法时传递的实际参数。
        返回值Object表示方法调用后的结果。

/
public class Demo06ReflectMethod {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
method2();
}
/

Method getMethod(String name, Class... parameterTypes):获取到的类中的指定的成员方法。 第一个参数是方法名, 第二个参数是该方法的参数列表。
获取Person中的eat()方法, 并让eat方法执行
*/
public static void method2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
//获取类的Class对象
Class clazz = Class.forName("cn.itcast.demo02_reflect.Person");
//获取Person中的eat方法
Method m = clazz.getMethod("eat");//第一个参数eat表示要获取的方法名是eat,第二个参数可变参数没有传递任何内容,表示获取的是空参数的eat方法
//调用invoke,让方法执行
//创建一个Person对象,用来执行方法
Object obj = clazz.newInstance();
//Object invoke(Object obj, Object... args): 让该方法执行。
//m表示的是eat方法,所以是eat方法执行, 因为第一个参数是obj,所以表示通过obj调用了eat方法,
//第二个参数应该是可变参数, 但是没有写任何东西,表示没有传递任何实际参数
m.invoke(obj); //相当于 obj.eat();
}

/*
    Method[] getMethods(): 获取到类中所有的成员方法。
 */
public static void method() throws ClassNotFoundException {
    //获取类的Class对象
    Class clazz = Class.forName("cn.itcast.demo02_reflect.Person");
    //通过类的Class对象调用getMethods获取所有的成员方法
    Method[] methods = clazz.getMethods();
    //遍历打印数组
    for (Method method : methods) {
        System.out.println(method);
    }
}

}

⚫ 反射获取成员方法

反射获取有参成员方法并执行

Class中有一些方法,可以获取到一个类中的成员方法:
    Method[] getMethods(): 获取到类中所有的成员方法。
    Method getMethod(String name, Class... parameterTypes):获取到的类中的指定的成员方法。 第一个参数是方法名, 第二个参数是该方法的参数列表。
    上面两个方法只能获取到一个类中public权限的成员方法。

Method表示的是成员方法,Method有一些功能:
    Object invoke(Object obj, Object... args): 让该方法执行。
        参数obj: 表示调用者对象。  如果调用的是静态方法,该参数传递null。
        参数args: 表示调用方法时传递的实际参数。
        返回值Object表示方法调用后的结果。

*/
public class Demo07ReflectMethod {
//获取有参成员方法并执行
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
//获取类的Class
Class clazz = Class.forName("cn.itcast.demo02_reflect.Person");
//获取Person中的sleep方法
//public void sleep(String address, int time)
Method method = clazz.getMethod("sleep", String.class, int.class);
//调用这个sleep方法,让它执行
//创建一个Person对象
Object obj = clazz.newInstance();
//通过invoke方法让sleep执行
method.invoke(obj, "天上人间", 3);// 相当于obj.sleep("天上人间", 3);
}
}

⚫ 反射获取set方法以及get方法完成赋值以及取值
/*
反射获取set/get方法分别完成赋值和取值的操作。

setName/getName

*/
public class Demo08ReflectMethod {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//获取Person的Class
Class clazz = Class.forName("cn.itcast.demo02_reflect.Person");
//通过Class创建Person对象
Object obj = clazz.newInstance();
//获取setName方法给对象属性赋值
//clazz调用getMethod获取方法
Method setMethod = clazz.getMethod("setName", String.class);//获取setName方法,setName有一个字符串的参数
//执行setName
setMethod.invoke(obj, "王叔叔");//相当于obj.setName("王叔叔");

    //获取getName方法,然后通过getName方法获取姓名的值。
    Method getMethod = clazz.getMethod("getName");
    Object result = getMethod.invoke(obj); //obj.getName();
    System.out.println(result);
}

}

⚫ 反射操作成员变量

/*
反射获取成员变量(了解)

在Class中有一些方法可以获取到成员变量
    Field[] getFields():获取到类中所有的成员变量。
    Field getField(String name) :获取类中的指定的成员变量,参数是成员变量的名字。
    上面两个方法只能获取到public权限的成员变量。

Field表示成员变量,里面也有一些功能:
    void set(Object obj, Object value):给成员变量设置值。
        参数obj:表示给哪个对象的成员变量设置值。
        参数value:表示设置成什么值。
    Object get(Object obj): 获取该成员变量的值。
        参数obj: 表示获取哪个对象的成员变量的值。
        返回值Object: 表示获取到的结果。

*/
public class Demo09ReflectFiled {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
method2();
}

/*
    获取Person中的hobby成员变量,赋值。
 */
public static void method2() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
    //获取Person的Class
    Class clazz = Class.forName("cn.itcast.demo02_reflect.Person");
    //获取hobby成员变量
    Field field = clazz.getField("hobby");
    //给hobby属性赋值
    //创建Person对象
    Object obj = clazz.newInstance();
    //给Person对象的hobby属性赋值
    field.set(obj, "编程");//相当于obj.hobby="编程"
    //获取obj的hobby属性值
    System.out.println(field.get(obj));//相当于输出流 obj.hobby
}

/*
    获取Person中的所有的成员变量
 */
public static void method() throws ClassNotFoundException {
    //获取Person的Class
    Class clazz = Class.forName("cn.itcast.demo02_reflect.Person");
    //通过class对象获取所有的成员变量
    Field[] fields = clazz.getFields();
    for (Field field : fields) {
        System.out.println(field);
    }
}

}

posted on 2021-03-04 22:20  凹凹凸凸  阅读(60)  评论(0编辑  收藏  举报

导航