反射机制的详细代码理解

原创 2017年01月03日 15:02:48

1.类的加载器以及如何获取Class的实例

public class TestReflection {
	
	//关于类的加载器:ClassLoader
	@Test
	public void test5() throws Exception{
		ClassLoader loader1 = ClassLoader.getSystemClassLoader();//获取系统类加载器
		System.out.println(loader1);
		
		ClassLoader loader2 = loader1.getParent();//获取扩展类加载器
		System.out.println(loader2);
		
		ClassLoader loader3 = loader2.getParent();//引导类加载器无法被获取
		System.out.println(loader3);
		
		Class class1 = Person.class;
		ClassLoader loader4 = class1.getClassLoader();
		System.out.println(loader4);
		
		String className = "java.lang.Object";
		Class class2 = Class.forName(className);
		ClassLoader loader5 = class2.getClassLoader();//引导类加载器无法被获取
		System.out.println(loader5);
		
		ClassLoader loader = this.getClass().getClassLoader();
		InputStream is = loader.getResourceAsStream("com\\panda\\java\\jdbc.properties");
		Properties pros = new Properties();
		pros.load(is);
		String name = pros.getProperty("user");
		System.out.println(name);
		
		String password = pros.getProperty("password");
		System.out.println(password);
	}
	
	//如何获取Class的实例(3种)
	@Test
	public void test4() throws ClassNotFoundException{
		//1.调用运行时类本身的.class属性
		Class class1 = Person.class;
		System.out.println(class1.getName());
		
		Class class2 = String.class;
		System.out.println(class2.getName());
		
		//2.通过运行时类的对象获取
		Person person = new Person();
		Class class3 = person.getClass();
		System.out.println(class3.getName());
		
		//3.通过Class的静态方法获取
		String className = "com.panda.java.Person";
		Class class4 = Class.forName(className);
		System.out.println(class4.getName());
		
		//4.通过类的加载器
		ClassLoader classLoader = this.getClass().getClassLoader();
		Class class5 = classLoader.loadClass(className);
		System.out.println(class5.getName());
		
	}
	
	/*
	 * java.lang.class:是反射的源头
	 * 我们创建了一个类,通过编译(javac.exe),生成对应的.class文件。之后我们使用java.exe加载(JVM的类加载器完成的)
	 * 此.class文件,此.class文件加载到内存以后,就是一个运行时类,存在在缓存区。那么这个运行时类本身就是一个Class的实例!
	 * 1.每一个运行时类只加载一次!
	 * 2.有了Class的实例以后,我们才可以进行如下的操作:
	 *     1)*创建对应的运行时类的对象
	 *     2)获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解、...)
	 *     3)*调用对应的运行时类的指定的结构(属性、方法、构造器)
	 *     4)反射的应用:动态代理
	 */
	@Test
	public void test3(){
		Person person = new Person();
		Class class1 = person.getClass();//通过运行时类的对象,调用其getClass(),返回其运行时类
		System.out.println(class1);
	}
	
	//有了反射,可以通过反射创建一个类的对象,并调用其中的结构
	@Test
	public void test2() throws Exception{
		Class class1 = Person.class;
		
		//1.创建class1对应的运行时类Person类的对象
		Person person = (Person) class1.newInstance();
		//2.通过反射调用运行时类的指定的属性
		Field f1 = class1.getField("name");
		f1.set(person, "liuDeHua");
		System.out.println(person);
		
		Field f2 = class1.getDeclaredField("age");
		f2.setAccessible(true);
		f2.set(person, 20);
		System.out.println(person);
		
		//3.通过反射调用运行时类的指定的方法
		Method m1 = class1.getMethod("show");
		m1.invoke(person);
		
		Method m2 = class1.getMethod("display", String.class);
		m2.invoke(person, "CHN");
	}
	//在有反射以前,如何创建一个类的对象,并调用其中的方法、属性
	@Test
	public void test1(){
		Person person = new Person();
		person.setAge(10);
		person.setName("liming");
		System.out.println(person);
		person.show();
		//person.display("中国");
	}
}
2.通过反射获取对应的运行时类的属性

