Java反射整理

简介:        无论是在C#还是Java(平常常玩儿的就这俩,所以这么举例,别的语言也雷同!),为了获取类的灵活性,我们会时常使用反射,将类的信息写入配置,通过运行时候动态获取类,类的方法,字段,等等。


    

   无论是在C#还是Java(平常常玩儿的就这俩,所以这么举例,别的语言也雷同!),为了获取类的灵活性,我们会时常使用反射,将类的信息写入配置,通过运行时候动态获取类,类的方法,字段,等等。


     在Java中,我们通常是一个思路来动态访问类信息的,先获取类的Class 类,这个Class指明了是哪个类,然后通过获取到的Class get各种类信息。


一,获取Class类


     
public class ClassDemo1 {
	
	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
		//Foo的实例对象如何表示
		Foo foo1=new Foo();//foo1就表示出来了
		//Foo这个类 也是一个实例对象,Class类的实例对象如何表示
		//任何一个类都是Class类的实例对象,这个实例对象有3中表示方式
		
		/*第一种表示方式--》实际在告诉我们任何一个类都有一个隐含的静态成员变量*/
		Class c1=Foo.class;
		
		/*第二种表达方式:已知该类的对象,通过getClass方法*/
		Class c2=foo1.getClass();
		
		/*官网:c1/c2表示了Foo类的类类型(class type)
		 * 类也是对象,是class类的实例对象
		 * 这个对象我们成为该类的类类型
		 * */
		
		/*不管c1 or c2都代表了Foo类的类类型,一个类只可能是Class类的一个对象*/
		System.out.println(c1==c2);//true
		
		//第三种表达方式
		Class c3=null;
		c3=Class.forName("ShuiTian.NaiLuo.Reflect.Foo");
		System.out.println(c3);
		
		/*我们完全可以通过类的类类型创建该类的对象
		 * 通过c1 or c2 or c3创建父的实例
		 * 
		 * */
		Foo foo=(Foo)c1.newInstance();//使用newInstance需要有无参数的构造方法		
	}
}

class Foo{}


       主要有上面三种方式:第一种通过类的静态变量获取;第二种通过实例的getClass方法获取,第三种通过一个字符串来动态加载;仔细观察这三种方式,感觉最后一种用的还是比较多的,比如为数据库加载驱动的时候,配置Spring的时候,这种方式使得类的装配更具有灵活性。例如,我们可以使用这种方式在运行时候动态加载类:

   
public class DynamicLoadClass {

	public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException{
		String animalName="Cat";
		Animal animal = null;
		switch (animalName){
		case "Cat":
			animal=(Animal)Class.forName("ShuiTian.NaiLuo.Reflect.Cat").newInstance();
			break;
		case "Dog":
			animal=(Animal)Class.forName("ShuiTian.NaiLuo.Reflect.Dog").newInstance();
			break;
		}
		System.out.println(animal);
		System.out.println(animal.getClass().getSimpleName());
	}
}

interface Animal{}
class Cat implements Animal{}
class Dog implements Animal{}

 

 二,获取类信息


              当我们使用各种方法获取到类class之后,就可以使用这个class访问类的信息了。

       1,获取类的方法信息


                      
/*
	 * 打印类的信息,包括类的成员函数,类的成员变量 参数是一个对象,该对象的所属信息
	 */
	public static void printClassMethodMessage(Object obj) {
		// 要获取类的信息,首先要获取类的类类型 class type
		Class c = obj.getClass();// 传递的是哪个子类的对象
		// 获取类的名称
		System.out.println(c.getName());
		/*
		 * Method类是方法对象 一个成员方法就是一个Method对象 getMethods获取的是所有的public函数,包括从父类继承而来的
		 * c.getDeclaredMethods()获取的是所有该类声明的方法,不问访问权限
		 */
		Method[] ms = c.getMethods();  //获取类的方法数组
		for (Method method : ms) { //对类的方法数组进行循环,在循环中获取函数返回值信息及参数信息,也可以对方法进行动态调用
			// 得到方法的返回值类型的类类型
			Class returnType = method.getReturnType();
			System.out.print(returnType.getName() + "(");
			// 得到方法的名称
			System.out.print(method.getName());
			// 获取方法的参数类型--->得到的是参数列表的类型的类类型
			Class[] paramTypes = method.getParameterTypes();
			for (Class c1 : paramTypes) {
				System.out.print(c1.getName() + ",");
			}
			System.out.println(")");
		}

		printFieldMessage(obj);

	}


       2,获取类的成员变量的信息


                  
/*获取类的field信息*/
	public static void printFieldMessage(Object obj) {
		Class c=obj.getClass();
		/*
		 * 成员变量也是对象 java.lang.reflect.field Field类封装了关于成员变量的操作
		 * getFields方法获取的是所有public成员变量的信息 getDeclaredFields获取的是该类自己声明的成员
		 */
		Field[] fs = c.getDeclaredFields();
		for (Field field : fs) {
			/* 得到成员变量的类类类型 */
			Class fieldType = field.getType();
			String typeName = fieldType.getName();

			/* 得到成员变量的名称 */
			String fieldName = field.getName();
			System.out.println(fieldType + "," + fieldName);
		}
	}

        

      3,获取对象的构造函数的信息


              
