反射应用总结

反射总结
反射概念

反射机制是在【运行状态中】:

  • 对于一个类,能够知道这个类的所有属性和方法;
  • 对于一个对象,能够调用这个对象的所有属性和方法。
反射提供的功能
  • 在运行时判断任意一个对象所属的类;
  • 在运行时构造任意一个类的对象;
  • 在运行时能够判断任意一个类所具有的的成员变量和方法;
  • 在运行时能够调用任意一个对象的方法;
  • 生成动态代理。
获取反射对象的三种方法
  • 第一种获取反射对象的方法:Class.forName(全限定类名);
  • 第二种获取反射对象的方法:类名.class;
  • 第三种获取反射对象的方法:对象.getClass()。
  • 接口代码演示:
package org.dsl.reflectdome;

public interface MyInterface {
	public void interfaceMethod();

}

  • 对象类代码演示:
package org.dsl.reflectdome;

public class People implements MyInterface {
	private String name;
	private int age;
	public int sex;

	public People() {

	}

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

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

	public static void staticMethod() {
		System.out.println("staticMethod.....");
	}
	public void staticMethod2() {
		System.out.println("staticMethod2.....");
	}

	private void testMethod() {
		System.out.println("testMethod......");
	}

	@Override
	public void interfaceMethod() {
		// TODO Auto-generated method stub

	}

	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 int getSex() {
		return sex;
	}

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

}

  • 测试类代码演示:
package org.dsl.reflectdome;

