Java反射

预备知识

一、反射的概述

Java反射(Reflection)是一种新的操作类中成员变量、构造方法和普通方法的机制,为了实现对成员变量、构造方法和普通方法的操作,我们需要借助Java自身提供的java.lang包下的Class类和java.lang.reflect包下的反射API 。

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

二、Class类

1、概念

Class类是Java 反射机制的入口,封装了一个类或接口的运行时信息,通过调用Class类的方法可以获取这些信息。

2、特点

1.该类在java.lang包中;
2.该类被final所修饰,即该类不可以被子类继承;
3.该类实现了Serializable接口;
4.该类的构造方法被private所修饰,即不能通过new关键字创建该类的对象;

3、备注

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。也就是JVM中有N多的实例每个类都有该Class对象。(包括基本数据类型)

Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了。

正文部分

一、图解反射

在这里插入图片描述

准备工作
package com.zzu;

public class Student {

	private String name;
	private String mobile;
	private String a;
	protected String b;
	String c;
	private String d;
	
	public Student() {

	}
	public Student(String name) {
		this.name = name;
	}
	public Student(String name, String mobile) {
		this.name = name;
		this.mobile = mobile;
	}
	
	public void study(String subject) throws Exception {
		System.out.println(subject+" is studying");
	}
	public void read() {
		System.out.println("reading");
	}
	@Override
	public String toString() {
		return "name=" + name + ", mobile=" + mobile + ", a=" + a + ", b=" + b + ", c=" + c + ", d=" + d;
	}
}


二、获取Class类实例化对象的方式

1、Class.forName(“完整的类名”)
2、类名.class
3、对象.getClass()

代码演示

package com.zzu;

public class Student {

	public static void main(String[] args) throws Exception {
	
		Class class1 = Class.forName("com.zzu.Student");
		System.out.println(class1);

		Class class2 = Student.class;
		System.out.println(class2);
		
		Class class3 = new Student().getClass();
		System.out.println(class3);
		
	}

}

输出结果

class com.zzu.Student
class com.zzu.Student
class com.zzu.Student

三、普通方法

(1)获取普通方法

借助Class类中某些方法可以获取对应类中声明的成员方法实例对象,这些方法有:

1、Method[] getMethods():返回该Class对象表示类或接口中所有public方法(含继承的)对应的Method对象数组。

2、Method getMethod(String methodName, Class<?>… parameterTypes):返回与该Class对象表示类或接口中方法名和方法形参类型相匹配的public方法(含继承的)的Method对象。

3、Method[] getDeclaredMethods():返回该Class对象表示类或接口内声明定义的所有访问权限的方法(不含继承的)对应的Method对象数组。

4、Method getDeclaredMethod(String methodName,Class<?>… parameterTypes) :返回与该Class对象表示类或接口中方法名和方法形参类型相匹配方法(不含继承的)对应的Method对象。

代码演示

package com.zzu;
import java.lang.reflect.Method;

public class Test {

	public static void main(String[] args) throws Exception {
		Class clazz = Student.class;
		
		Method[] methods = clazz.getMethods();
		for (Method method : methods) {
			System.out.println(method);
		}
		
		Method method = clazz.getMethod("study", String.class);
		System.out.println(method);
		
		Method[] methods2 = clazz.getDeclaredMethods();
		for (Method method2 : methods2) {
			System.out.println(method2);
		}
		
		Method method2 = clazz.getDeclaredMethod("study", String.class);
		System.out.println(method2);		
	}
}

控制台输出

public java.lang.String com.zzu.Student.toString()
public void com.zzu.Student.read()
public void com.zzu.Student.study(java.lang.String) throws java.lang.Exception
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) 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 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()
public void com.zzu.Student.study(java.lang.String) throws java.lang.Exception
public java.lang.String com.zzu.Student.toString()
public void com.zzu.Student.read()
public void com.zzu.Student.study(java.lang.String) throws java.lang.Exception
public void com.zzu.Student.study(java.lang.String) throws java.lang.Exception