/*打印对象的构造函数的信息*/
	public static void printConMessage(Object obj){
		Class c=obj.getClass();
		/*
		 * java.lang.constructors封装了构造函数的信息
		 * getConstructors()获取了所有的public的构造函数的信息
		 * getDeclaredConstructors:得到了自己声明的构造函数
		 * */
		Constructor[] cs =c.getDeclaredConstructors(); //获取构造函数数组
		for(Constructor con :cs ){  //分别对各个构造函数进行遍历
			System.out.print(con.getName()+"(");
			//获取构造函数的参数列表----得到的是参数列表的类类型
			Class[] paramTypes=con.getParameterTypes();  //得到构造函数的参数列表
			for(Class param:paramTypes){
				System.out.print(param.getName()+",");
			}
			System.out.println(")");
		}
	}


      4,通过反射动态调用方法

             
/*
 * 测试方法的反射
 * 
 * */
public class MethodDemo1 {
	public static void main(String[] args) throws InstantiationException,
			IllegalAccessException, ClassNotFoundException,
			NoSuchMethodException, SecurityException, IllegalArgumentException,
			InvocationTargetException {

		// 获取print(int,int)方法
		Class a = Class.forName("ShuiTian.NaiLuo.Reflect.A");
		/*
		 * 获取方法名称,参数列表。。。 getMethod:获取的是public的方法 getDeclaredMethod:获得的是自己声明的方法
		 */
		Method m = a.getMethod("print", new Class[] { int.class, int.class });
		/*
		 * 方法的反射操作 使用m对象来进行方法的调用 方法返回值问题 1,无返回值返回null 2,有返回值,返回具体值
		 */
		m.invoke(a.newInstance(), 10, 10);
		// m.invoke(a,10,10);
		System.out.println("==========分割线============");
		Method m2 = a.getMethod("print", String.class, String.class);
		m2.invoke(a.newInstance(), "lhc", "水田");
	}
}

class A {
	public void print(int a, int b) {
		System.out.println(a + b);
	}

	public void print(String a, String b) {
		System.out.println(a.toUpperCase() + "," + b.toLowerCase());
	}
}






            额,有了这个基础,再去看spring的源码,估计就差不多能看懂了。







目录
相关文章
|
2月前
|
存储 Java
[Java]反射
本文详细介绍了Java反射机制的基本概念、使用方法及其注意事项。首先解释了反射的定义和类加载过程,接着通过具体示例展示了如何使用反射获取和操作类的构造方法、方法和变量。文章还讨论了反射在类加载、内部类、父类成员访问等方面的特殊行为,并提供了通过反射跳过泛型检查的示例。最后,简要介绍了字面量和符号引用的概念。全文旨在帮助读者深入理解反射机制及其应用场景。
22 0
[Java]反射
|
3月前
|
安全 Java 索引
Java——反射&枚举
本文介绍了Java反射机制及其应用,包括获取Class对象、构造方法、成员变量和成员方法。反射允许在运行时动态操作类和对象,例如创建对象、调用方法和访问字段。文章详细解释了不同方法的使用方式及其注意事项,并展示了如何通过反射获取类的各种信息。此外,还介绍了枚举类型的特点和使用方法,包括枚举的构造方法及其在反射中的特殊处理。
66 9
Java——反射&枚举
|
2月前
|
安全 Java 测试技术
🌟Java零基础-反射:从入门到精通
【10月更文挑战第4天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
26 2
|
3月前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
2月前
|
IDE Java 编译器
java的反射与注解
java的反射与注解
17 0
|
3月前
|
Java 程序员 编译器
Java的反射技术reflect
Java的反射技术允许程序在运行时动态加载和操作类,基于字节码文件构建中间语言代码,进而生成机器码在JVM上执行,实现了“一次编译,到处运行”。此技术虽需更多运行时间,但广泛应用于Spring框架的持续集成、动态配置及三大特性(IOC、DI、AOP)中,支持企业级应用的迭代升级和灵活配置管理,适用于集群部署与数据同步场景。
|
3月前
|
存储 安全 Java
扫盲java基础-反射(一)
扫盲java基础-反射(一)
|
3月前
|
Java
扫盲java基础-反射(二)
扫盲java基础-反射(二)
|
5月前
|
安全 Java 测试技术
day26:Java零基础 - 反射
【7月更文挑战第26天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
35 5
|
4月前
|
缓存 安全 Java
【Java 第十篇章】反射
Java 反射技术让程序能在运行时动态获取类信息并操作对象,极大提升了灵活性与扩展性。本文将介绍反射的基本概念、原理及应用,包括如何使用 `Class`、`Field`、`Method` 和 `Constructor` 类进行动态操作。此外,还将探讨反射在动态加载、框架开发与代码测试中的应用场景,并提醒开发者注意性能与安全方面的问题,帮助你更合理地运用这一强大工具。
31 0