Java的反射机制

一、背景引入

tomcat是由Java编写的,所以可以和servlet合成一个程序。用tomcat启动网站,实际就是将网站与tomcat合成一个项目。

servlet没有主方法,借助tomcat的主方法来启动,tomcat作为进程存在,servlet作为线程存在。

tomcat作为一个早就编写好的程序,是如何调用到刚创建的servlet?

用到的就是反射机制。

二、反射的定义及作用

        能够分析类能力的程序称为反射( reflective )。反射机制的功能极其强大,在下面可以看
到, 反射机制可以用来:

  1. 在运行时分析类的能力。
  2. 在运行时查看对象, 例如, 编写一个toString 方法供所有类使用。
  3. 实现通用的数组操作代码。
  4. 利用Method 对象, 这个对象很像中的函数指针。(from 《Java核心技术》)

三、反射相关的各种类

Java官方文档java.lang.reflect中:

其中AccessibleObject类是Field,Method和Constructor对象的基类。

在Java核心技术(5.7反射)主要涉及的类是Class类、Constructor类、Field类、Method类、Modifier类这五个类。

  • Class类:是对类的抽象和集合
  • Constructor类:英文Constructor构造器,所以这个类是和类的构造器信息有关的类。
  • Field类:英文Field领域,所以这个类是和类的域信息有关的类。
  • Method类:英文Method方法,所以这个类是和类的方法信息有关的类。
  • Modifier类:英文Modifier修饰语,所以这个类是和类中的修饰信息有关的类。

1、Class类

一些解释:

  • 如果说类是对象抽象和集合的话,那么Class类就是对类的抽象和集合;如同用一个Employee 对象表示一个特定的雇员属性一样, 一个Class 对象将表示一个特定类的属性。
  • 它的构造函数是私有的,只有虚拟机才能够创建它的对象
  • Object 类中的getClass( ) 方法将会返回一个Class 类型的实例。(Object类是所有类的超类)

 常用方法:

返回类型方法名作用
static ClassforName(String className)返回描述类名为className 的Class 对象。
Objectnewlnstance()返回这个类的一个新实例。
Field[ ]getFields()返回一个包含Field 对象的数组, 这些对象记录这个类或其超类的公有域。
Filed[ ]getDeclaredFields()

获得这个类(不含超类)所有的域,包括私有变量

Constructor[ ]

getConstructors()

获得这个类所有所有公有构造方法

Constructor[ ]

getDeclaredConstructors()

获得这个类所有的构造方法,包括私有

Method[ ]

getdMethods()

获得所有公有方法,包括从超类继承的

Method[ ]

getDeclaredFields()

获得这个类所有的方法,但不含超类继承的

int

getModifiers()

获取类的修饰

  • 反射通过以下三种种方式获取类信息(创建Class的对象的方法):
    • Class c1 = 对象.getClass()
    • Class c1 = 类名.Class
    • Class c1 = Class.forName("包名.类名")
  • c1.newInstance();根据类信息获取类的实例

 代码:

Class c1 = Class.forName("com.工商.Son1")//Class类的静态方法,获得类名"com.工商.Son1"对应的Class对象
Class superc1 = c1.getSuperclass()//获取c1的父类对应的Class对象
Object m = c1.newInstance();//返回一个类的对象
Constructor[] constructors = c1.getDeclaredConstructors() ;//获得这个类所有的构造方法,包括私有
Constructor[] constructors = c1.getConstructors() ;//获得这个类所有所有公有构造方法
Method[] methods = c1.getDeclaredMethods() ;//获得这个类所有的方法,但不含超类继承的
Method[] methods = c1.getdMethods() ;//获得所有公有方法,包括从超类继承的
Field[] fields = c1.getDeclaredFields() ;//获得这个类(不含超类)所有的域,包括私有变量
Field[] fields = c1.getFields() ;//获得类或其超类的公有域
//获取class信息的一段代码实例
Class c1 = Class.forName("com.工商.Son1");
Class superc1 = c1.getSuperclass();
String modifiers = Modifier.toString(c1.getModifiers());
if(modifiers.length()>0) System.out.print(modifiers + " ");
System.out.print("class " + path);
if(superc1 !=null && superc1 != Object.class) System.out.print(" extends " + superc1.getName());
//运行结果:
//public class com.工商.Son1 extends com.工商.PersonA

 2、Constructor类

常用方法:

返回类型

方法名

作用

Object

newlnstance(Object[] args)

构造一个这个构造器所属类的新实例。args 是提供给构造器的参数。

String

getName()

获取构造方法名字,返回字符串

int

getModifiers()

返回一个整型数值,用于描述修饰符

Class

getDeclaringClass()

返冋一个用于描述类中定义构造函数的Class 对象

Class[ ]

getParameterTypes()

返回一个Class[]数组,获取方法的所有参数类型(入参)

Class[ ]

getExceptionTypes()

返回一个用于描述方法抛出的异常类型的Class 对象数组