2、查看普通方法信息

通过Method类中某些方法可以获取某个成员方法的信息,这些方法如下:

1、Class<?> getDeclaringClass():返回声明Method对象表示方法的类或接口的 Class 对象。

2、int getModifiers():以整数形式返回此Method对象所表示方法的修饰符。应该使用Modifier类中的toString方法对所返回的整数进行解码。

3、Class<?> getReturnType():返回Method对象所表示的方法的返回值类型所对应的Class对象。

4、String getName():返回方法名。

5、Class<?>[] getParameterTypes():返回由Method对象代表方法的形参类型对应Class对象组成的数组。如果方法没有参数,则数组长度为 0。

6、Class<?>[] getExceptionTypes():返回由Method对象表示方法抛出异常类型对应Class对象组成的数组。如果此方法没有在其 throws子句中声明异常,则返回长度为 0 的数组。

代码示例

package com.zzu;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Test {

	public static void main(String[] args) throws Exception {
		Class clazz = Student.class;
		Method method = clazz.getMethod("study",String.class);

		Class class1 = method.getDeclaringClass();
		System.out.println(class1);
		System.out.println("~~~~~~~~~~~~");

		int i = method.getModifiers();
		String string = Modifier.toString(i);
		System.out.println(string);
		System.out.println("~~~~~~~~~~~~");

		Class rt = method.getReturnType();
		System.out.println(rt);
		System.out.println("~~~~~~~~~~~~");

		String name = method.getName();
		System.out.println(name);
		System.out.println("~~~~~~~~~~~~");

		Class [] types = method.getParameterTypes();
		for (Class class2 : types) {
			System.out.println(class2);
		}
		System.out.println("~~~~~~~~~~~~");

		Class [] types2 = method.getExceptionTypes();
		for (Class class2 : types2) {
			System.out.println(class2);
		}
	}
}

控制台输出

class com.zzu.Student
~~~~~~~~~~~~
public
~~~~~~~~~~~~
void
~~~~~~~~~~~~
study
~~~~~~~~~~~~
class java.lang.String
~~~~~~~~~~~~
class java.lang.Exception

3、操作普通方法

通过Method类中某些方法可以调用成员方法,这些方法如下:

1、void setAccessible(boolean flag):调用方法时是否忽略访问权限的影响,true表示忽略,false表示不忽略。

2、Object invoke(Object obj, Object… args):调用Method对象指代的方法并返回Object类型结果。obj表示该方法所在类实例,如果方法时静态的则obj可以指定为null; args表示传入该方法的参数,如果方法没有参数,则args数组长度可以为0或null 。

package com.zzu;
import java.lang.reflect.Method;

public class Test {

	public static void main(String[] args) throws Exception {
		Class clazz = Student.class;
		Student student = new Student();
		Method method = clazz.getMethod("study",String.class);
		method.invoke(student, "Math");		
	}
}

控制台输出

tom is studying
四、构造方法

1、获取构造方法

通过Class类中某些方法可以获取对应类中声明的构造方法实例对象,这些方法有:

1、Constructor<?>[] getConstructors():返回该Class对象表示类中包含的所有public构造方法(不含继承)所对应的Constructor对象数组。

2、Constructor getConstrutor(Class<?>… parameterTypes):返回与该Class对象表示类中参数列表相匹配的public构造方法(不含继承)对应的Constructor对象。

3、Constructor<?>[] getDeclaredConstructors():返回该Class对象表示类中声明的所有构造方法(不区分访问权限)所对应的Constructor对象数组。

4、Constructor getDeclaredConstructor(Class<?>… parameterTypes):返回与该Class对象表示类中参数列表相匹配的构造方法(不区分访问权限)对应的Constructor对象。

代码示例

package com.zzu;
import java.lang.reflect.Constructor;

