学技术ing——反射

1、什么是反射?

反射是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说“自审”,也有称作“自省”。反射非常强大,它甚至能直接操作程序的私有属性。我们前面学习都有一个概念,被private封装的资源只能类内部访问,外部是不行的,但这个规定被反射赤裸裸的打破了。
反射就像一面镜子,它可以在运行时获取一个类的所有信息,可以获取到任何定义的信息(包括成员变量,成员方法,构造器等),并且可以操纵类的字段、方法、构造器等部分。
那么,作为小白的我怎么理解:
概念:反射是Java的一种机制,让我们可以在运行时获取类的信息;
作用:通过反射,我们可以在程序运行时动态创建对象,还能获取到类的所有信息,比如它的属性、构造器、方法、注解等;

2、利用反射动态创建对象

2.1 获取class对象的三种方式

//创建一个实体类
public class Animal {
    private String name;
    private String sex;
    private int age;

    public Animal(){

    }

    public Animal(String name, String sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

public class TestAnimal {
    public static void main(String[] args) {
        Animal dog = new Animal("小狗", "公", 2);
        Animal cat = new Animal("小猫", "母", 4);
        /**
         * 获取对象的三种方式
         */
        //1、利用 getClass()方法获取对象的class对象
        Class c1 = dog.getClass();
        Class c2 = cat.getClass();
        System.out.println(c1 == c2);//true

        //2、利用class属性获取字节码文件
        // (类,class:需要输入一个明确的类,任意一个类型都有一个静态的class属性)
        Class c3 = Animal.class;
        System.out.println(c1 == c3);

        //3、利用Class.forName()获取--最常用的方式
        //通过Class类的一个forName(String className)静态方法返回一个Class对象,
        //className必须是全路径名称;
        //Class.forName()有异常:ClassNotFoundException
        try {
            Class c4 = Class.forName("com.etime.entity.Animal");
            System.out.println(c3 == c4);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
}

2.2 动态创建对象

(1)newInstance()创建对象

        //2.2.1 newInstance()创建对象
        try {
            Object obj = c3.newInstance();
            System.out.println(obj.toString());
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

通过Class对象的newInstance()方法来创建Class对象对应类的实例。这个方法是使用Class对象对应类的默认构造器创建对象,这就要求Class对象对应类必须要有默认构造器(无参数的构造方法)。

(2)构造方法创建对象
使用Class对象获取指定的Constructor对象,调用Constructor对象的newInstance()方法来创建Class对象对应类的实例。这个方法可以使用Class对象对应类的任意指定的构造器来创建实例。

//2.2.2 构造方法创建对象
try {
    Constructor constructor = c3.getConstructor(String.class, String.class, int.class);
    Object obj = constructor.newInstance("猪", "母", 2);
    System.out.println(obj.toString());
} catch (NoSuchMethodException e) {
    e.printStackTrace();
} catch (InvocationTargetException e) {
    e.printStackTrace();
} catch (InstantiationException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
}

三、利用反射调用方法

//获取class对象
			Class c1 = Class.forName("edu.etime.reflex.demo1.Animal");
			//反射创建类的实例
			Animal obj = (Animal) c1.newInstance();		
			obj.setName("人");
			//通过反射获取到method对象
			Method m = c1.getMethod("getName");
			//通过method对象的invoke方法调用方法
			Object o = m.invoke(obj);
			System.out.println(o);
			

四、动态操作属性(调用get,set方法)

//获取class对象
		Class c1 = Class.forName("edu.etime.reflex.demo1.Animal");
		//反射创建类的实例
		Animal obj = (Animal) c1.newInstance();	
		//获取公有属性
		Field[] fileds = c1.getFields();
		for(Field f :fileds){
			System.out.println("公有属性:"+f.getName());
			
		}

		Field[] fileds2 = c1.getDeclaredFields();
		for(Field f :fileds2){
			System.out.println("私有属性:"+f.getName());
		}
		//给属性赋值
		Field[] fileds2 = c1.getDeclaredFields();
		for(Field f :fileds2){
			System.out.println("私有属性:"+f.getName());
			f.setAccessible(true);
			if(f.getType().equals(String.class)){
				f.set(obj, "123");
			}else if(f.getType().equals(int.class)){
				f.set(obj, 123);
			}
		}
		System.out.println(obj.toString());

		//调用get,set方法
		PropertyDescriptor p = new PropertyDescriptor("name",c1);
		//获取写方法
		Method mset = p.getWriteMethod();
		mset.invoke(obj, "xxxxxxx");
		//获取读方法
		Method mget =  p.getReadMethod();
		System.out.println(mget.invoke(obj));

五、反射的应用场景

1、Spring 实例化对象:当程序启动时,Spring 会读取配置文件applicationContext.xml并解析出里面所有的标签实例化到IOC容器中。
2、反射 + 工厂模式:通过反射消除工厂中的多个分支,如果需要生产新的类,无需关注工厂类,工厂类可以应对各种新增的类,反射可以使得程序更加健壮。
3、JDBC连接数据库:使用JDBC连接数据库时,指定连接数据库的驱动类时用到反射加载驱动类

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值