java基础学习之反射 十六

反射 是在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方法;对于任意一个对象,都只能都调用它的任意一个
方法和属性,这种动态获取的信息一级动态调用对象的方法的功能呢个称为java 的反射机制。



反射其实就是动态加载一个指定的类,并获取该类中的所有的内容。而且将字节码文件封装成对象,
并将字节码文件中的内容都封装成对象,这样便于操作这些成员。就是把JAVA类中的各种成分反射成为相应的JAVA类
简单说:反射技术可以对一个类进行解剖。


如果想要对指定名称的字节码文件进行加载


反射的好处:大大的增强了程序的扩展性。 
反射的基本步骤: 
1、获得Class对象,就是获取到指定的名称的字节码文件对象。 
2、实例化对象,获得类的属性、方法或构造函数。 
3、访问属性、调用方法、调用构造函数创建对象。


得到类的字节码文件相同,这三种方式。
1.Class cls1=类名.class 相对简单,还是需要明确类名
2.cls1.getclass();必须要明确具体的类,并创建对象

3.class.forName("完整的类名(带包名)");



person类

package fanshe;

public class person {
	public String name;
	private int age;
	public person() {
		// TODO Auto-generated constructor stub
	}
	private person(String name){
		this.name = name;
	}
	public person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	public void show(){
		System.out.println("show");
	}
	public void function(String s){
		System.out.println("function"+s);
	}
	public String returnValue(String name, int age){
		return"hello"+name+"**********"+age;
	}
	private void hello(){
		System.out.println("helloworld");
	}
	@Override
	public String toString() {
		return "person [name=" + name + ", age=" + age + "]";
	}
	
}


得到类的字节码文件测试demo;

package fanshe;
/**
 * @author Angus
 *	反射;通过Class文件对象,去使用构造方法,成员变量,成员方法
 *	
 *	怎么得到Class文件对象?
 *	A:Object对象的getClass方法
 *	B:数据类型静态的class属性
 *	C;类 Class的forName(String className)  返回与带有给定字符串名的类或接口相关联的 Class 对象。
 */
public class ReflectDemo {

	public static void main(String[] args) throws ClassNotFoundException {
		//方式一
		person p = new person();
		Class c = p.getClass();
		
		person p2 = new person();
		Class c2 = p.getClass();
		
		System.out.println(p == p2); //false
		System.out.println(c == c2); //true   字节码文件只能是一个
	
		//方式二
		Class c3 = person.class;
		System.out.println(c==c3); //true
		
		//方式三
		Class c4 = Class.forName("fanshe.person");//路径
		System.out.println(c==c4); //true
	}

}

反射获取构造方法并使用

package fanshe;

import java.lang.reflect.Constructor;

/**
 * @author Angus
 *	反射获取构造方法并使用
 *
 *	构造方法:Constructor 
 *	成员变量:Field
 *	成员方法:Method
 */
public class ReflectDemo2 {

	public static void main(String[] args) throws ClassNotFoundException {
		Class c = Class.forName("fanshe.person");
		//public Constructor<?>[] getConstructors()
		//返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法sss
		Constructor[] constructors = c.getConstructors();
		for (Constructor constructor : constructors) {
			System.out.println(constructor);
		}
		System.out.println("------------------------------");
		//getDeclaredClasses这些对象反映声明为此 Class 对象所表示的类的成员的所有类和接口
		Constructor[] declaredConstructors = c.getDeclaredConstructors();
		for (Constructor constructor : declaredConstructors) {
			System.out.println(constructor);
		}
	}

}

可变参数的使用:

package fanshe;
/**
 * 
 * @author Angus
 *	
 *	可变参数
 *		格式:
 *		修饰符  返回值类型 方法名(数据类型... 变量)
 *		{
 *	
 *		}
 *	注意:变量其实为一个数据
 *		如果你的方法需要可变参数的数据最好定义在末尾
 *
 */
public class ArgsDemo {

	public static void main(String[] args) {
		int a = 10;
		int b = 20;
		int c = 30;
		System.out.println(sum1(a,b));
		System.out.println(sum2(a,b,c));
		//......多个数求和呢?
		int d = 40;
		System.out.println(sun3(a,b,c,d));
		System.out.println(sun4(a,b,c,d));
	}
	
