java 反射类及辅助类

本文主要介绍反射的基本使用

目录

反射

反射作用及优缺点

Class类   

创建Class对象的三种方式:

由Class对象得到类的对象

其他常用方法:

获取属性

获取方法

获取构造方法

获取父类及接口

Field类

Method类

Modifier类

Constructor类

代码示例:


 

反射

反射机制是指在程序运行状态中,对于任意一个类(只要知道类的完整路径,即包名和类名),都能获取这个类的所有信息(所有属性和方法);反射不需要有明确的类型对象,所有的对象都使用Object表示,所以对于一个对象,通过反射都能调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制。

反射作用及优缺点

作用

  • 1.实现简单的反编译,获取类中的属性和方法等基本信息,即.class—>java
  • 2.通过反射机制可以获取类的属性、方法等信息并且可以是用这些属性和方法

优缺点

优点

  •  提高程序的灵活性和扩展性。使用反射后,创建对象有两种方式,1可以使用new关键字来创建对象,2可以从配置文件中读取,提高程序的灵活性和稳定性,因为频繁修改程序可能出错,通过反射读取配置文件会方便很多

缺点

  1. 影响性能。使用反射,代码量变多,由于要动态的读取类,就会影响性能了。
  2. 破坏封装性。Field类和Method类可以修改属性和方法的访问权,破坏了程序设置成private的初衷

 

 

Class类   

java.lang.Class

在Java中,每个class都有一个相应的Class对象。也就是说,当我们编写一个类,编译完成后生成.class文件,在类加载器将.class文件读取到内存中的时候,jvm就会创建.class文件的Class对象,并且只创建一个,存放到jvm的方法区内存中,用于表示这个类的类型信息。任何类在被使用时,都会创建这个类的Class对象,即我们写的每一个类都是对象,即每一个类都有自己的对象,也是Class类的对象

java中的反射就是通过类的Class对象来操作的,来看下Class类:

构造方法:

private Class(ClassLoader loader)  //私有的构造方法,无法显示声明一个Class对象,即无法使用new来创建对象

private Class(ClassLoader loader, Class<?> arrayComponentType) {
        classLoader = loader;
        componentType = arrayComponentType;
    }

创建Class对象的三种方式:

1 public static Class<?> forName(String className) throws ClassNotFoundException,调用Class的静态方法forName获取该类的Class对象,参数className要包括包名和类名,此方法可以不用java文件,只用java对象编译后的.class文件,将其加载到内存中,通过这种方式来创建Class对象,也需要知道完整的路径和类名

2 通过类的隐含的静态成员class调用 比如获取类Student的Class对象  Class c1=Student.class

3java语言中任何一个java对象都有getClass 方法,调用该类的任何一个对象的getClass方法创建该类的Class对象

由Class对象得到类的对象

1public T newInstance()  调用Class对象的newInstance方法,实际上是利用默认构造器来创建该类的实例,该实例为Object类型

该方法在jdk9被Deprecated了

2.使用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建该Class对象对应类的实例。

其他常用方法:

String getName()返回Class对象的类名,包括包名

String getSimpleName()返回Class对象的类名,不包括包名

ClassLoader getClassLoader()返回当前Class的类加载器

获取属性

Field getField(String name)返回Class对象对应类的public修饰的指定名字的属性的Field对象,

Field[] getFields() 返回Class对象对应类的所有public修饰的属性的Filed对象数组,不能获取父类的

Field getDeclaredField(String name)返回Class对象对应类的指定名字的属性的Field对象

Field[] getDeclaredFields()返回Class对象对应类的所有属性的Field对象的数组

native int getModifiers()返回Class对象的修饰符对应的int值

获取方法

Method对应类中的方法

Method getMethod(String name, Class<?>... parameterTypes)返回Class对象所有公共方法中指定名称的方法,可变参数:该方法中所有形参的类型的Class对象,基本数据类型的不要写成包装类的Class对象