public class TestField {
	//获取对应的运行时类的属性
	@Test
	public void test1(){
		Class class1 = Person.class;
		
		//1.getFields(),只能获取到运行时类中极其父类中声明为public的属性
		Field[] fields = class1.getFields();
		for (int i = 0; i < fields.length; i++) {
			System.out.println(fields[i]);
		}
		System.out.println();
		//2.getDeclaredFields(),获取运行时类本身声明的所有的属性
		Field[] fields2 = class1.getDeclaredFields();
		for(Field f : fields2){
			System.out.println(f.getName());
		}
	}
	/*
	 * 权限修饰符 变量类型 变量名
	 * 获取属性的各个部分的内容
	 */
	@Test
	public void test2(){
		Class class1 = Person.class;
		Field[] fields2 = class1.getDeclaredFields();
		for(Field f : fields2){
			//1.获取每个属性的权限修饰符
			int i = f.getModifiers();
			String str = Modifier.toString(i);
			System.out.print(str + " ");
			
			//2.获取属性的变量类型
			Class type = f.getType();
			System.out.print(type.getName() + " ");
			
			//3.获取属性名
			System.out.print(f.getName());
	
			System.out.println();
		}
	}
	
	//调用运行时类指定的属性
	@Test
	public void test3() throws Exception, SecurityException{
		Class class1 = Person.class;
		//1.获取指定的属性
		//getField(String fieldName):获取运行时类中声明为public的指定属性名为fieldName的属性
		Field name = class1.getField("name");
		//2.创建运行时类的对象
		Person person = (Person) class1.newInstance();
		//3.将运行时类的指定的属性赋值
		name.set(person, "Jack");
		System.out.println(person);
		
		System.out.println();
		//getDeclaredField(String fieldName):获取运行时类中指定属性名为fieldName的属性
		Field age = class1.getDeclaredField("age");
		//由于属性权限修饰的限制,为了保证可以给属性赋值,需要在操作前使得此属性可被操作
		age.setAccessible(true);
		age.set(person, 22);
		System.out.println(person);
	}
}

3.通过反射获取运行时类的方法

public class TestMethod {
	//1.获取运行时类的方法
	@Test
	public void test1(){
		Class class1 = Person.class;
		//1.getMethods(),获取运行时类及其父类中所有的声明为public的方法
		Method[] methods = class1.getMethods();
		for(Method m : methods){
			System.out.println(m);
		}
		System.out.println();
		
		//2.getDeclaredMethods(),获取运行时类本身声明的所有的方法
		Method[] methods2 = class1.getDeclaredMethods();
		for(Method m : methods2){
			System.out.println(m);
		}
	}
	
	
	//注解 权限修饰符 返回值类型 方法名 形参列表 异常
	@Test
	public void test2(){
		Class class1 = Person.class;
		
		Method[] methods2 = class1.getDeclaredMethods();
		for(Method m : methods2){
			//1.注解
			Annotation[] ann = m.getAnnotations();
			for(Annotation a : ann){
				System.out.println(a);
			}
			
			//2.权限修饰符
			String str = Modifier.toString(m.getModifiers());
			System.out.print(str + " ");
			
			//3.返回值类型
			Class returnType = m.getReturnType();
			System.out.print(returnType.getName() + " ");
			
			//4.方法名
			System.out.print(m.getName() + " ");
			
			//5.形参列表
			System.out.print("(");
			Class[] params = m.getParameterTypes();
			for(Class p : params){
				System.out.print(p.getName() + " ");
			}
			System.out.print(")");
			
			//6.异常类型
			Class[] exps = m.getExceptionTypes();
			for (int i = 0; i < exps.length; i++) {
				System.out.println(exps[i].getName());
			}
			System.out.println();
		}
	}
	//调用运行时类中的指定的方法
	@Test
	public void test3() throws Exception{
		Class class1 = Person.class;
		//getMethod(String methodName,Class ... params):获取运行时类中声明为public的指定的方法
		Method m1 = class1.getMethod("show");
		Person person = (Person) class1.newInstance();
		//调用指定的方法:Object invoke(Object obj,Object ... obj)
		Object returnVal = m1.invoke(person);//我是一个人
		System.out.println(returnVal);//null
		
		Method m2 = class1.getMethod("toString");
		Object returnVal1 = m2.invoke(person);
		System.out.println(returnVal1);//Person [name=null,age=0]
		
		//对于运行时类中静态方法的调用
		Method m3 = class1.getMethod("info");
		m3.invoke(Person.class);//中国人
		
		//getDeclaredMethod(String methodName,Class ... params):获取运行时类中声明了的指定的方法
		Method m4 = class1.getDeclaredMethod("display",String.class);
		m4.setAccessible(true);
		Object value = m4.invoke(person,"CHN");//我的国籍是:CHN
		
	}
}
4.通过反射调用指定的构造器

