反射学习笔记

为什么使用反射

比如某公司定义了一组接口,然后第三方公司按照这个公司的接口实现了一套功能,然后交给这个公司,但是这个公司的项目已经结束,如何实现动态加载第三方公司提供的功能。

什么是反射

反射就是把Java类中的各种成分映射成一个个的Java对象。例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。

反射常用类
  • Class类—可获取类和类的成员信息
  • Field类—可访问类的属性
  • Method类—可调用类的方法
  • Constructor类—可调用类的构造方法

使用反射的步骤

1.导入java.lang.reflect.*

​2.获得需要操作的类的Java.lang.Class对象

​3.调用Class的方法获取Field、Method等对象

​4.使用反射API进行操作(设置属性﹑调用方法)

Class类
Class类是反射的起源和入口
  • 每个类都有自己的Class对象
  • 提供了获取类信息的相关方法
  • Class类继承自Object类
Class类存储类的结构信息
  • 类名
  • 父类﹑接口
  • 方法﹑构造方法﹑属性
  • 注释
获取Class对象的方法

1.类名.getClass

//方法1:对象.getClass()
Student stu=new Student();
Class clazz=stu.getClass();

2.类名.Class

//方法2:类.class
clazz= Student.class;
clazz=String.class;

3.Class.forname(“stu”);推荐这种方法,耦合度低

//方法3:Class.forName()
clazz=Class.forName("java.lang.String");
clazz=Class.forName("java.util.Date");
获取类的其他信息
Class clazz = Class.forName("java.lang.Object");
Field fields[ ] = clazz.getDeclaredFields();//获取Field 对象  属性 
Method methods[] = clazz.getDeclaredMethods();//获取Method 对象  方法
Constructor constructors[] = clazz.getDeclaredConstructors();//获取Constructor对象   构造方法
动态创建对象方法

1.使用Class的newInstance()方法,仅限于无参构造

Class clazz=Class.forName("com.qf.reflection.Student");
Object obj=clazz.newInstance();	

2.使用Constructor方法的newInstance()方法,适用于所有构造方法

Constructor cons = clazz.getConstructor(new Class[]{ String.class,  int.class, float.class });
Object obj = cons.newInstance(new Object[ ] {"lkl", 32, 56.5f });

通过反射获取类的各种信息:

类:

package com.qf;

/*
 * wgy 2019/8/16 9:55
 * 佛祖保佑,永无BUG!
 */
public class Person extends AbstractPerson<String> implements Comparable<String>{
    //成员变量
    private String name;
    private int age;
    private String gender;
    //构造方法
    public Person() {
    }