Method[] getMethods()返回Class对象所有Public修饰的方法对应的Method对象的数组,包括父类的public方法,不包括无修饰符的方法

Method getDeclaredMethod(String name, Class<?>... parameterTypes)返回Class对象中指定方法名的Method对象,第一个参数是方法名,第二个参数是可变参数,是所有形式参数 类型的Class对象,基本数据类型不用写成包装类,参数个数用来区分重载的方法

Method[] getDeclaredMethods()获取Class对象的所有方法的Method对象的数组,只有当前类的方法

获取构造方法

Constructor[] getConstructors():获取所有公共public修饰的构造方法 对应的Constructor对象的数组

Constructor<T> getConstructor(Class<?>... parameterTypes):获取公共的单个构造方法,参数:要获取的构造方法的所有参数类型的Class对象,避免方法的重载造成选错构造方法

Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes):获取所有构造方法中指定的那个构造方法对应的Constructor对象,参数:要获取的构造方法的所有参数类型的Class对象,可获取私有的

Constructor[] getDeclaredConstructors():获取所有构造方法对应的Construct对象的数组

获取父类及接口

native Class<? super T> getSuperclass()获取父类的Class对象

Class<?>[] getInterfaces()获取接口的Class对象的数组,因为接口可以有多个,父类只能有一个


既然设计到了属性,方法,构造方法,修饰符,那就先看属性类Field,java.lang.reflect.Field

Field类

用来辅助获取和操作类的字段

常用方法:

Class<?> getType()返回该属性的类型的Class对象。基本数据类型的返回包装类的Class对象

String getName():返回属性的名称

Object get(Object obj)获取指定对象的指定字段的值

void set(Object obj, Object value)设置指定对象的指定字段的值

setAccessible(boolean flag)设置该属性是否可以被访问,可以把private修饰的属性变为可访问的,从外部打破了访问权限

int getModifiers()获取属性修饰符对应的int值,,0默认的,1public2private4protected


看下Method类,import java.lang.reflect.Method

Method类

用来处理Class对象返回的方法

Method常用方法:

String getName()获得方法名

int getModifiers返回当前Method对象的修饰符对应的int值

Class<?>getReturnType()返回该方法返回值类型对应Class对象

Class<?>[] getParameterTypes()返回所有 参数类型的Class对象  的数组

Class<?>getExceptionTypes()返回当前Method对象的底层代码中抛出的异常类型对应的Class对象的数组

Class<?>getDeclaringClass返回当前Method对象表示的方法所在类或接口的Class实例

String toGenericString()返回描述此Method对象的字符串,包括类型参数

Object invoke(Object obj, Object... args)执行Method对象对应的方法,第一个参数是对象,第二个参数是可变参数,该方法要求的参数,是实参


 

再来看修饰符类,里面有修饰符的常用方法,在 java.lang.reflect.Modifier

Modifier类

static String toString(int mod)

static boolean isPublic(int mod)将修饰符对应的int参数传入,返回对应的修饰符字符串

static boolean isPublic(int mod)判断是否为public类型,类似的方法还有不少,不一 一列举


再来看下构造器类相关的方法,在java.lang.reflect.Constructor

Constructor类

T newInstance(Object ... initargs)用构造方法来创建实例,返回Object类型的对象,可变参数: 构造器中应传入的参数,实参,无参构造器不需要参数

int getModifiers()返回构造方法的修饰符对应的int值

String getName()返回构造方法的名称,其实就是对应的类名,但是包含包名

Class<?>[] getParameterTypes()返回构造方法中参数类型对应的Class对象的数组

void setAccessible(boolean flag)修改构造方法的试用权限,可以将私有构造方法设置成可访问,利用私有构造方法创建实例


代码示例:

先看下用来示例的Student类:

public class Student {
	private int age;
	public String name;
	protected int high;
	boolean sex;

	public Student() {
		System.out.println("无参构造器");
	}
	private Student(String name) {
		this.name=name;
	}
	public Student(int age, String name, int high, boolean sex) {
		super();
		this.age = age;
		this.name = name;
		this.high = high;
		this.sex = sex;
	}

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

