美文网首页
java反射

java反射

作者: 0640fefbc8bf | 来源:发表于2019-03-06 16:25 被阅读0次

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

反射概念:

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

  • 对于任意一个类,都能够知道这个类的属性和方法
  • 对于任意一个对象,都能够调用他的方法与属性

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

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的方法
  • 生成动态代理

declared:公然的,公开的

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

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

  • 类型为Class
  • 获取反射对象(反射入口)
    1.Class.forname(全类名) (带异常处理 推荐使用)
//        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);
  • 注意凡是反射必须是Class

获取方法

第一步还是获取反射接口

//        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());

相关文章

  • 博客地址

    java注解-01、java注解-02、Git面试资源java反射-01、java反射-02、java反射-03为...

  • Java反射机制入门

    Java反射机制入门 一、什么是反射 JAVA反射机制(The JAVA reflection mechanism...

  • Java基础之反射

    Java基础之—反射(非常重要)Java中反射机制详解Java进阶之reflection(反射机制)——反射概念与...

  • 反射之一

    总结内容源自一下文章粗浅看java反射机制反射机制应用实践谈谈java反射机制Java Reflection(反射...

  • 反射之二

    总结内容源自一下文章粗浅看java反射机制反射机制应用实践谈谈java反射机制Java Reflection(反射...

  • Java基础之反射

    Java基础之反射 反射基本介绍 反射的使用通过反射调用属性和方法通过反射获取配置文件 反射基本介绍 Java反射...

  • Java 反射机制

    Java 反射机制 什么是反射 Java 反射是Java语言的一个很重要的特征,它使得Java具体了“动态性”。 ...

  • 一探究竟:Java反射效率低的原因到底在哪?

    预备知识 了解 Java 反射基本用法 看完本文可以达到什么程度 了解 Java 反射原理及 Java 反射效率低...

  • 面试官说:大家都说 Java 反射效率低,你知道原因在哪里么

    预备知识 了解 Java 反射基本用法 看完本文可以达到什么程度 了解 Java 反射原理及 Java 反射效率低...

  • Java面试题之JavaSE高级

    一、Java中的反射 1.说说你对Java中反射的理解 java中的反射首先是能够获取到Java...

网友评论

      本文标题:java反射

      本文链接:https://www.haomeiwen.com/subject/enxwuqtx.html