    public Person(String name, int age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    //方法
    //无参无返回值
    public void show(){
        System.out.println("姓名:"+name+" 年龄:"+age+" 性别:"+gender);
    }
    //有参无返回值
    public void show(String address){
        System.out.println("姓名:"+name+" 年龄:"+age+" 性别:"+gender+" 地址:"+address);
    }
    //带返回值的方法
    public String getInfo(){
        return "信息:"+name+"  "+age+"  "+gender;
    }

    //静态方法
    public static void print(){
        System.out.println("这是一个静态方法");
    }

    //私有方法
    private void show(String address,String email){
        System.out.println("地址:"+address+"  邮箱:"+email);
    }

    @Override
    public int compareTo(String o) {
        return 0;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }
}

反射获得信息

package com.qf;

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

/*
 * 使用反射技术操作Person
 * (1)获取类的类对象
 * (2)获取类中构造方法
 * (3)获取方法
 */
public class Demo1 {
    public static void main(String[] args) throws Exception {
//        getClazz();
        //getConstructor();
//        getMethod();
        getField();

    }
    //(1)获取类的类对象
    public static void  getClazz() throws Exception{
        //方式1:使用class属性获取
        Class<?> clazz1=Person.class;
        System.out.println(clazz1.hashCode());
        //方法2  使用getClass方法
        Person shaobo=new Person();
        Class<?> clazz2 = shaobo.getClass();
        System.out.println(clazz2.hashCode());
        //方式3  使用Class.forName方法:耦合性低,不依赖于具体的类,可以编译通过
        Class<?> clazz3=Class.forName("com.qf.Person");
        System.out.println(clazz3.hashCode());
        //扩展
        //获取父类
        Class<?> superclass = clazz3.getSuperclass();
        System.out.println(superclass.getName());
        //获取父类泛型
        Type genericSuperclass = clazz3.getGenericSuperclass();
        System.out.println(genericSuperclass.getTypeName());
        //获取接口
        Class<?>[] interfaces = clazz3.getInterfaces();
        System.out.println(interfaces.length);
        for (Class<?> anInterface : interfaces) {
            System.out.println(anInterface.toString());
        }
        //获取包名
        Package aPackage = clazz3.getPackage();
        System.out.println(aPackage.getName());

    }	
    
 
    public static void getConstructor() throws Exception{
        Class<?> clazz=Class.forName("com.qf.Person");
        //1获取构造方法
        Constructor<?>[] constructors = clazz.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("--------------------------");
        //2获取单个构造方法
        //2.1获取无参构造方法
        Constructor<?> constructor = clazz.getConstructor();
        //2.2获取带参
        Constructor<?> constructor1 = clazz.getConstructor(String.class, int.class, String.class);
        System.out.println(constructor);//输出的是Person 的无参构造方法
        System.out.println(constructor1);//输出的是Person的有参构造方法,包括参数所在的包
        //3利用构造方法创建对象
        System.out.println("---------利用构造方法创建对象------------");
        Person zhangsan=new Person();
        Object lisi = constructor.newInstance();
        System.out.println(zhangsan);
        System.out.println(lisi);

        Object wangwu = constructor1.newInstance("王五", 20, "男");
        System.out.println(wangwu);

        //简单创建对象的方法
        Object o = clazz.newInstance();
        System.out.println(o.toString());

    }

	//获取方法
    public static void getMethod() throws Exception{
        //1获取无参的方法
        Class<?> clazz=Class.forName("com.qf.Person");
        //Method[] methods = clazz.getMethods();//获取公类自己公开的方法,继承的公开方法
//        Method[] methods = clazz.getDeclaredMethods();//获取公类自己所有的方法,包括非公开的方法
//        System.out.println("-----------getMethods();----------");
//        for (Method method : methods) {
//            System.out.println(method);
//        }

//        Person p=new Person();
//        p.show();
        Object zhangsan = clazz.newInstance();
        Method show = clazz.getMethod("show");
        show.invoke(zhangsan);// zhangsan.show();

        //2获取有参
        Method show2=clazz.getMethod("show",String.class);
        show2.invoke(zhangsan, "北京");

        //3获取带返回值的方法
        Method getInfo = clazz.getMethod("getInfo");
        Object value=getInfo.invoke(zhangsan);
        System.out.println(value);

        //4获取静态方法
        Method print = clazz.getMethod("print");
        print.invoke(null);// Person.print();

        //5私有方法
        Method show3 = clazz.getDeclaredMethod("show", String.class, String.class);
        //设置访问权限无效
        show3.setAccessible(true);
        show3.invoke(zhangsan, "上海","zhangsan@qq.com");
    }

    public static void getField() throws  Exception{
        //1获取类对象
        Class<?> clazz = Class.forName("com.qf.Person");
        //2获取
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        //获取单个
        System.out.println("--------------------------");
        Field name = clazz.getDeclaredField("name");
//
//        Person wangwu=new Person();
//        wangwu.name="王五";
        Object wangwu = clazz.newInstance();

        //赋值
        name.setAccessible(true);
        name.set(wangwu, "王五");//  wangwu.name="王五";

        //获取
        Object object=name.get(wangwu);// wangwu.name
        System.out.println(object);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值