	public static String test1(int i, String s) {
		return s + " : " + i;
	}

	private int getAge() {
		return age;
	}

}

 下面示例三种方式创建Class对象

public class ReflectTest01 {
	public static void main(String[] args) throws ClassNotFoundException {
		// 利用反射获取Class对象的三种方式
		Class clazz1 = Class.forName("reflect.Student");
		System.out.println(clazz1.getName());
		// java中每个类都有.class属性
		Class clazz2 = Student.class;
		// 通过对象实例的引用
		Student s = new Student();
		Class clazz3 = s.getClass();

		System.out.println(clazz1 == clazz2);
		System.out.println(clazz1 == clazz3);

	}
}
out:
reflect.Student
无参构造器
true
true

示例获取类的属性

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class ReflectTest03 {
	public static void main(String[] args) throws ClassNotFoundException {
		Class clazz = Class.forName("reflect.Student");
		// 获取public修饰的属性的数组

		Field[] fields = clazz.getFields();
		for (Field field : fields) {
			System.out.println(field.getName());
		}
		// 获取类中所有的属性,返回Field数组,getName方法
		Field[] fields2 = clazz.getDeclaredFields();
		for (Field field : fields2) {
			// 获取变量名
			System.out.println(field.getName());
		}
		Field[] field3 = clazz.getDeclaredFields();
		for (Field field : field3) {
			int i = field.getModifiers();// 获取变量修饰符对应的int值,0默认的,1public2private4protected
			String str = Modifier.toString(i);
			System.out.println(str);
			Class c = field.getType();// 返回属性的类型比如Integer,String类对应的Class对象
			String s1 = c.getName();// 返回带包名的类名
			String s2 = c.getSimpleName();// 返回不带包名的类型
			System.out.println(s2);
			System.out.println(field.getName());

		}
		// 反编译打印Student类的属性
		StringBuilder sb = new StringBuilder(200);
		sb.append(Modifier.toString(clazz.getModifiers()) + "\t" + clazz.getName() + "{\n");
		for (Field f : field3) {
			sb.append("\t");
			if (f.getModifiers() != 0) {
				sb.append(Modifier.toString(f.getModifiers()) + " ");
			}
			sb.append(f.getType().getSimpleName() + " ");
			sb.append(f.getName() + "\n");
		}
		sb.append("}");
		System.out.println(sb);

	}
}
out:
name
age
name
high
sex
private
int
age
public
String
name
protected
int
high

boolean
sex
public	reflect.Student{
	private int age
	public String name
	protected int high
	boolean sex
}

获取属性并修改属性示例:

import java.lang.reflect.Field;

public class ReflectTest04 {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException,
			IllegalArgumentException, IllegalAccessException, InstantiationException {
		Class c = Class.forName("reflect.Student");
		Object student = c.newInstance();//创建对象实例
		Field f1 = c.getField("name");//获取指定public属性
		f1.set(student, "张三丰");//为属性赋值,传入对象和值
		System.out.println(f1.get(student));//取出值,传入对象

		Field f2 = c.getDeclaredField("age");
		f2.setAccessible(true);//对不可访问的变量修改访问权限,使其可被访问
		f2.set(student, 15);
		System.out.println(f2.get(student));

	}
}


out:
无参构造器
张三丰
15

 