代码:

public static void printConstructors(Class c1) {
    Constructor[] constructors = c1.getDeclaredConstructors();
     for(Constructor c : constructors) {		
		String name = c.getName();
		System.out.println("   ");
		String modifiers = Modifier.toString(c.getModifiers());
		if(modifiers.length() > 0) System.out.print(modifiers + " ");
		System.out.print(name + "(");
		
		Class[] paramTypes = c.getParameterTypes();
		for(int j = 0; j < paramTypes.length; j++) {
			if(j > 0) System.out.print(", ");
			System.out.print(paramTypes[j].getName());
		}
		System.out.println(");");
	}
}
//运行结果:
//public com.工商.Son1();
   
//public com.工商.Son1(java.lang.String, int);

3、Method类

常用方法:

返回类型

方法名

作用

String

getName()

获取方法名字

Class

getReturnType()

获取返回值类型

int

getModifiers()

返回一个整型数值,用于描述修饰符

Class

getDeclaringClass()

返冋一个用于描述类中定义方法的Class 对象

Class[ ]

getParameterTypes()

返回一个Class[]数组,获取方法的所有参数类型(入参)

Class[ ]

getExceptionTypes()

返回一个用于描述方法抛出的异常类型的Class 对象数组

 代码:

public static void printlnMethods(Class c1) {		
	Method[] methods = c1.getDeclaredMethods();
		
	for(Method method : methods) {
		Class retType = method.getReturnType();
		String name = method.getName();
			
		System.out.println("   ");
			
		String modifiers = Modifier.toString(method.getModifiers());
		if(modifiers.length() > 0) System.out.print(modifiers + " ");
		System.out.print(retType.getName() + " " + name + "(");
			
		Class[] paramTypes = method.getParameterTypes();
		for(int j = 0; j< paramTypes.length; j++) {
			if(j > 0) System.out.print(", ");
			System.out.print(paramTypes[j].getName());
		}
		System.out.println(");");

	}
}
//运行结果:
//public void m1();
   
//public void m2(java.lang.String, java.lang.String);

4、Field类

常用方法:

返回类型

方法名

作用

String

getName()

获取域名字

Class

getType()

获取域类型

int

getModifiers()

返回一个整型数值,用于描述修饰符

Class

getDeclaringClass()

返冋一个用于描述类中定义域的Class 对象

代码:

public static void printFields(Class c1) {		
	Field[] fields = c1.getDeclaredFields();		
	for(Field f : fields) {
		Class type = f.getType();
		String name = f.getName();
		//System.out.print("   ");
		String modifiers = Modifier.toString(f.getModifiers());
		if(modifiers.length() > 0) System.out.print(modifiers + " ");
		System.out.println(type.getName() + " " + name + ";");
	} 
}
//运行结果:
//public int height;
//public java.lang.String name;

 5、Modifier类

常用方法:

 代码:

String modifiers = Modifier.toString(c.getModifiers());
  • 反射能否获取类的私有属性?
    • 可以,setAccessible(true) ,设置为true

 6、利用反射分析对象//Java核心技术的完整代码

package objectAnalyzer;

import java.util.ArrayList;

public class ObjectAnalyzerTest {
	
	public static void main(String[] args){
		ArrayList<Integer> squares = new ArrayList<>();
		for(int i = 1;i <= 5;i ++) 
			squares.add(i*i);
		System.out.println(new ObjectAnalyzer().toString(squares));
		
	}
}
package objectAnalyzer;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;

public class ObjectAnalyzer {
	private ArrayList<Object> visited = new ArrayList<>();
	
	public String toString(Object obj)
	{
		if(obj == null) return "null";
		if(visited.contains(obj)) return "...";
		visited.add(obj);
		Class c1 = obj.getClass();
		if(c1 == String.class) return (String) obj;
		if(c1.isArray()) {
			String r = c1.getComponentType() + "[]{";
			for(int i = 0; i<Array.getLength(obj); i++) {
				if(i > 0) r += ",";
				Object val = Array.get(obj, i);
				if(c1.getComponentType().isPrimitive()) r += val;
				else r += toString(val);
				
			}
			return r + "}";
		}
		
		String r = c1.getName();
		
		do {
			r += "[";
			Field[] fields = c1.getDeclaredFields();
			AccessibleObject.setAccessible(fields, true);
			
			for(Field f : fields) {
				if(!Modifier.isStatic(f.getModifiers())) {
					if(!r.endsWith("[")) r +=",";
					r += f.getName() + "=";
					
					
					try {
						Class t = f.getType();
						Object val;
						val = f.get(obj);
						if(t.isPrimitive()) r += val;
						else r += toString(val);
					} catch (IllegalArgumentException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IllegalAccessException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				
				}
			}
			r +="]";
			c1 = c1.getSuperclass();
		}
		while(c1 != null);
		return r;
	}
}

全文整理自Java核心技术5.7反射。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值