public class Test {

	@SuppressWarnings({ "rawtypes", "unchecked", "unused" })
	public static void main(String[] args) throws Exception {
		Class clazz = Student.class;
	
		Constructor[] constructors = clazz.getConstructors();
		for (Constructor constructor : constructors) {
			System.out.println(constructor);
		}
		System.out.println("++++++++++++++");

		Constructor constructor = clazz.getConstructor(String.class);
		System.out.println(constructor);
		System.out.println("++++++++++++++");
		
		Constructor[] constructors2 = clazz.getDeclaredConstructors();
		for (Constructor constructor2 : constructors2) {
			System.out.println(constructors2);
		}		
		System.out.println("++++++++++++++");
		
		Constructor constructor1 = clazz.getDeclaredConstructor(String.class,String.class);
		System.out.println(constructor1);
		System.out.println("++++++++++++++");
	}
}

控制台输出

public com.zzu.Student(java.lang.String,java.lang.String)
public com.zzu.Student(java.lang.String)
public com.zzu.Student()
++++++++++++++
public com.zzu.Student(java.lang.String)
++++++++++++++
[Ljava.lang.reflect.Constructor;@52e922
[Ljava.lang.reflect.Constructor;@52e922
[Ljava.lang.reflect.Constructor;@52e922
++++++++++++++
public com.zzu.Student(java.lang.String,java.lang.String)
++++++++++++++

2、查看构造方法信息

通过Constructor类中某些方法可以获取某个构造方法的信息,这些方法如下:

1、Class getDeclaringClass():返回声明Constructor对象对应构造方法的类的Class对象。

2、int getModifiers():以整数形式返回Constructor对象表示的构造方法的修饰符。

3、String getName() :以字符串形式返回Constructor对象所表示的构造方法的名称。

4、Class<?>[] getParameterTypes():返回由Constructor对象所表示的构造方法的形参类型对应Class对象组成的数组 。如果构造方法没有参数,则数组长度为0。

代码示例

package com.zzu;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;

public class Test {

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static void main(String[] args) throws Exception {
		Class clazz = Student.class;
		Constructor constructor = clazz.getConstructor(String.class);

		Class class1 = constructor.getDeclaringClass();
		System.out.println(class1);
		System.out.println("**********");

		int i = constructor.getModifiers();
		String string = Modifier.toString(i);
		System.out.println(string);
		System.out.println("**********");

		String name = constructor.getName();
		System.out.println(name);
		System.out.println("*********");

		Class[] parameterTypes = constructor.getParameterTypes();
		for (Class class2 : parameterTypes) {
			System.out.println(class2);
		}
	}
}

控制台输出结果

class com.zzu.Student
**********
public
**********
com.zzu.Student
*********
class java.lang.String

3、操作构造方法

通过Constructor类中某些方法可以创建对象,这些方法如下:

1、void setAccessible(boolean flag):调用构造方法时是否忽略访问权限的影响,true表示忽略,false表示不忽略。

2、T newInstance(Object… initargs):使用此Constructor对象表示的构造方法来创建声明该构造方法类的新对象。initargs为传入该构造方法中的参数,如果该构造方法没有参数,则可设定为null或一个长度为0的数组。

代码示例

package com.zzu;
import java.lang.reflect.Constructor;

public class Test {

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static void main(String[] args) throws Exception {
		Class clazz = Student.class;
		
		Constructor constructor = clazz.getConstructor(String.class);
		
		Object object = constructor.newInstance("tom");
		
		System.out.println(object);
	}
}

控制台输出结果

 name=tom, mobile=null, a=null, b=null, c=null, d=null
五、成员变量

1、获取成员变量

通过Class类中某些方法可以获取对应类中声明的成员变量实例对象,这些方法有:

1、Field[] getFields():返回该Class对象表示类或接口中所有public属性(含继承的)对应的Field对象数组。

2、Field getField(String fieldName):返回该Class对象表示类或接口中与指定属性名(含继承的)相同的public 属性对应的Field对象。

3、Field[] getDeclaredFields():返回该Class对象表示类或接口内定义的所有属性(不含继承的)对应的Field对象数组。

4、Field getDeclaredField(String fieldName) :返回与该Class对象表示类或接口内定义的属性名(不含继承的)相匹配的属性相对应的Field对象。

代码示例

package com.zzu;
import java.lang.reflect.Field;

public class Test {


	public static void main(String[] args) throws Exception {
		Class clazz = Student.class;

		Field[] fields = clazz.getFields();
		for (Field field : fields) {
			System.out.println(field);
		}
		System.out.println("&&&&&&&");

		Field field = clazz.getField("mobile");
		System.out.println(field);
		System.out.println("&&&&&&&");
		
		Field[] fields2 = clazz.getDeclaredFields();
		for (Field field2 : fields2) {
			System.out.println(field2);
		}
		System.out.println("&&&&&&&");

		Field field2 = clazz.getDeclaredField("d");
		System.out.println(field2);
	}
}

控制台输出

public java.lang.String com.zzu.Student.mobile
&&&&&&&
public java.lang.String com.zzu.Student.mobile
&&&&&&&
private java.lang.String com.zzu.Student.name
public java.lang.String com.zzu.Student.mobile
private java.lang.String com.zzu.Student.a
protected java.lang.String com.zzu.Student.b
java.lang.String com.zzu.Student.c
private java.lang.String com.zzu.Student.d
&&&&&&&
private java.lang.String com.zzu.Student.d

2、获取成员变量信息

通过Field类中某些方法可以获取某个成员变量的信息,这些方法如下:

1、Class<?> getDeclaringClass():返回声明Field对象表示字段的类或接口所对应的Class对象。

2、int getModifiers():以整数形式返回Field对象表示的字段的修饰符。

3、Class<?> getType():返回Field对象所表示字段的数据类型所对应的Class对象(推荐)。

4、Type getGenericType():返回此Field对象所表示字段的声明类型。

5、String getName():返回Field对象表示字段的名称。

代码示例

package com.zzu;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;

public class Test {

	public static void main(String[] args) throws Exception {
		Class clazz = Student.class;
		Field field = clazz.getDeclaredField("d");

		Class class1 = field.getDeclaringClass();
		System.out.println(class1);
		System.out.println("——————————");

		int i = field.getModifiers();
		String string = Modifier.toString(i);
		System.out.println(string);
		System.out.println("——————————");

		Class type = field.getType();
		System.out.println(type);
		System.out.println("——————————");

		Type type2 = field.getGenericType();
		System.out.println(type2);
		System.out.println("——————————");

		String name = field.getName();
		System.out.println(name);
	}
}


控制台输出

class com.zzu.Student
——————————
private
——————————
class java.lang.String
——————————
class java.lang.String
——————————
d

3、操作成员变量
通过Field类中某些方法获取及设置成员变量的值,这些方法如下:

1、void setAccessible(boolean flag):设置或获取属性值时是否忽略访问权限的影响,true表示忽略,false表示不忽略。

2、Object get(Object obj):返回Field表示字段的Object类型的值。obj为该属性所在类创建的对象,如果该属性是静态的,则可设置为null。

3、void set(Object obj, Object value):为Field对象表示属性设置新值。obj为该属性所在类创建的对象,如果该属性为静态的则设置为null;value为该属性新值。

代码演示

package com.zzu;
import java.lang.reflect.Field;

public class Test {

	public static void main(String[] args) throws Exception {
		Class<Student> clazz = Student.class;
		Student student = (Student) clazz.newInstance();
		Field field = clazz.getDeclaredField("d");
		field.setAccessible(true);
		field.set(student, "iron man");
		Object object = field.get(student);
		System.out.println(object);
	}
}

控制台输出结果为:iron man

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值