反射

 

 

 

 2.1反射概述
Java反射机制:是指在运行时去获取一个类的变量 和方法信息。然后通过获取到的信息来创建对象,调用方法的一
种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展

获取Class类的对象
我们要想通过反射去使用一个类,首先我们要获取到该类的字节码文件对象,也就是类型为Class类型的对象
这里我们提供三种方式获取Class类型的对象
●使用类的class属 性来获取该类对应的Class对象。举例: Student.class将 会返回Student类对应的Class对象
●调用对象的getClass0方法, 返回该象所属类对应的Class对象
该方法是Object类中的方法,所有的Java对象都可以调用该方法
●使用Class类中的静态方法forName(String className),该方法需要传入字符串参数,该字符串参数的值是某
个类的全路径,也就是完整包名的路径

 

package com.test02;


public class reflectDemo {
    public static void main(String[] args) throws ClassNotFoundException {
//        1:使用类的class属性来获取该类对应的Class对象
        Class<Student> c1 = Student.class;
        System.out.println(c1);
        System.out.println("---------");
        Student s = new Student();
        Class<? extends Student> c2 = s.getClass();
//        调用对象的getClass()方法
        System.out.println(c2);
        System.out.println("-------------");
//        使用Class类中的静态方法forName(String className)
        Class<?> c3 = Class.forName("com.test02.Student");
        System.out.println(c3);
    }
}

 

反射获取构造方法并使用
Class类中用于获取构造方法的方法

数组:
●Constructor<?> ] getConstructors(): 返回所有公共构造方法对象的数组
●Constructor<?>[ getDeclaredConstructors0: 返回所有构造方法对象的数组

单个:
●Constructor<T> getConstructor(Class <?> .. parameterTypes):返回单个公共构造方法对象
●Constructor<T> getDeclaredConstructor(Class<?> .. parameterTypes):返回单个构造方法对象


Constructor类中用于创建对象的方法
●T newlnstance(Objec... initargs):根据指定的构造方法创建对象
//暴力反射

public void setAccessible(boolean flag):值为true,取消访问检查

 

 

package com.test02;
/*
反射获取构造方法并使用
 */

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class refelectDemo01 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取class对象
        Class<?> c1 = Class.forName("com.test02.Student");

//        Constructor<?>[] getConstructors​() 返回一个包含 Constructor对象的数组,
//         Constructor对象反映了由该 Class对象表示的类的所有公共构造函数。
        Constructor<?>[] cons = c1.getConstructors();

        //  Constructor<?>[] getDeclaredConstructors​()
// 返回反映由该 Class对象表示的类声明的所有构造函数的 Constructor对象的数组。
        Constructor<?>[] cons2 = c1.getDeclaredConstructors();
        for(Constructor con:cons2) {
            System.out.println(con);
        }
        System.out.println("-----------");

//        Constructor<T> getConstructor​(Class<?>... parameterTypes)
//        返回一个 Constructor对象,该对象反映由该 Class对象表示的类的指定公共构造函数。

//        Constructor<T> getDeclaredConstructor​(Class<?>... parameterTypes)
//        返回一个 Constructor对象,该对象反映由此 Class对象表示的类或接口的指定构造函数。

        //Constructor<?> con = c1.getConstructor();


        //Constructor是供了-一个类的单个构造函数的信息和访问权限
//        T newInstance​(Object... initargs)
//        使用由此 Constructor对象表示的构造函数,使用指定的初始化参数来创建和初始化构造函数的声明类的新实例。
        //
//        基本数据类型也可以通过.Class得到对应的Class类型
                //练习1
        Constructor<?> con3 = c1.getConstructor(String.class, int.class, String.class);
        Object obj = con3.newInstance("林青霞",30,"西安");
        System.out.println(obj);
        System.out.println("-----------");
//        练习2 通过反射实现如下的操作:
//        Student s = new Student( "林青霞");
//        System. out. println(s);

        //暴力反射
//     public void setAccessible​(boolean flag)将此反射对象的accessible标志设置为指示的布尔值。 值为true表示反射对象
//     应该在使用Java语言访问控制时抑制检查。 值为false表示反射对象应该在使用Java语言访问控制时执行检查,并在类描述中指出变体。
        Constructor<?> con4 = c1.getDeclaredConstructor(String.class);
        con4.setAccessible(true);//由于下面对私有构造方法
        Object obj1 = con4.newInstance("林青霞");
        System.out.println(obj1);


    }
}

 

 

反射获取成员变量并使用
Class类中用于获取成员变量的方法
  Field[ getFields():返回所有公共成员变对象的数组
  Field[] getDeclaredFields():返回所有成员变量对象的数组
  Field getField(String name):返回单个公共成员变量对象
  Field getDeclaredField(String name):返回单个成员变量对象
Field类中用于给成员变量赋值的方法
●void set(Object obj, Object value):给obj对象的成员变量赋值为value

package com.test02;
/*
反射获取成员变量
 */

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class reflectDemo02 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取class对象
        Class<?> c = Class.forName("com.test02.Student");
//        Field[] getFields​() 返回一个包含 Field对象的数组, Field对象反映由该 Class对象表示的类或接口的所有可访问的公共字段。
//        Field[] getDeclaredFields​()             返回一个 Field对象的数组,反映了由该 Class对象表示的类或接口声明的所有字段。
//        Field[] fields = c.getFields();
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("---------------");
//        Field getField​(String name) 返回一个 Field对象,该对象反映由该 Class对象表示的类或接口的指定公共成员字段。
//        Field getDeclaredField​(String name) 返回一个 Field对象,该对象反映由该 Class对象表示的类或接口的指定声明字段。
//        Field getField​(String name)
        Field field = c.getField("address");//成员变量的引用对象

        //获取无参构造方法创建对象
        //FieLa提供有关类或接口的单个字段的信息和动态访问
        //void set (object obj, object value) 将指定的对象参数中由此Field对象表示的字段设置为指定的新值

        Constructor<?> con = c.getConstructor();
        Object obj = con.newInstance();
        field.set(obj, "北京");//给obj的成员变量field赋值为北京
        System.out.println(obj);


//        Student s = new Student();
//····s.address = "西安";
//····System. out . println(s);

        System.out.println("----------------");

//        Field getDeclaredField​(String name)
        Field age = c.getDeclaredField("age");

        System.out.println(age); //age对象的引用
    }
}

 