public class TestConstructor {
	@Test
	public void test1() throws Exception{
		String className = "com.panda.java.Person";
		Class class1 = Class.forName(className);
		
		//创建对应的运行时类的对象.使用newInstan(),实际上就是调用了运行时类的空参的构造器
		//要想能创建成功:1.要求对应的运行时类要有空参的构造器。2.构造器的权限修饰符的权限要足够
		Object object = class1.newInstance();
		Person person = (Person) object;
		System.out.println(person);
	}
	
	@Test
	public void test2() throws ClassNotFoundException{
		String className = "com.panda.java.Person";
		Class class1 = Class.forName(className);
		
		Constructor[] cons = class1.getDeclaredConstructors();
		
		for(Constructor constructor : cons){
			System.out.println(constructor);
		}
	}
	//调用指定的构造器,创建运行时类的对象
	@Test
	public void test3() throws Exception{
		String className = "com.panda.java.Person";
		Class class1 = Class.forName(className);
		Constructor constructor = class1.getDeclaredConstructor(String.class,int.class);
		constructor.setAccessible(true);
		Person person = (Person) constructor.newInstance("李明",21);
		System.out.println(person);
	}
} 
5.通过反射获取其他
public class TestOthers {
	//1.获取运行时类的父类
	@Test
	public void test1(){
		Class class1 = Person.class;
		Class supercClass = class1.getSuperclass();
		
		System.out.println(supercClass);
	}
	//2.获取带泛型的父类
	@Test
	public void test2(){
		Class class1 = Person.class;
		Type type = class1.getGenericSuperclass();
		
		System.out.println(type);
	}
	
	//3.获取父类的泛型
	@Test
	public void test3(){
		Class class1 = Person.class;
		Type type = class1.getGenericSuperclass();
		
		ParameterizedType pType = (ParameterizedType) type;
		Type[] ars = pType.getActualTypeArguments();
		System.out.println(((Class)ars[0]).getName());
	}
	
	//4.获取实现的接口
	@Test
	public void test4(){
		Class class1 = Person.class;
		Class[] interfaces = class1.getInterfaces();
		
		for(Class c : interfaces){
			System.out.println(c);
		}
	}
	
	//5.获取所在的包
	@Test
	public void test5(){
		Class class1 = Person.class;
		Package package1 = class1.getPackage();
		
		System.out.println(package1);
	}
	
	//6.获取注解
	@Test
	public void test6(){
		Class class1 = Person.class;
		Annotation[] anns = class1.getAnnotations();
		
		for(Annotation annotation : anns){
			System.out.println(annotation);
		}
	}
}
附录:

1.父类Creature

public class Creature<T> {
	public double weight;
	
	public void breath(){
		System.out.println("呼吸!");
	}
}

2.Person类

@MyAnnotation(value = "panda")
public class Person extends Creature<String> implements Comparable,MyInterface{

	public String name;
	private int age;
	int id;
	
	public Person() {
		super();
	}