演示获取方法相关信息的示例:

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class ReflectTest5 {
	public static void main(String[] args) throws ClassNotFoundException {
//		Class c = Class.forName("reflect.Student");
		Class c = Class.forName("java.lang.Object");
		Method[] methods = c.getMethods();// 获取Class对象表示的类中所有public方法,包括父类
		/*
		 * for (Method m : methods) { System.out.println(m.getName()); }
		 */
		Method[] methods2 = c.getDeclaredMethods();// 获取Class对象的所有方法对应的Method数组,不包括父类
		for (Method m : methods2) {
			System.out.println(Modifier.toString(m.getModifiers()));// 获取方法的修饰符
			Class returnType = m.getReturnType();// 返回方法返回值类型对应的Class对象

			System.out.println(returnType.getSimpleName());// 输出方法的返回值类型
			System.out.println(m.getName());// 获取方法名
			Class[] types = m.getParameterTypes();// 获取参数的类型对应的Class对象数组
			for (Class type : types) {
				System.out.println(type.getSimpleName());
			}
			System.out.println("----------------");

		}
		// 反编译打印类中的所有方法
		StringBuilder sb = new StringBuilder(200);
		sb.append(Modifier.toString(c.getModifiers()) + "\t" + "class  " + c.getSimpleName() + "{" + "\n");
		for (Method m : methods2) {
			sb.append("\t");
			sb.append(Modifier.toString(m.getModifiers()) + " ");// 方法修饰符
			sb.append(m.getReturnType().getSimpleName() + " "); // 方法返回值
			sb.append(m.getName()); // 方法名
			sb.append("(");
			Class[] classes = m.getParameterTypes(); // 方法的参数
			for (int i = 0; i < classes.length; i++) {
				sb.append(classes[i].getSimpleName() + " ");
				if (i != classes.length - 1) {
					sb.append(",");
				}
			}
			sb.append(")");
			sb.append("{}\n");
		}
		sb.append("}");

		System.out.println(sb);// 打印拼接好的字符串

	}

}
out:
private
int
getAge
----------------
public
void
setAge
int
----------------
public static
String
test1
int
String
----------------
public	class  Student{
	private int getAge(){}
	public void setAge(int ){}
	public static String test1(int ,String ){}
}

演示调用类中方法示例

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

public class ReflectTest06 {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException,
			InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Class class1 = Class.forName("reflect.Student");
		Method method = class1.getDeclaredMethod("test1", int.class, String.class);//获取指定方法
		Object obj = class1.newInstance();//创建对象
		Object strObj = method.invoke(obj, 5, "Str");//执行指定方法
		System.out.println(strObj);

	}
}
out:
无参构造器
Str : 5

获取构造方法并利用构造方法创建实例的示例:

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;

public class ReflectTest07 {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException,
			InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Class c = Class.forName("reflect.Student");
//		Class c = Class.forName("java.lang.StringBuilder");
//		Class c = Class.forName("java.util.HashMap");
		Constructor[] cons = c.getConstructors();// 获取所有公共的构造方法(public修饰),返回一个Constructor类型数组
		for (Constructor i : cons) {
			System.out.println(Modifier.toString(i.getModifiers()));// 打印修饰符
			System.out.print(i.getName() + "\t");// 打印构造方法名字
			Class[] classes = i.getParameterTypes();
			for (Class c1 : classes) {
				System.out.print(c1.getSimpleName() + " ");// 打印参数类型
			}
			System.out.println();
		}

		// 调用公共无参构造器创建实例
		Constructor con1 = c.getConstructor();
		Object obj = con1.newInstance();
		// 利用私有构造器创建对象
		Constructor con2 = c.getDeclaredConstructor(String.class);// 获取私有构造器
		con2.setAccessible(true);// 设置其权限可访问
		Object obj2 = con2.newInstance("李白");// 调用私有构造器创建对象实例
		// 使用公共有参构造器创建对象
		Constructor con3 = c.getDeclaredConstructor(int.class, String.class, int.class, boolean.class);
		Object obj3 = con3.newInstance(10, "杜甫", 180, true);
		System.out.println(obj3);//返回对象对应的内存地址

	}
}

获取父类及接口类型示例

package reflect;

public class ReflectTest08 {