通过反射给成员变量赋值练习

package com.test02;
/*
练习:通过反射实现如下操作
        Students = ngw Student();
        s.name = "林青霞";
        s.age = 30;
        s.address = "西安";
        System.out.printin();

 */

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class reflectDemo03 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //获取要反射的类的对象
        Class<?> c = Class.forName("com.test02.Student");

        //创建对象示例
//        通过有参构造赋值
//        Constructor<?> con = c.getConstructor(String.class, int.class, String.class);
//        Object obj = con.newInstance("林青霞",30,"西安");

        Constructor<?> con = c.getConstructor();
        Object obj = con.newInstance();
        System.out.println(obj);

        //通过反射成员变量赋值


        Field name = c.getDeclaredField("name");
        name.setAccessible(true);
        name.set(obj,"林青霞");

        Field age = c.getDeclaredField("age");
        age.setAccessible(true);
        age.set(obj,33);

        Field address = c.getField("address");
        address.set(obj,"北京");
        System.out.println(obj);

//


    }
}

 


反射获取成员方法并使用


Class类中用于获取成员方法的方法
●Method[ getMethods0: 返回所有公共成员方法对象的数组,包括继承的
●Method] getDeclaredMethods(): 返回所有成员方法对象的数组,不包括继承的
●Method getMethod(String name, Class <?> .. parameterTypes):返回单个公共成员方法对象
●Method getDeclaredMethod(String name, Class <?> .. parameterTypes):返回单个成员方法对象
Method类中用于调用成员方法的方法
●Object invoke(Object obj, Object... args):调用obj对象的成员方法,参数是args,返回值是Object类型

package com.test02;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class reflectDemo04 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取class对象
        Class<?> c = Class.forName("com.test02.Student");
//   Method[] getMethods​() 返回一个包含 方法对象的数组, 方法对象反映由该 Class对象表示的类或接口的所有公共方法,
//             包括由类或接口声明的对象以及从超类和超级接口继承的类。
//   Method[] getDeclaredMethods​() 返回一个包含 方法对象的数组, 方法对象反映由 Class对象表示的类或接口的所有声明方法,
//      包括public,protected,default(package)访问和私有方法,但不包括继承方法。
        Method[] Methods = c.getDeclaredMethods();
        for (Method method : Methods) {
            System.out.println(method);
        }

//        Method getMethod​(String name, Class<?>... parameterTypes) 返回一个 方法对象,
//              该对象反映由该 Class对象表示的类或接口的指定公共成员方法。
//        Method getDeclaredMethod​(String name, Class<?>... parameterTypes) 返回一个 方法对象,
//              它反映此表示的类或接口的指定声明的方法 Class对象。
        Method m = c.getMethod("method1");
        //获取无参构造方法创建对象

        Constructor<?> con = c.getConstructor();
        Object obj = con.newInstance();
        //在类或接口上提供有关单- 方法的信息和访问权限
//        Object invoke​(Object obj, Object... args) 在具有指定参数的指定对象上调用此 方法对象表示的基础方法。
        //0bject: 返回值类型
        //obj:调用方法的对象
        //args:方法需要的参数

        m.invoke(obj);


//        Student s = new Student();
//        s. method1( ) ;


    }
}

 练习:通过反射实现如下操作

Student s = new Student();

s . method1();

s. method2("林青霞");

String ss = s.method3( "林青霞", 30);

System. out. println(ss);

s. function();

 

package com.test02;
/*
练习:通过反射实现如下操作
Student s = new Student();
s . method1();
s. method2("林青霞");
String ss = s.method3( "林青霞", 30);
System. out. println(ss);
s. function();

 */

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class reflectDemo05 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取类的对象
        Class<?> c = Class.forName("com.test02.Student");

//        Student s = new Student();
        Constructor<?> con = c.getConstructor() ;
        Object obj = con.newInstance();

//        s . method1();
//        invoke调用对象
        Method method1 = c.getMethod("method1");
        method1.invoke(obj);

//        s. method2("林青霞");
        Method method2 = c.getMethod("method2", String.class);
        method2.invoke(obj,"林青霞");
//        String ss = s.method3( "林青霞", 30);
        Method method3 = c.getMethod("method3", String.class, int.class);
        Object ss = method3.invoke(obj, "林青霞", 30);
        System.out.println(ss);

//        s. function();
        Method function = c.getDeclaredMethod("function");
        function.setAccessible(true);
        function.invoke(obj);


    }
}

反射练习之越过泛型检查

package com.test02;
/*
练习1:我有一个Arraylist<Integer>集合, 现在我想在这个集合中添加一-个字符串数据,如何实现?

 */

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

public class refiectDemo06 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //创建集合
        ArrayList<Integer> array = new ArrayList<Integer>();
        array.add(10);
        array.add(20);
        array.add(30);
//        array.add("hello");

        Class<? extends ArrayList> c = array.getClass();
        
        Method m = c.getMethod("add", Object.class);

        m.invoke(array, "hello");
        System.out.println(array);
    }
}

反射运行配置文件

 

posted @ 2019-09-03 19:25  水果、、  阅读(239)  评论(0编辑  收藏  举报