	public Person(String name) {
		super();
		this.name = name;
	}

	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
	
	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 getId() {
		return id;
	}

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

	@MyAnnotation(value = "abc123")
	public void show(){
		System.out.println("我是一个人");
	}
	private void display(String nation)throws Exception{
		System.out.println("我的国籍是:" + nation);
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}

	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		return 0;
	}
	public static void info(){
		System.out.println("中国人!");
	}
	class Bird{
		
	}
}
3.注解类

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
	String value();
}
4.接口类
public interface MyInterface extends Serializable{

}
5.jdbc.properties文件
user=root
password=123456











java反射机制的理解

java反射机制:动态(运行时)获取类中的信息就是java反射,可以理解为对类的解剖。 反射机制主要提供的功能: 1)在运行时判断任意一个对象所属的类 2)在运行时构造任意一个类的对象 ...
  • u012586848
  • u012586848
  • 2015年09月26日 15:03
  • 483

对java反射机制的一些理解

1.什么是java的反射机制? 说实话,一开始的时候我真的不知道什么是java的反射机制,反射机制又有什么用呢?甚至于在刚开始的时候,我还觉得java反射机制真的麻烦,还不如平常的使用类以及其实例对...
  • YQYnsmile
  • YQYnsmile
  • 2016年08月14日 10:47
  • 2078

深入理解java反射机制

一,java的核心机制java有两种核心机制:java虚拟机(JavaVirtual Machine)与垃圾收集机制(Garbage collection): Java虚拟机:是运行所有Java...
  • u012585964
  • u012585964
  • 2016年07月24日 02:32
  • 7877

关于对反射机制的通俗理解

关于反射机制的理解,反射其实就是照镜子的过程,通过照镜子,镜子里的镜像 能获取你的属性和行为。 1. 首先要先有一个定义了自身的本体(Class A),里面必须有一个无参的构造函数 2. 所有的镜子...
  • qq_35699070
  • qq_35699070
  • 2017年10月24日 22:13
  • 123

全面说说反射机制

1 反射机制的基本概念         JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息...
  • caozhangyingfei0109
  • caozhangyingfei0109
  • 2015年08月30日 22:09
  • 600

Java 反射机制的理解

这两天把JAVA的反射机制看了一遍,回味真的很酸爽,应该说很痴迷和很敬佩JAVA设计者的睿智,太完美了,简直是对C++设计者的一种藐视(原理我的无知,我只是想表达下JAVA的反射有多么强大和完美)。首...
  • mantantan
  • mantantan
  • 2016年07月08日 11:17
  • 940

通俗易懂解释java反射机制(一)

Java的反射机制是Java特性之一,反射机制是构建框架技术的基础所在。灵活掌握Java反射机制,对大家以后学习框架技术有很大的帮助。     那么什么是Java的反射呢?        大家都知道,...
  • xiaohai798
  • xiaohai798
  • 2013年09月13日 13:48
  • 6125

【框架基础】:Java反射机制详解(一)

在学习框架设计之前,先来了解一下框架基础——Java反射机制。         一、什么是反射机制         反射机制是在程序运行状态时,对于任意一个类,都能够知道这个类的所有属性和方法;对...
  • erlian1992
  • erlian1992
  • 2016年11月29日 15:13
  • 1463

理解C#反射机制

反射是.NET中的重要机制,通过反射可以得到*.exe或*.dll等程序集内部的接口、类、方法、字段、属性、特性等信息,还可以动态创建出类型实例并执行其中的方法。...
  • xiaouncle
  • xiaouncle
  • 2016年11月01日 13:12
  • 2029

java反射机制代码

今天,自己特意复习了一下java的反射机制,对一个类中的属性、方法及构造方法通过反射机制进行操作,关于反射机制的一些概念就不多说了,大家可以看我以前的java基础博客进行了解,下面的都是一些代码: ...
  • HarderXin
  • HarderXin
  • 2014年04月09日 17:07
  • 2195
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:反射机制的详细代码理解
举报原因:
原因补充:

(最多只允许输入30个字)