	/*
	 * 两个数就和
	 */
	private static int sum1(int a, int b) {
		return a+b;
	}
	private static int sum2(int a, int b, int c) {
		// TODO Auto-generated method stub
		return a+b+c;
	}
	/**
	 * 可变参数的使用
	 * @param x
	 * @return
	 */
	private static int sun3(int... x){
		int result = 0;
		for(int i :x){
			result += i;
		}
		return result;
	}
	/**
	 * 第一个参数传递给y  剩下的封装数据给x  
	 * 如果int y写到x后边会报错,应为数据全部封装成数据给力x。。。
	 * @param y
	 * @param x
	 * @return
	 */
	private static int sun4(int y ,int... x){
		int result = 0;
		for(int i :x){
			result += i;
		}
		return result;
	}

}

getConstructor方法使用;

package fanshe;

import java.lang.reflect.Constructor;

/**
 * @author Angus
 *	反射获取构造方法并使用
 *
 *	构造方法:Constructor 
 *	成员变量:Field
 *	成员方法:Method
 */
public class ReflectDemo2 {

	public static void main(String[] args) throws Exception {
		Class c = Class.forName("fanshe.person");
		//public Constructor<?>[] getConstructors()
		//返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法sss
		Constructor[] constructors = c.getConstructors();
		for (Constructor constructor : constructors) {
			System.out.println(constructor);
		}
		System.out.println("------------------------------");
		
		//getDeclaredClasses这些对象反映声明为此 Class 对象所表示的类的成员的所有类和接口
		Constructor[] declaredConstructors = c.getDeclaredConstructors();
		for (Constructor constructor : declaredConstructors) {
			System.out.println(constructor);
		}
		System.out.println("------------------------------");
		
		//public Constructor<T> getConstructor(Class<?>... parameterTypes)
		Constructor con = c.getConstructor();
		//通过构造对象创建对象
		//public T newInstance(Object... initargs)
		Object newInstance = con.newInstance();
		System.out.println(newInstance); //person [name=null, age=0]
	}

}


效果;



获取带参构造并使用

package fanshe;

import java.lang.reflect.Constructor;

/**
 * @author Angus
 *	获取带参构造并使用
 *
 */
public class ReflectDemo2 {

	public static void main(String[] args) throws Exception {
		//获取字节码文件对象
		Class c = Class.forName("fanshe.person");
		
		//获取构造器对象
//		Class[] calsses = new Class[2];
//		calsses[0] = String.class;
//		calsses[1] = int.class;
//		Constructor con = c.getConstructor(calsses);
		//改进
//		Constructor com = c.getConstructor(new Class[]{String.class,int.class});
		
		//最终
		Constructor con = c.getConstructor(String.class,int.class);
		
		//创建对象
		Object newInstance = con.newInstance("Angus",26);
		
		System.out.println(newInstance);
		//输出结果:person [name=Angus, age=26]
	}

}

获取公共成员变量并使用

package fanshe;

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

/**
 * @author Angus
 *	获取公共成员变量并使用
 *	getFields 获取公共的成员变量
 */
public class ReflectDemo2 {

	public static void main(String[] args) throws Exception {
		//获取字节码文件对象
		Class c = Class.forName("fanshe.person");
		
		//获取公共成员变量对象
//		Field[] fields = c.getFields();  //
//		for (Field field : fields) {
//			System.out.println(field);
//			//public java.lang.String fanshe.person.name
//		}
//		System.out.println("---------------------------------");
//		//获取所有的成员比那里
//		Field[] declaredFields = c.getDeclaredFields();
//		for (Field field : declaredFields) {
//			System.out.println(field);
//		}
		System.out.println("---------------------------------");
		
		Constructor con = c.getConstructor();
		Object obj = con.newInstance();
		//获取一个成员变量
		//public void set(Object obj,Object value)

		Field field = c.getField("name");  //只能公共的对象
		field.set(obj, "Angus");
		System.out.println(obj);
		//person [name=Angus, age=0]

	}

}