public class ReflectDome {
	public static void main(String[] args) {
		try {
			//第一种获取反射对象的方法:Class.forName(全限定类名)
			Class<?> perClass = Class.forName("org.dsl.reflectdome.People");
			System.out.println("first:"+perClass);
			//第二种获取反射对象的方法:类名.class
			Class<?> perClass2 = People.class;
			System.out.println("second:"+perClass2);
			//第三种获取反射对象的方法:对象.getClass()
			People people = new People();
			Class<?> perClass3 = people.getClass();
			System.out.println("third:"+perClass3);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

  • 运行结果:
first:class org.dsl.reflectdome.People
second:class org.dsl.reflectdome.People
third:class org.dsl.reflectdome.People
通过反射获取类的属性、方法,并创建对象
获取方法
  • 获取所有公共方法,包括本类、父类、接口中的所有方法,符合访问修饰符规律(public)使用getMethods();
  • 获取本类所有方法,只有本类方法,不包含父类,并且突破修饰符限定使用getDeclaredMethods();
  • 通过反射,查看本类中的所有构造方法使用getConstructors()
获取接口
  • 通过反射,查看本类实现的所有接口使用getInterfaces();
获取父类
  • 通过反射,查看本类继承的父类使用getSuperclass()
获取属性
  • 通过反射,查看本类和父类中的所有公共属性使用getFields();
  • 获取本类(不包含父类)中所有属性,并且突破修饰符限定,私有也可获取到使用getDeclaredFields();
创建对象并调用公共对象方法
  • 通过反射,创建类的对象并调用对象中公共的方法使用newInstance();
代码演示:
package org.dsl.reflectdome;

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

public class ReflectDome2 {
	public static void dome01() {
		try {
			Class<?> perClass = Class.forName("org.dsl.reflectdome.People");
			System.out.println("dome01获取所有公共方法:");
			// 获取所有公共方法,包括本类、父类、接口中的所有方法,符合访问修饰符规律(public)
			Method[] methods = perClass.getMethods();
			for (Method method : methods) {
				System.out.println(method);
			}
			System.out.println("dome01获取本类所有方法:");
			// 获取本类所有方法,只有本类方法,不包含父类,并且突破修饰符限定
			Method[] methods2 = perClass.getDeclaredMethods();
			for (Method method : methods2) {
				System.out.println(method);
			}
  
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	// 通过反射,查看本类实现的所有接口
	public static void dome02() {
		try {
			Class<?> perClass = Class.forName("org.dsl.reflectdome.People");
			Class<?>[] intes = perClass.getInterfaces();
			for (Class inte : intes) {
				System.out.println("dome02People中实现的接口:\n" + inte);
			}
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	// 通过反射,查看本类继承的父类
	public static void dome03() {
		try {
			Class<?> perClass = Class.forName("org.dsl.reflectdome.People");
			Class<?> superclass = perClass.getSuperclass();

			System.out.println("dome03..People中继承的父类:\n" + superclass);

		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


	// 通过反射,查看本类中的所有构造方法
	public static void dome04() {
		try {
			Class<?> perClass = Class.forName("org.dsl.reflectdome.People");
			Constructor<?>[] constructors = perClass.getConstructors();
			System.out.println("dome04..People类中的所有构造方法:");
			for (Constructor con : constructors) {
				System.out.println(con);
			}
			
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	// 通过反射,查看本类和父类中的所有公共属性
	public static void dome05() {
		try {
			Class<?> perClass = Class.forName("org.dsl.reflectdome.People");
			Field[] fields = perClass.getFields();
			System.out.println("dome05获取所有公共属性:");
			for (Field con : fields) {
				System.out.println(con);
			}
			//获取本类(不包含父类)中所有属性,并且突破修饰符限定,私有也可获取到
			Field[] fields2 = perClass.getDeclaredFields();
			System.out.println("dome05获取本类所有属性:");
			for (Field con : fields2) {
				System.out.println(con);
			}
			
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	// 通过反射,创建类的对象并调用对象中的方法
	public static void dome06() {
		
			try {
				Class<?> perClass = Class.forName("org.dsl.reflectdome.People");
				System.out.println("dome06创建对象并调用方法:");
				People per = (People)perClass.newInstance();
				per.staticMethod();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
	}
	public static void main(String[] args) {
		dome01();
		dome02();
		dome03();
		dome04();
		dome05();
		dome06();
	}

}

结果演示:
dome01获取所有公共方法:
public java.lang.String org.dsl.reflectdome.People.getName()
public void org.dsl.reflectdome.People.setName(java.lang.String)
public void org.dsl.reflectdome.People.staticMethod2()
public static void org.dsl.reflectdome.People.staticMethod()
public int org.dsl.reflectdome.People.getAge()
public int org.dsl.reflectdome.People.getSex()
public void org.dsl.reflectdome.People.interfaceMethod()
public void org.dsl.reflectdome.People.setAge(int)
public void org.dsl.reflectdome.People.setSex(int)
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
dome01获取本类所有方法:
public java.lang.String org.dsl.reflectdome.People.getName()
public void org.dsl.reflectdome.People.setName(java.lang.String)
private void org.dsl.reflectdome.People.testMethod()
public void org.dsl.reflectdome.People.staticMethod2()
public static void org.dsl.reflectdome.People.staticMethod()
public int org.dsl.reflectdome.People.getAge()
public int org.dsl.reflectdome.People.getSex()
public void org.dsl.reflectdome.People.interfaceMethod()
public void org.dsl.reflectdome.People.setAge(int)
public void org.dsl.reflectdome.People.setSex(int)
dome02People中实现的接口:
interface org.dsl.reflectdome.MyInterface
dome03..People中继承的父类:
class java.lang.Object
dome04..People类中的所有构造方法:
public org.dsl.reflectdome.People(java.lang.String,int,int)
public org.dsl.reflectdome.People(java.lang.String,int)
public org.dsl.reflectdome.People()
dome05获取所有公共属性:
public int org.dsl.reflectdome.People.sex
dome05获取本类所有属性:
private java.lang.String org.dsl.reflectdome.People.name
private int org.dsl.reflectdome.People.age
public int org.dsl.reflectdome.People.sex
dome06创建对象并调用方法:
staticMethod.....

通过反射操作类中属性和方法
操作属性
  • 创建反射对象,利用反射对象中newInstance()方法,创建类的对象,再利用类的对象的set方法和get方法,进行属性的赋值和查看;
  • 创建反射对象,利用反射对象获取类中的属性对象,再利用反射对象创建类的对象,最后利用属性对象的set方法将值赋给相应对象的相应属性,例如:nameField.set(person, “zs”),如果值为空可以赋值为null。
操作方法
  • 通过反射操作类中的方法,与操作属性同理,不同点是方法要使用invoke()进行调用,例如:method.invoke(person, “zs”),如果方法参数为空,可以使用null,method.invoke(person, null")。
  • 通过反射操作构造方法进行对象创建,与普通方法无异,需要注意有参构造中的参数是与类中的有参构造一一对应的,如果类中的有参构造是基本类型(例如:int,short,char),则通过反射获取的构造方法中的参数就是int.class,short.class,char.class;如果如果类中的有参构造是封装类型(Integer,Short、Character),则通过反射获取的构造方法中的参数就是Integer.class,Short.class、Character.class,基本类型和封装类型在这里是不一样的,另访问private私有构造时,也是需要将setAccessible赋值为true。
特别注意
  • 在访问私有的属性或方法时,要将setAccessible赋值为true,作用是屏蔽访问修饰符的作用,使外部可以进行赋值或调用。
  • 如果不将setAccessible赋值为true,则会报如下错误:
java.lang.IllegalAccessException: Class indi.dsl.reflectDome.MyReflect can not access a member of class indi.dsl.reflectDome.Person with modifiers "private"
代码演示:
package indi.dsl.reflectDome;

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

public class MyReflect {
	public static void dome01() {
		// 通过反射创建对象,通过对象给对象属性赋值(先创建对象,再赋值属性)
		try {
			Class<?> perClass = Class.forName("indi.dsl.reflectDome.Person");
			Person person = (Person) perClass.newInstance();
			person.setId(1);
			person.setAge(20);
			person.setName("zs");
			System.out.println("id:" + person.getId() + "\nage:"
					+ person.getAge() + "\nname:" + person.getName());
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public static void dome02() {
		// 通过反射直接获取类的具体属性,将属性赋值给对象(先获取属性,再给对象同属性赋值)
		try {
			Class<?> perClass = Class.forName("indi.dsl.reflectDome.Person");
			Field nameField = perClass.getDeclaredField("name");
			Person person = (Person) perClass.newInstance();
			// 屏蔽修饰符影像,使私有属性能够进行外部赋值
			nameField.setAccessible(true);
			nameField.set(person, "zs");
			System.out.println("name:" + person.getName());
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void dome03() {
		// 通过反射获取类中的方法,再创建对象进行方法调用
		try {
			Class<?> perClass = Class.forName("indi.dsl.reflectDome.Person");
			Method method = perClass.getDeclaredMethod("testMethod",
					String.class);
			// 屏蔽修饰符影像,使私有方法能够进行外部调用
			method.setAccessible(true);
			Person person = (Person) perClass.newInstance();
			method.invoke(person, "zs");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void dome04() {
		try {
			Class<?> perClass = Class.forName("indi.dsl.reflectDome.Person");
			// 获取无参公共构造方法进行对象创建
			Constructor<?> con = perClass.getConstructor();
			Person person = (Person) con.newInstance();
			System.out.println("无参公共构造:" + person);
			// 获取有参公共构造方法进行对象创建
			Constructor<?> con2 = perClass.getConstructor(int.class);
			Person person2 = (Person) con2.newInstance(12);
			System.out.println("有参公共构造:" + person2);
			// 获取有参私有构造方法进行对象创建
			Constructor<?> con3 = perClass.getDeclaredConstructor(String.class);
			con3.setAccessible(true);
			Person person3 = (Person) con3.newInstance("zs");
			System.out.println("有参私有构造:" + person3);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public static void main(String[] args) {
		dome01();
		dome02();
		dome03();
		dome04();
	}

}


结果展示:
id:1
age:20
name:zs
name:zs
testMethod...zs
无参公共构造:indi.dsl.reflectDome.Person@ca0b6
有参公共构造:indi.dsl.reflectDome.Person@10b30a7
有参私有构造:indi.dsl.reflectDome.Person@1a758cb

通过反射动态获取类和方法
动态加载类和方法
  • 先在项目路径下创建配置文件,名字随意即可,本次创建文件class.txt,其中key=classname,value=reflectdome.Person为类的限定类名,key=method,value=testMethod为要访问的方法名。
  • 通过Properties类的对象,将class.txt文件读到内存,然后通过key值获取value值,最后通过创建类的反射对象来访问类的方法。
利用反射绕过泛型检查
  • 原理:泛型(int,char,string)的检查是在代码的编译期进行的,而反射是在代码的运行期执行的,事实上泛型的在运行时全都是Object类型,所以利用反射可以将参数的泛型检查“绕过去”。
classname=reflectdome.Person
method=testMethod
  • 要访问的类的代码:
package reflectdome;

public class Person {
	private int id;
	private int age;
	private String name;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public int getAge() {
		return age;
	}

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

	public String getName() {
		return name;
	}

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

	public Person() {

	}

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

	}
	public static void testMethod() {
		System.out.println("testMethod...");
	}

}

  • 测试代码演示:
package reflectdome;

import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Properties;

public class MyReflectDome {
	// 动态加载类名和方法
	public static void dome01() {

		try {
			// 加载配置文件
			Properties pro = new Properties();
			pro.load(new FileReader("class.txt"));
			// 获取配置文件中信息,通过key=classname,获取value=reflectdome.Person
			String classname = pro.getProperty("classname");
			// 获取类的反射对象
			Class<?> perClass = Class.forName(classname);
			// 获取配置文件中信息,通过key=method,获取value=testMethod
			String methodValue = pro.getProperty("method");
			// 利用反射对象获取类中方法
			Method method = perClass.getMethod(methodValue, null);
			method.invoke(perClass.newInstance());

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	// 利用反射绕过泛型检查
	public static void dome02() {
		try {
			ArrayList<Integer> list = new ArrayList<Integer>();
			list.add(1);
			list.add(2);
			list.add(3);
			System.out.println(list);
			Class<?> perClass = list.getClass();
			Method method = perClass.getMethod("add", Object.class);
			method.invoke(list, "zs...");
			System.out.println(list);
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		dome01();
		dome02();
	}

}

  • 测试结果:
dome01演示结果:
testMethod...
dome02演示结果:
[1, 2, 3]
[1, 2, 3, zs...]
利用反射创建一维和二维数组
  • 利用反射创建一维数组和二维数组必须要指定数组的数据类型(类型为Class,例如:Integer.class)和数组长度,利用Array类中newInstance()方法创建数组对象,此处为对象,并不是真正的数组,所以取值时不能使用遍历取值,要使用Array.get(取值的数组对象,数组索引)。
  • 特别注意,创建二维数组或者是多维数组时,要先定义一维数组,例如:int[] dim={2,3},二维数组的类型依然是class类型,数组的维度和长度由所定义的一维数组决定,如果将所定义的dim传入,则定义一个2行3列的二维数组;int[] dim={2,3,4},此时如果将所定义的dim传入,则定义了一个x=2,y=3,z=4的三维数组,以此类推。。。。
  • 代码演示:
package indi.dsl.reflectDome;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import indi.dsl.reflectDome.Person;

public class MyReflect {
	public static void dome05() {
		// 利用反射定义一个一维数组
		Class c = Integer.TYPE;
		Object array = Array.newInstance(c, 5);
		Array.set(array, 2, 5);
		System.out.println(Array.get(array, 2));

	}
	
	public static void dome06(){
		//利用反射创建二维数组
		Class c = Integer.TYPE;
		int dim[] = {2,3};
		Object array = Array.newInstance(c, dim);
		Object ary = Array.get(array, 0);
		Array.set(ary, 2, 369);
		System.out.println(Array.get(ary, 2));
		
	}

	public static void main(String[] args) {
		// dome01();
		// dome02();
		// dome03();
		// dome04();
		dome05();
		dome06();
	}

}

  • 结果演示:
一维数组:5
二维数组:369
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值