java中的反射应用

反射

我们先创建一个Student类出来。注意类中的成员变量、构造方法、成员方法公共还是私有

package com.reflect;

public class Student {
	//成员变量
	public String name;//公共
	private int age;//私有
	
	//构造方法
	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}

	//私有构造方法
	private Student(String name) {
		this.name = name;
	}
	
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	//成员方法(getXxx/setXxx)
	public String getName() {
		return name;
	}

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

	public int getAge() {
		return age;
	}

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

	//成员方法
	public void study() {
		System.out.println("我爱学习java!");
	}
	// 私有
	private void study(String string) {
		System.out.println("我还爱学习"+string);
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
}


反射概述

  1. 反射:反射是通过class文件对象,去使用文件对象的成员方法、构造方法、成员变量
    回想之前我们使用对象方法时必须通过new对象去使用。new Student().study(),此时我们就发现了一个问题,小例中我们肯定是知道Student类中是有study()方法的,如果我们想使用用这个类但却不清楚类中的信息,此时反射就起到了一定作用。
    其实反射的作用,不止这一点点。如下
  2. 反射可以提高程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,无需提高硬编码目标类
    Java反射技术应用领域很广,后期如软件测试、JavaBean等都有很重要的作用
    许多流行的开源框架例如Struts、Hibernate、Spring在实现过程中都采用了该技术
  3. 性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此Java反射机制只要应用在对;灵活性和扩展性要求很高的系统框架上,普通程序不建议使用使用反射会模糊程序内部逻辑:程序员希望在代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。

反射获取Class类对象

  1. 要想使用反射,我们必须得到class文件对象,也就是我们要使用的类Class对象
  2. 三种获得class文件对象的方法:
    • Object类的getClass()方法
    • 数据类型的静态属性class
    • Class类中的静态方法public static Class forName(String classname)
      一般我们使用第三种
package com.reflect;

public class Demo {
	public static void main(String[] args) throws ClassNotFoundException {
		// 方式1
		Student p = new Student();
		Class c = p.getClass();

		Student p2 = new Student();
		Class c2 = p2.getClass();

		System.out.println(p == p2);// false不是同一Student对象
		System.out.println(c == c2);// true是同一class对象

		// 方式2
		Class c3 = Student.class;
		System.out.println(c == c3);//true是同一class对象

		// 方式3
		// ClassNotFoundException(类找不到时)
		Class c4 = Class.forName("com.reflect.Student");
		System.out.println(c == c4);//true是同一class对象
	}

}

Class类中相关的几个类

  • 和成员变量有关 Field
  • 和构造方法有关 Constructor
  • 和成员方法有关 Method
    有关的几个方法
  • public T newInstance(Object… initargs) 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。

反射获取构造方法

先来认识几个方法

public Constructor getConstructor()// 公共构造方法对象
public Constructor[] getConstructors()//所有公共构造方法对象
public Constructor[] getDeclaredConstructors()//所有构造方法对象
public Constructor getDeclaredConstructor()//获取私有构造方法对象
public Constructor<T> getConstructor(Class<?>... parameterTypes)// 参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象
public void setAccessible(boolean flag)// 值为true则指示反射的对象在使用时应该取消Java语言访问检查。  暴力访问
package com.reflect;

import java.lang.reflect.Constructor;

public class ConstructorDemo {
	public static void main(String[] args) throws Exception {
		// 获取字节码文件对象
		Class c = Class.forName("com.reflect.Student");
		
		// 获取所有构造方法
		Constructor[] cons = c.getDeclaredConstructors();
		for (Constructor con : cons) {
			System.out.println(con);
		}

		// 获取单个构造方法
		Constructor con = c.getConstructor();// 返回的是构造方法对象
		Constructor con1 = c.getConstructor(String.class, int.class);// 返回的是有参构造方法对象
		Constructor con2 = c.getDeclaredConstructor(String.class);
		//创建对象 
		Object obj = con.newInstance();
		Object obj1=con1.newInstance("小米",12);
		// 暴力访问
		con2.setAccessible(true);// 值为true则指示反射的对象在使用时应该取消Java语言访问检查。
		Object obj2 = con2.newInstance("小白");
		
		System.out.println(obj.toString());
		System.out.println(obj1.toString());
		System.out.println(obj2.toString());
		
	}
}

运行结果:
在这里插入图片描述

反射获取成员变量

**类比上面Constructor类中的方法,这个类也有同样的方法,获取所有成员变量(返回数组),获取私有成员变量等 这里不再赘述 **

package com.reflect;

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

/*
 * 通过发生获取成员变量并使用
 */
public class FieldDemo {
	public static void main(String[] args) throws Exception {
		// 获取字节码文件对象
		Class c = Class.forName("com.reflect.Student");

		// 获取所有的成员变量
		 Field[] fields = c.getFields();
		 Field[] fields1 = c.getDeclaredFields();
		 for (Field field : fields1) {
		 System.out.println(field);
		 }

		/*
		 * Person p = new Person(); p.address = "北京"; System.out.println(p);
		 */

		// 通过无参构造方法创建对象
		Constructor con = c.getConstructor();
		Object obj = con.newInstance();
		System.out.println(obj);

		// 获取单个的成员变量
		//通过成员变量名
		Field nameField = c.getField("name");
		// public void set(Object obj,Object value)
		// 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
		nameField.set(obj, "小红"); // 给obj对象的addressField字段设置值为"北京"
		System.out.println(obj);

		// 获取age并对其赋值
		// NoSuchFieldException  私有变量
		Field ageField = c.getDeclaredField("age");
		// IllegalAccessException 暴力访问
		ageField.setAccessible(true);
		ageField.set(obj, 18);
		System.out.println(obj);

	}
}

运行结果:
在这里插入图片描述

反射获取成员方法

**类比上面Constructor类中的方法,这个类也有同样的方法,获取所有成员方法(返回数组),获取私有成员方法等 这里不再赘述 **

package com.reflect;

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

public class MethodDemo {
	public static void main(String[] args) throws Exception {
		// 获取字节码文件对象
		Class c = Class.forName("com.reflect.Student");

		// 获取所有的方法
		 Method[] methods = c.getMethods(); // 获取自己的包括继承父亲的公共方法
		 Method[] methods1 = c.getDeclaredMethods(); // 获取自己的所有的方法
		 for (Method method : methods1) {
		 System.out.println(method);
		 }

		Constructor con = c.getConstructor();
		Object obj = con.newInstance();
		
		// 获取单个方法并使用
		// public void show()
		// public Method getMethod(String name,Class<?>... parameterTypes)
		// 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型
		Method m1 = c.getMethod("study");
		// public Object invoke(Object obj,Object... args)
		// 返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数
		m1.invoke(obj); // 调用obj对象的m1方法

		System.out.println("----------");
		Method m2 = c.getDeclaredMethod("study", String.class);
		// NoSuchMethodException 访问私有方法  暴力访问
		m2.setAccessible(true);
		m2.invoke(obj, "数学");
	}
}

运行结果:
在这里插入图片描述

到这里,最基本的反射就完了,希望本文对你有帮助,关注支持一波,多多指正,谢谢哦

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值