day07_反射

一、原理

简介:

  1. 应用在一些通用性比较高的代码中
  2. 大多数使用反射来实现 框架
  3. 在框架开发中,都是基于配置文件开发的
    在配置文件中,可以通过反射,得到类中的所有内容,可以让类中的某个方法来执行

Tomcat 对外提供了接口,为了扩展功能,由开发者来实现具体请求和应答处理
Java反射机制是在运行状态中, 对任意一个类(class),都能知道这个累的属性和方法
对于任意一个对象,可以调用他的任意一个方法和属性
动态获取信息+动态动态调用对象的方法的功能=java语言的反射机制[对类的解剖]

反射技术:加载字节码文件,获取并调用其中的内容
对一个类文件进行解剖,只需要拿到该类的字节码文件对象即可.
配置变化的参数信息

原理:

  1. 把Java文件保存到本地硬盘 .java
  2. 编译Java文件,成.class文件
  3. 使用JVM,把class文件通过类加载器加载到内存中
  4. class文件在内存中,使用class类来表示对象
  5. 反射:首先,获取class类,其次,得到里面所有内容
  6. 如何获取?
    属性:通过一个类 Filed
    构造方法:通过一个类 Constructor
    普通方法:通过一个类Method

得到class类的3种方式:

  1. 类名.class
    任何对象都具备 静态属性.class,来获取对应的class对象
    相对简单,但是必须明确到类中的静态成员–>不够扩展

  2. 对象.getClass()
    必须明确具体的类 并创建对象,麻烦[不建议]

  3. 使用Class.forName(“路径”)
    知道 类的字符串名称 就可以获得该类
    方便,扩展性强

二、使用反射操作无参构造方法

//操作无参构造方法
@Test
public void test1() throws Exception {
    //得到class
    Class c3 = Class.forName("cn.itcast.test06.Person");
    //得到Person类的实例
    Person p = (Person) c3.newInstance();

    p.setId(1500);
    System.out.println(p.getId());
}

对一个对象实例化,可以new ,不使用new的话,可以如下操作:

//得到class
    Class c3 = Class.forName("cn.itcast.test06.Person");
    //得到Person类的实例
    Person p = (Person) c3.newInstance();

三、使用反射操作有参构造方法

//操作有参构造方法
@Test
public void test2() throws Exception {
    //得到class
    Class c1 = Class.forName("cn.itcast.test06.Person");
    //使用有参构造方法
    //c1.getConstructors();//获取所有的构造方法

    //穿肚有参数的构造方法里面的参数类型,类型使用class形式传递
    Constructor cs = c1.getConstructor(String.class,String.class);
    //通过有参数的构造方法,设置值,创建Person实例
    Person p1 = (Person) cs.newInstance("jingvjing","100");
    System.out.println(p1.getId()+":"+p1.getName());    
}

四、使用反射操作name属性

@Test
//操作name属性
public void test3() throws Exception {

    try{//得到class
    Class c3 = Class.forName("cn.itcast.test06.Person");
    //得到name属性
    //c3.getDeclaredFields();//获取所有属性
    //得到person实例
    Person p11 = (Person)c3.newInstance();
    Field f1 = c3.getDeclaredField("name");
    //设置可以操作私有属性,不让操作时,使用这个
    f1.setAccessible(true);
    //设置name值[实例,值]
    f1.set(p11, "wujing");
    System.out.println(p11.getName());
    }catch(Exception e) {
        e.printStackTrace();
    }

}

五、使用反射操作普通方法

//操作方法
@Test
public void test4() throws Exception {
//得到class
    Class c4 = Class.forName("cn.itcast.test06.Person");
    //得到实例
    Person p12 = (Person)c4.newInstance();
    //得到普通方法
    //c4.getDeclaredMethods();//得到所有方法  【方法名,方法值】
    Method m1 =c4.getDeclaredMethod("setName", String.class);
    //执行setName方法,设置值 【类的实例,设置值】
    m1.invoke(p12,"aoao");
    System.out.println(p12.getName());  
}

反射操作静态方法时,类名.静态方法,不需要实例。代码为:m1.invoke(null,”aoao”);


package cn.itcast.reflect.dmeo;

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

import cn.itcast.bean.Person;

public class ReflectDemo {

    public static void main(String[] args) throws Exception {
//      getClassObject();
//      getClassObject2();
//      getClassObject3();
//      getFieldDemo();
//      getMethodDemo();
//      getMethodDemo1();
//      getMethodDemo22();
    }

    //调用有参方法
    public static void getMethodDemo22() throws Exception {
        Class c = Class.forName("cn.itcast.bean.Person");

        Method m = c.getMethod("parammethod", String.class,int.class);//方法必须是公有的

        Object obj = c.newInstance();
        m.invoke(obj, "one",80);

    }

    //调用无参方法
    private static void getMethodDemo1()  throws Exception{
        Class c = Class.forName("cn.itcast.bean.Person");

        Method m = c.getMethod("show", null);

        Constructor con = c.getConstructor();
        Object obj = con.newInstance();

        m.invoke(obj, null);                
    }

    //获取所有公有方法+获取本类中的方法
    private static void getMethodDemo() throws Exception {
        Class c = Class.forName("cn.itcast.bean.Person");
        Person p = (Person) c.newInstance();

        Method[] m = c.getMethods();//获取所有公有方法
        Method[] m1 = c.getDeclaredMethods();//获取本类中的方法,包含私有


        for(Method ms :m1) {
            System.out.println(ms);
        }   
    }

    //获取字节码中的字段
    private static void getFieldDemo() throws Exception {
        Class c  = Class.forName("cn.itcast.bean.Person");

        Field field = null; 
        field = c.getDeclaredField("age");//只获取本类,但包含私有     
        //对私有字段访问取消权限检查
        field.setAccessible(true);
        Object obj = c.newInstance();
        //设置值
        field.set(obj, 89);
        Object o = field.get(obj);
        System.out.println(o);

    }

    //知道  类的字符串名称 就可以获得该类
    //方便,扩展性强
    private static void getClassObject3() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
        Class c1 = Class.forName("cn.itcast.bean.Person");
        System.out.println(c1);
        Constructor con = c1.getConstructor(int.class,String.class);
        Person p = (Person) con.newInstance(20,"ioo");

        System.out.println(p.getAge()+":"+p.getName());
    }

    //任何对象都具备  静态属性.class,来获取对应的class对象
    //相对简单,但是必须明确到类中的静态成员-->不够扩展
    private static void getClassObject2() throws InstantiationException, IllegalAccessException {
        Class c1 = Person.class;
        Class c2 = Person.class;
        Person p = (Person) c1.newInstance();

        p.setAge(123);
        p.setName("ann");

        System.out.println((c1==c2)+"\r\n"+p.getAge()+p.getName());
    }

    //必须明确具体的类  并创建对象,麻烦[不建议]
    private static void getClassObject() {
        Person p = new Person();
        Class c = p.getClass();

        Person p1 = new Person();
        Class c1 = p1.getClass();

        System.out.println(c1==c);
    }


}

猜你喜欢

转载自blog.csdn.net/weixin_39134861/article/details/78876780
今日推荐