获取私有成员变量并使用

package fanshe;

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

/**
 * @author Angus
 *	获取私有成员变量并使用
 *	getFields 获取公共的成员变量
 *
 *	public static void setAccessible(AccessibleObject[] array,boolean flag)
 *	使用单一安全性检查(为了提高效率)为一组对象设置 accessible 标志的便捷方法。 
 */
public class ReflectDemo2 {

	public static void main(String[] args) throws Exception {
		//获取字节码文件对象
		Class c = Class.forName("fanshe.person");
		
		//创建对象
		Constructor con = c.getConstructor();
		Object obj = con.newInstance();
		
		//赋值
		Field field = c.getField("name"); //私有的会报错
		field.set(obj, "Angus");
		
		Field declaredField = c.getDeclaredField("age");
		declaredField.setAccessible(true);//设置私有可访问
		declaredField.set(obj, 26);
		
		System.out.println(obj);
		//person [name=Angus, age=26]
	}

}






获取成员方法并使用

package fanshe;

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

/**
 * @author Angus
 * 获取成员方法并使用
 * public Object invoke(Object obj, Object... args)
 * 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
 */
public class ReflectDemo2 {

	public static void main(String[] args) throws Exception {
		//获取字节码文件对象
		Class c = Class.forName("fanshe.person");
		
		//创建对象
		Constructor con = c.getConstructor();
		Object obj = con.newInstance();
		
		//获取方法
		//所有公共方法,包括父亲的
		Method[] methods = c.getMethods(); 
		for (Method method : methods) {
//			System.out.println(method);
		}
		//获取本类的所有方法
		Method[] declaredMethods = c.getDeclaredMethods();
		for (Method method : declaredMethods) {
//			System.out.println(method);
		}
		//无参无返回值
		Method method1 = c.getMethod("show", null);
		method1.invoke(obj, null);
		System.out.println("--------------------------");
		
		//带参数无返回值
		Method method2 = c.getMethod("function", String.class);
		method2.invoke(obj, "Angus");
		System.out.println("--------------------------");
		
		//带多个参数有返回值
		Method method3 = c.getMethod("returnValue", String.class,int.class);
		Object invoke = method3.invoke(obj, "Angus",26);
		System.out.println(invoke);
		System.out.println("--------------------------");
		
		//私有方法的调用
		Method m4 = c.getDeclaredMethod("hello", null);
		m4.setAccessible(true);
		m4.invoke(obj, null);
	}

}






结果:



反射运行配置文件中的内容

package fanshe;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * @author Angus
 *	反射运行配置文件中的内容
 */
public class Test {

	public static void main(String[] args) throws Exception {
		Properties prop = new Properties();
		FileReader fr = new FileReader("test.properties");
		
		prop.load(fr);
		fr.close();
		
		//获取类名
		String className = prop.getProperty("className");
		//获取方法名
		String methodName = prop.getProperty("methodName");
		
		//获取字节码对象
		Class c = Class.forName(className);
		
		Constructor con = c.getConstructor();
		Object obj = con.newInstance();
		
		Method m = c.getMethod(methodName, null);
		m.invoke(obj, null);
	}

}







配置文件:


Student类


这样若果获取别的类的方法属性信息,可以直接修改属性文件了。。。。


反射滤过泛型检测。。。

有一个ArrayList<Integer>对象,在集合中添加一个字符串数据,如何实现。。。。

package fanshe;

import java.lang.reflect.Method;
import java.util.ArrayList;

/**
 * @author Angus
 *	有一个ArrayList<Integer>对象,在集合中添加一个字符串数据,如何实现。。。。
 */
public class ArrayListTest {

	public static void main(String[] args) throws Exception{
		ArrayList<Integer> array = new ArrayList<>();
		
		//获取字节码问价你对象
		Class c = array.getClass();
		Method m = c.getMethod("add", Object.class);
		m.invoke(array, "hello");
		m.invoke(array, "world");
		m.invoke(array, "java");
		
		System.out.println(array);
	
	}

}

结果:



最后附上JDK使用文档API 下载





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值