java反射

2019-03-06  本文已影响0人  0640fefbc8bf

Class的理解:
https://www.cnblogs.com/flyme/p/4571030.html

反射概念:

反射机制在【运行状态】中:

反射提供的功能(具体能做什么事情):

declared:公然的,公开的

反射中基本类型(int,char)和包装类(Integer,Character)是不同的类型

第一步:获取反射对象(反射入口)

//        1.Class.forName(全类名)
        try {
            Class<?> perclass = Class.forName("reflect.Person");
            System.out.println(perclass);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

2.类名.Class

 Class<?> perclass2 = Person.class;
        System.out.println(perclass2);

3.对象.getclass()

Person person = new Person();
        Class<?> perclass3 = person.getClass();
        System.out.println(perclass3);

获取方法

第一步还是获取反射接口

//        1.Class.forName(全类名)
        try {
            Class<?> perclass = Class.forName("reflect.Person");
            System.out.println(perclass);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

获取所有的公共方法(1.本类以及父类中以及接口中所有的方法,2.符合访问修饰符规律 public private不行)

 Method[] methods = perclass.getMethods();
        for (Method method:methods){
            System.out.println(method);
        }

//获取当前类的所有方法(1.忽略访问修饰符规律 2.只限当前类)

        Method[] methods1 = perclass. getDeclaredMethods();
        for (Method method:methods1){
            System.out.println(method);

获取属性

//获得所有的公共属性(第一步仍然是获取反射接口)

 Field[]  fields= perclass.getFields();
        for (Field field:fields){
            System.out.println(field);
        }

//所有的属性

        Field[] fields1 = perclass.getDeclaredFields();
        for (Field field:fields1){
            System.out.println(field);

获得所有的反射接口

Class<?>[] interfaces = perclass.getInterfaces();
        for (Class<?> inter:interfaces){
            System.out.println(inter);

获得父类

 Class<?> superclass = perclass.getSuperclass() ;
        System.out.println(superclass);

获取对象

Object instance = perclass.newInstance();
        Person person = (Person) instance;
        person.interfaceMethod();

注意 所以得获取前提都是先获得反射接口

获得对象的实例并且操作对象

1.首先拿到类

Class<?> perclass = null;
        try {
           perclass = Class.forName("reflect.Person");
            System.out.println(perclass);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

2.转化为实例

Person person = (Person)perclass.newInstance();//将instance转化为Person

3.调用属性和方法并测试

 person.setNama("zhangsan"); 
 person.setAge(22);

操作属性

1.首先拿到类

Class<?> perclass = null;
        try {
           perclass = Class.forName("reflect.Person");
            System.out.println(perclass);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

2.转化为实例

Person person = (Person)perclass.newInstance();//将instance转化为Person

3.设置属性

idField.set(person,"1"); 等同于//person.setid(1)

Field idField = perclass.getDeclaredField("id");
idField.set(person,"1");//person.setid(1)
System.out.println(person.getId());

这时候运行一下会报错


错误提示

错误原因:

访问的是private修饰的id,但是private是私有的 只能本类访问

措施

修改属性访问权限 ,使用反射时如果因为访问修饰符造成异常 可以通过Field/Method/Constructor.setAccessible(true)

操作方法

Method method = perclass.getDeclaredMethod("privateMethod",null);
method.setAccessible(true);
method.invoke(person,null);//方法的调用invoke()
//person.say(xxx)

这里的null是表示parameter参数 QQ截图20190305173104.png

Method method = perclass.getDeclaredMethod("object",parameter);

这是一个不带参数的方法 所以填写null

带参方法的操作

带参.png
Method method1 = perclass.getDeclaredMethod("privateMethod2",String.class);
method1.setAccessible(true);
method1.invoke(person,"zhangsan");

两个方法都是用private修饰 所以需要我们Method.setAccessible(true);

操作构造方法

获取全部公共构造方法

 Constructor<?>[] constructors = perclass.getConstructors();
    for (Constructor constructor:constructors){
         System.out.println(constructor);

获取本类全部 构造.png

Constructor<?>[] constructors02 = perclass.getDeclaredConstructors();
       for (Constructor constructor:constructors02) {
            System.out.println(constructor);

获取指定构造方法

构造方法分为有参无参以及public修饰和private修饰

1.操作无参构造方法

QQ截图20190305185007无参.png

1.1获取指定构造方法

 Constructor<?> constructor02 = perclass.getConstructor() ;

1.2创建对象进行强制转换

    Person person1 = (Person) constructor02.newInstance();
    System.out.println(person1);

2.操作有参构造方法 指定.png

2.1.获取反射入口

 Class<?> perclass = null;
        try {
            perclass = Class.forName("reflect.Person");
            System.out.println(perclass);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

2.2获取指定构造方法getConstructor(属性类型.class)

Constructor<?> constructor = perclass.getConstructor(String.class) ;

2.3创建对象进行赋值

 Person person = (Person)constructor.newInstance("za");//转化为Person类
        System.out.println(person);

3.操作private修饰的构造方法

构造.png

3.1获取指定构造方法

Constructor<?> constructor03 = perclass.getDeclaredConstructor(int.class) ;

3.2因为是private修饰 这个需要释放权限

        constructor03.setAccessible(true);

3.3创建对象并赋值

    Person person2 = (Person)constructor03.newInstance(22);
    System.out.println(person2);

动态加载类名和方法

1.首先在项目下建立一个class.txt文本

微信截图_20190306154031.png

2.读取文件(在运行时调用方法 创建对象 运行之前不知道)

Properties prop = new Properties();
        prop.load( new FileReader("class.txt"));
        String classname = prop.getProperty("classname");//获得类名
        String methodname = prop.getProperty("methodname");//获得方法名

获得反射入口...

try {
            perclass = Class.forName(classname);//这里的类名不是指定的了
            System.out.println(perclass);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

拿到方法并调用方法

Method method = perclass.getMethod(methodname);
 method.invoke(perclass.newInstance());//创建对象调用方法

//反射可以越过泛型检查(虽然可以通过反射可以访问private等访问修饰符不允许访问的属性和方法,也可以忽略泛型的约束 但实际开发不建议)

ArrayList<Integer> list = new ArrayList<>();//这里指定可以添加Integer类型
        list.add(12);
        list.add(14);
        list.add(15);

        Class<?> listClass = list.getClass();
        Method method = listClass.getMethod("add",Object.class);
        method.invoke(list,"zs");//因为上面创建过对象所以这边不需要listClass.newInstance 一个新的对象
        System.out.println(list);

通过反射写一个万能赋值方法

//person.setXxx(value);一一对应
public static void setProperty(Object obj, String propertyName, Object value) throws NoSuchFieldException, IllegalAccessException {
        Class<?> perclass = obj.getClass();
        Field field = perclass.getDeclaredField( propertyName);//获得属性
        field.setAccessible(true);//因为是私有的
        field.set(obj,value);//(对象,方法)
    }
Person person = new Person();
     PropertyUtil.setProperty(person,"nama","zs");
       System.out.println(person.getNama());
上一篇 下一篇

猜你喜欢

热点阅读