	public static void main(String[] args) throws ClassNotFoundException {
		Class c1 = Class.forName("reflect.Student");
		Class c1sup = c1.getSuperclass();// 获取父类
		System.out.println(c1sup.getSimpleName());

		Class c2 = Class.forName("java.util.HashMap");
		Class c2sup = c2.getSuperclass();
		System.out.println(c2sup.getSimpleName());
		// 获取父接口
		Class[] c2inters = c2.getInterfaces();
		for (Class ci : c2inters) {
			System.out.print(ci.getSimpleName() + " ");
		}
		System.out.println();// 换行

	}

}
out:
Object
AbstractMap
Map Cloneable Serializable 

演示将一个类的全部信息通过反射机制打印出来

package reflect;

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

public class ReflectTest09 {

	public static void main(String[] args) throws ClassNotFoundException {
//		Class c = Class.forName("java.util.HashMap");
		Class c = Class.forName("reflect.Student");
		Class sup = c.getSuperclass();// 父类
		Class[] inters = c.getInterfaces();// 接口数组
		Constructor[] cons = c.getDeclaredConstructors();// 构造方法数组
		Field[] fields = c.getDeclaredFields();// 属性数组
		Method[] methods = c.getDeclaredMethods();// 方法数组
		StringBuilder sb = new StringBuilder(400);
		// 添加类名,
		sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName());
		// 添加继承类名
		if (!sup.getSimpleName().equals("Object")) {
			sb.append(" extends  " + sup.getSimpleName());
		}
		// 添加接口名
		if (inters.length != 0) {
			sb.append(" implements ");
			for (int i = 0; i < inters.length; i++) {
				sb.append(inters[i].getSimpleName());
				if (i != inters.length - 1) {
					sb.append(" , ");
				}
			}
		}
		// 添加左大括号
		sb.append("{\n");

		// 添加属性字段
		for (Field f : fields) {
			sb.append("\t");
			if (f.getModifiers() != 0) {// 格式化没有修饰符的方法
				sb.append(Modifier.toString(f.getModifiers()) + " ");
			}
			sb.append(f.getType().getSimpleName() + " ");
			sb.append(f.getName() + "\n");
		}
		sb.append("\n");
		// 添加构造方法
		for (Constructor con : cons) {
			sb.append("\t");
			sb.append(Modifier.toString(con.getModifiers()) + " ");// 修饰符
			String str = con.getName();// 对构造对象的名字处理
			sb.append(str.substring(str.lastIndexOf(".") + 1) + "");// 构造方法名字
			sb.append("(");
			Class[] classType = con.getParameterTypes();
			if (classType.length != 0) {
				for (int i = 0; i < classType.length; i++) {
					sb.append(classType[i].getSimpleName() + " ");
					if (i != classType.length - 1) {
						sb.append(",");
					}
				}
			}
			sb.append(")");
			sb.append("{}\n");

		}
		sb.append("\n");
		// 添加方法
		for (Method m : methods) {
			sb.append("\t");
			if (m.getModifiers() != 0) {
				sb.append(Modifier.toString(m.getModifiers()) + " ");// 方法修饰符
			}

			sb.append(m.getReturnType().getSimpleName() + " "); // 方法返回值
			sb.append(m.getName()); // 方法名
			sb.append("(");
			Class[] classes = m.getParameterTypes(); // 方法的参数
			for (int i = 0; i < classes.length; i++) {
				sb.append(classes[i].getSimpleName() + " ");
				if (i != classes.length - 1) {
					sb.append(",");
				}
			}
			sb.append(")");
			sb.append("{}\n");
		}
		sb.append("}");
		System.out.println(sb);

	}

}
out:
public class Student{
	private int age
	public String name
	protected int high
	boolean sex

	public Student(int ,String ,int ,boolean ){}
	private Student(String ){}
	public Student(){}

	public void setAge(int ){}
	public static String test1(int ,String ){}
	private int getAge(){}
}

这段代码只能打印一个java文件定义了一个类,还不能打印接口的信息,如果一个类中还定义内部类,能打印出来内部类的方法,但不能打印出类名,属性,括号信息.


               

 

主要参考 http://www.monkey1024.com/javase/702

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值