Java基础——浅析反射

目录

一、前言

二、字节码对象

2.1 Java反射机制中获取字节码对象

2.2 Java虚拟机中对于某一个类只保留一份字节码对象

2.3 小结

三、使用字节码对象获取构造器进而新建对象

3.1 从字节码对象到构造器

3.2 使用字节码对象获取构造器

3.3 使用获取到的构造器新建对象

3.4  小结

四、使用字节码对象获取方法进而调用方法

4.1 从字节码对象到方法调用

4.2 字节码对象获取方法并调用,无返回值,返回值为void

4.3 字节码对象获取方法并调用,有返回值,返回值为String

4.4 字节码对象获取static方法并调用,无返回值,返回值为void

4.5 字节码对象获取static方法并调用,有返回值,返回值为String

4.6 演示参数列表为可变参数(数组)时的情况

4.7  小结

五、小结


一、前言

官方解释:Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.
The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class. It also allows programs to suppress default reflective access control.(反射使Java代码可以发现有关已加载类的字段,方法和构造函数的信息,并在安全性限制内使用反射的字段,方法和构造函数对其基础副本进行操作。该API容纳需要访问目标对象的公共成员(基于其运行时类)或给定类声明的成员的应用程序。 它还允许程序禁止默认的反射访问控制。)

我的理解:反射,最简单的理解就是不用new而新建对象。Java反射相关的所有内容都是在java.lang.reflect包中,记住这个包,为练习下面的代码做好准备。

二、字节码对象

2.1 Java反射机制中获取字节码对象

Java反射机制中获取字节码对象有三种方式,各个方式各有优缺,如下图:

示例代码——获取字节码对象的三种方式:

package mypackage;

//获取字节码对象的三种方式
//Java中,String是一种特殊的引用类型,这里以java.lang.String为例,获取字节码对象
public class Test {

	public static void main(String[] args) throws ClassNotFoundException {
		// 方式1:使用class属性
		// 注意:其实这里可以不用使用java.lang.String.class 直接使用String.class 因为Java程序默认import
		// java.lang包

		Class<java.lang.String> class1 = java.lang.String.class;
		System.out.println(class1);

		class1 = String.class;
		System.out.println(class1);
		System.out.println("====================");
		// 方式2:使用getClass()方法
		// 注意:其实这里可以不用使用java.lang.String().getClass 直接使用String.getClass()
		// 因为Java程序默认import java.lang包
		Class<?> class2 = new java.lang.String().getClass();
		System.out.println(class2);

		class2 = new String().getClass();
		System.out.println(class2);
		System.out.println("====================");
		// 方式3:使用Class类的静态方法forName(String className)
		// 注意:这里必须写java.lang.String,作为字符串时,不必写全限定类名,否则报错java.lang.ClassNotFoundException
		Class<?> class3 = Class.forName("java.lang.String");
		System.out.println(class3);
		//class3 = Class.forName("String");
		// System.out.println(class3);   //这里必须注释,因为这里报错java.lang.ClassNotFoundException
		
	}

}

输出:

class java.lang.String
class java.lang.String
====================
class java.lang.String
class java.lang.String
====================
class java.lang.String

小结:获取字节码对象是反射机制的第一步,后面使用字节码对象获取构造器并新建对象,使用字节码对象获取方法并调用方法。

2.2 Java虚拟机中对于某一个类只保留一份字节码对象

Java虚拟机中对于某一个类只保留一份字节码对象,即表示同一个类的n个不同对象使用的是同一个字节码对象,即同一个类的n个不同对象的字节码引用指向的是同一个字节码对象。

示例代码:

package mypackage比较;

//获取字节码对象的三种方式
//Java中,String是一种特殊的引用类型,这里以java.lang.String为例,获取字节码对象
public class Test {

	public static void main(String[] args) throws ClassNotFoundException {
		// 方式1:使用class属性
		// 注意:其实这里可以不用使用java.lang.String.class 直接使用String.class 因为Java程序默认import
		// java.lang包

		Class<java.lang.String> class1 = java.lang.String.class;
		System.out.println(class1);

		class1 = String.class;
		System.out.println(class1);
		System.out.println("====================");
		// 方式2:使用getClass()方法
		// 注意:其实这里可以不用使用java.lang.String().getClass 直接使用String.getClass()
		// 因为Java程序默认import java.lang包
		Class<?> class2 = new java.lang.String().getClass();
		System.out.println(class2);

		class2 = new String().getClass();
		System.out.println(class2);
		System.out.println("====================");
		// 方式3:使用Class类的静态方法forName(String className)
		// 注意:这里必须写java.lang.String,作为字符串时,不必写全限定类名,否则报错java.lang.ClassNotFoundException
		Class<?> class3 = Class.forName("java.lang.String");
		System.out.println(class3);
		//class3 = Class.forName("String");
		// System.out.println(class3);   //这里必须注释,因为这里报错java.lang.ClassNotFoundException
		
		//对应同一个类,Java虚拟机中只保存一份字节码对象,
		System.out.println("====================");
		System.out.println(myCompareFunc(class1,class2,class3));
	}
	
	private static boolean myCompareFunc(Class<?> class1,Class<?> class2,Class<?> class3){
		if (class1==class2 && class1==class3) {
			return true;
		}
		return false;
	}

}

输出:

class java.lang.String
class java.lang.String
====================
class java.lang.String
class java.lang.String
====================
class java.lang.String
====================
true

小结:class1 class2 class3,对于三种不同方式的三个不同引用直接比较,返回为true,说明class1 class2 class3 所指向的是同一地址,所以所指向的是同一对象,同一字节码对象。

附:特殊情况,基本类型和包装类型的字节码对象:

package mypackage基本类型和包装类型的字节码对象;

//8种基本类型和9种包装类型   包装类型Void没有对应的基本类型
//基本类型是值类型,包装类型是引用类型,
//又因为同一类在JVM只存放一份字节码对象
public class Test {

	public static void main(String[] args) {
		// boolean和Boolean
		System.out.println(boolean.class + " - " + Boolean.class + " - " + Boolean.TYPE);
		System.out.println(boolean.class == Boolean.TYPE);

		// char和Character
		System.out.println(char.class + " - " + Character.class + " - " + Character.TYPE);
		System.out.println(char.class == Character.TYPE);

		// byte和Byte
		System.out.println(byte.class + " - " + Byte.class + " - " + Byte.TYPE);
		System.out.println(byte.class == Byte.TYPE);

		// short和Short
		System.out.println(short.class + " - " + Short.class + " - " + Short.TYPE);
		System.out.println(short.class == Short.TYPE);

		System.out.println("====================================");// 看着头晕,画一条分割线

		// int和Integer
		System.out.println(int.class + " - " + Integer.class + " - " + Integer.TYPE);
		System.out.println(int.class == Integer.TYPE);

		// long和Long
		System.out.println(long.class + " - " + Long.class + " - " + Long.TYPE);
		System.out.println(long.class == Long.TYPE);

		// float和Float
		System.out.println(float.class + " - " + Float.class + " - " + Float.TYPE);
		System.out.println(float.class == Float.TYPE);

		// long和Long
		System.out.println(double.class + " - " + Double.class + " - " + Double.TYPE);
		System.out.println(double.class == Double.TYPE);
	}

}

输出:

boolean - class java.lang.Boolean - boolean
true
char - class java.lang.Character - char
true
byte - class java.lang.Byte - byte
true
short - class java.lang.Short - short
true
====================================
int - class java.lang.Integer - int
true
long - class java.lang.Long - long
true
float - class java.lang.Float - float
true
double - class java.lang.Double - double
true

小结:从上面基本类型.class==包装类型.Type,根据小结2,则int.class和Integer.Type指向的是同一字节码对象,理解清楚了基本类型和包装类型的字节码对象的关联关系。

2.3 小结

      字节码对象是Java反射机制的基础,获取到了字节码对象,后面才可以通过字节码对象获取构造器,新建对象,调用属性和方法,本小节中提供三种获取字节码对象的方法——.class属性,getClass()方法,Class.forName("全限定类名"),然后用代码解释JVM(Java虚拟机)中任何一个类(无论新建多少个对象)只保存一份字节码对象。

三、使用字节码对象获取构造器进而新建对象

3.1 从字节码对象到构造器

        获取字节码对象后,我们通过字节码对象获取类的构造器,然后使用构造器新建对象,且看3.2、3.3。

3.2 使用字节码对象获取构造器

package mypackage;
//获取构造器的步骤:

//1、获取字节码对象
//2、通过字节码对象获取构造器
//获取构造器的方法:
//public Constructor<?>[] getConstructors():该方法只能获取当前Class所表示类的public修饰的构造器
//public Constructor<?>[] getDeclaredConstructors():获取当前Class所表示类的所有的构造器,和访问权限无关
//public Constructor<T> getConstructor(Class<?>... parameterTypes) :获取当前Class所表示类中指定的一个public的构造器
//public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) :获取当前Class所表示类中指定的一个的构造

import java.lang.reflect.Constructor;

public class Test {

	public static void main(String[] args) throws Exception {
		getOne();
		System.out.println("==================");
		getAll();
	}

	// 调用一个构造器
	private static void getOne() throws Exception {
		Class<Student> class1 = Student.class;
		// 调用无参构造函数 Student()
		Constructor<Student> constructor = class1.getConstructor();
		System.out.println(constructor);
		// 调用指定参数构造函数 Student(String name)
		constructor = class1.getConstructor(String.class);
		System.out.println(constructor);
		// 调用指定参数构造函数 Student(String name,int age)
		constructor = class1.getConstructor(String.class, int.class);
		System.out.println(constructor);
		// 调用指定非public构造器
		constructor = class1.getDeclaredConstructor(String.class, int.class, int.class);
		System.out.println(constructor);
	}

	// 调用多个构造器
	private static void getAll() throws Exception {
		Class<Student> class1 = Student.class;

		Constructor<?>[] constructors = class1.getConstructors();
		for (Constructor<?> constructor : constructors) {
			System.out.println(constructor);
		}
		System.out.println("--------------------");
		constructors = class1.getDeclaredConstructors();
		for (Constructor<?> constructor : constructors) {
			System.out.println(constructor);
		}
	}
}

class Student {
	public Student() {

	}

	public Student(String name) {

	}

	public Student(String name, int age) {

	}

	private Student(String name, int age, int grade) {

	}
}

输出:

public mypackage.Student()
public mypackage.Student(java.lang.String)
public mypackage.Student(java.lang.String,int)
private mypackage.Student(java.lang.String,int,int)
==================
public mypackage.Student(java.lang.String,int)
public mypackage.Student(java.lang.String)
public mypackage.Student()
--------------------
private mypackage.Student(java.lang.String,int,int)
public mypackage.Student(java.lang.String,int)
public mypackage.Student(java.lang.String)
public mypackage.Student()

小结:Java反射机制中,获取构造器的四个方法,如:

     

如本小节代码所示,灵活的使用获取构造器的方法,可以用字节码对象获取任意一个构造器。

3.3 使用获取到的构造器新建对象

使用字节码获取到构造器之后,可以调用构造器新建对象。

示例代码:

package mypackage;

import java.lang.reflect.Constructor;

//步骤:
//1、获取字节码对象
//2、通过字节码对象获取构造器
//3、使用构造器新建对象
public class Test {

	public static void main(String[] args) throws Exception {
		Class<Student> class1 = Student.class;// 获取字节码对象
		// 调用无参构造函数Student()
		Constructor<Student> constructor = class1.getConstructor(); // 调用无参构造函数
		constructor.newInstance(); // 构造器新建对象

		// 调用带参构造函数Student(String name)
		constructor = class1.getConstructor(String.class);
		constructor.newInstance("小明");

		// 调用带参构造函数Student(String name,int age)
		constructor = class1.getConstructor(String.class, int.class);
		constructor.newInstance("小明", 12);

		// 调用带参构造函数Student(String name,int age,int grade)
		constructor = class1.getDeclaredConstructor(String.class, int.class, int.class);
		constructor.setAccessible(true); // 将私有构造函数设置为可以访问的
		constructor.newInstance("小明", 12, 98);
	}

}

class Student {
	public Student() {
		System.out.println("无参构造函数");
	}

	public Student(String name) {
		System.out.println("带参构造函数,name: " + name);
	}

	public Student(String name, int age) {
		System.out.println("带参构造函数,name: " + name + " ,age: " + age);
	}

	private Student(String name, int age, int grade) {
		System.out.println("带参构造函数,name: " + name + " ,age: " + age + " ,grade: " + grade);
	}
}

输出:

无参构造函数
带参构造函数,name: 小明
带参构造函数,name: 小明 ,age: 12
带参构造函数,name: 小明 ,age: 12 ,grade: 98

小结:新建对象的方法:public T newInstance(Object... initargs):如调用带参数的构造器,只能使用该方式.

如果是私有构造函数,新建对象前使用: 对象.setAccessible(true);  设置为可以访问的,如代码private Student(String name, int age, int grade)的调用。

附:特殊情况,前面我们是先获得字节码对象,然后使用字节码对象获取构造器,最后调用构造器新建对象,实际上,当一个类中的构造器是外界可以直接访问,同时没有参数.,那么可以直接使用 "字节码对象.newInstance()"  创建对象,如:

package mypackage1;

import java.lang.reflect.Constructor;

public class Test {

	public static void main(String[] args) throws Exception {
		Class<Student> class1 = Student.class;// 获取字节码对象
		// 调用无参构造函数Student()
		class1.newInstance();
		
	}

}

class Student {
	public Student() {
		System.out.println("无参构造函数");
	}
}

输出:

无参构造函数

这样,当某构造器满足公开无参时(默认无参构造器满足此条件),即可直接使用 "字节码对象.newInstance()"  创建对象,这为默认无参构造器的调用提供了快捷方式。

3.4  小结

      字节码对象是反射机制的基础,有了字节码对象,可以获取构造器,进而新建对象(实现了反射的基本要求,不使用new即可新建对象)。另外,提供一种附加方法,如果一个类中的构造器是外界可以直接访问,同时没有参数.,那么可以直接使用 "字节码对象.newInstance()"  创建对象,上面的附加代码中演示出来了。

四、使用字节码对象获取方法进而调用方法

4.1 从字节码对象到方法调用

      构造器不过是一种特殊的函数方法罢了,字节码对象不仅可以调用构造方法,而且可以调用普通方法,本节演示字节码对象获取普通方法进而调用方法的过程

4.2 字节码对象获取方法并调用,无返回值,返回值为void

代码——字节码对象获取方法并调用,无返回值,返回值为void:

package mypackage获取方法void;

import java.lang.reflect.Method;

//public Method[] getMethods():获取包括自身和继承过来的所有的public方法
//public Method[] getDeclaredMethods():获取自身类中所有的方法(不包括继承的,和访问权限无关)
//
//public Method getMethod(String methodName,
//                        Class<?>... parameterTypes):表示调用指定的一个公共的方法(包括继承的)
//public Method getDeclaredMethod(String name,
//                                Class<?>... parameterTypes):表示调用指定的一个本类中的方法(不包括继承的)

public class Test {

	public static void main(String[] args) throws Exception {
		Class class1 = Student.class;
		// 调用无参study()方法
		Method method = class1.getMethod("study");
		Object object = method.invoke(class1.newInstance()); // 无参构造参数,可以直接用字节码对象调用,不一定要用constructor构造器调用

		method = class1.getMethod("study", String.class);
		object = method.invoke(class1.newInstance(), "小明");

		method = class1.getDeclaredMethod("learning", String.class, int.class);
		method.setAccessible(true);
		object = method.invoke(class1.newInstance(), "小明", 12);

	}

}

class Student {
	public void study() {
		System.out.println("study");
	}

	public void study(String name) {
		System.out.println("study name: " + name);

	}

	private void learning(String name, int age) {
		System.out.println("learning  name: " + name + ",age: " + age);
	}
}

输出:

study
study name: 小明
learning  name: 小明,age: 12

小结:字节码对象获取方法的四个方法:

调用方法的一个方法:method.invoke

和调用构造器类似,若调用private私有方法,则调用前需  method.setAccessible(true);

如上代码所示,灵活的使用上述方法,可以使用字节码对象方便的调用任意一个方法,而不是使用类对象,这正好符合反射的思维。

上面演示的方法均返回为void,如果返回为非void,情况如何,且看下面。

4.3 字节码对象获取方法并调用,有返回值,返回值为String

代码——字节码对象获取方法并调用,有返回值,返回值为String:

package mypackage2获取方法调用方法String;

import java.lang.reflect.Method;

public class Test {

	public static void main(String[] args) throws Exception {
		Class class1 = Student.class;
		// 调用无参study()方法
		Method method = class1.getMethod("study");
		Object object = method.invoke(class1.newInstance()); // 无参构造参数,可以直接用字节码对象调用,不一定要用constructor构造器调用
		System.out.println(object);

		method = class1.getMethod("study", String.class);
		object = method.invoke(class1.newInstance(), "小明");
		System.out.println(object);

		method = class1.getDeclaredMethod("learning", String.class, int.class);
		method.setAccessible(true);
		object = method.invoke(class1.newInstance(), "小明", 12);
		System.out.println(object);
	}

}

class Student {
	public String study() {
		return "study";
	}

	public String study(String name) {

		return "study name: " + name;
	}

	private String learning(String name, int age) {
		return "learning  name: " + name + ",age: " + age;
	}
}

输出:

study
study name: 小明
learning  name: 小明,age: 12

小结:此段代码演示当调用的方法有返回值(这里以返回值为String为例)时,反射机制的处理情况,非常简单,只要打印调用方法后的结果即可。

上面演示的都是非static方法,如果是static方法,情况如何呢?且看下面.

4.4 字节码对象获取static方法并调用,无返回值,返回值为void

代码——字节码对象获取static方法并调用,无返回值,返回值为void:

package mypackage3反射调用静态方法void;

import java.lang.reflect.Method;


public class Test {

	public static void main(String[] args) throws Exception{
		Class  class1=Student.class;
		//调用无参study()方法
			Method method=class1.getMethod("study");
			Object object=method.invoke(class1.newInstance());  //无参构造参数,可以直接用字节码对象调用,不一定要用constructor构造器调用
			method.invoke(null);
			
			method=class1.getMethod("study", String.class);
			object=method.invoke(class1.newInstance(), "小明");
			method.invoke(null,"小张");
			
			method=class1.getDeclaredMethod("learning", String.class,int.class);
			method.setAccessible(true);
			object=method.invoke(class1.newInstance(), "小明",12);
			method.invoke(null,"小张",20);
	}

}
class Student{
	public static void study(){
		System.out.println("study");
	}
	public  static void study(String name){
		System.out.println("study name: "+name);

	}
	private static void learning(String name,int age){
		System.out.println("learning  name: "+name+",age: "+age);
	}
}

输出:

study name: 小张
learning  name: 小明,age: 12
learning  name: 小张,age: 20

小结:使用反射调用静态方法时,静态方法不属于任何对象,静态方法属于类本身. 所以此时把invoke方法的第一个参数设置为null即可.如果一定要第一个实参设为类对象,也是可以,使用class1.newInstance()。

理由:Java中非static方法只能用对象名调用,因为非static方法只有在对象存在时才有意义,而static方法属于类,可以用类名调用,可以用对象名调用。使用反射实现时,也遵循了同样的原则,非static方法第一个实参一定为class1.newInstance(),static方法第一个实参可以为class1.newInstance(),可以为null。

上面的static方法返回值为void,当返回值为非void,情况如何,且见下面。

4.5 字节码对象获取static方法并调用,有返回值,返回值为String

代码——字节码对象获取static方法并调用,有返回值,返回值为String:

package mypackage4反射调用静态方法String;

import java.lang.reflect.Method;

public class Test {

	public static void main(String[] args) throws Exception {

		Class class1 = Student.class;
		// 调用无参study()方法
		Method method = class1.getMethod("study");
		Object object = method.invoke(class1.newInstance()); // 无参构造参数,可以直接用字节码对象调用,不一定要用constructor构造器调用
		System.out.println(object);
		object = method.invoke(null);
		System.out.println(object);

		method = class1.getMethod("study", String.class);
		object = method.invoke(class1.newInstance(), "小明");
		System.out.println(object);
		object = method.invoke(null, "小张");
		System.out.println(object);

		method = class1.getDeclaredMethod("learning", String.class, int.class);
		method.setAccessible(true);
		object = method.invoke(class1.newInstance(), "小明", 12);
		System.out.println(object);
		object = method.invoke(null, "小张", 20);
		System.out.println(object);
	}

}

class Student {
	public static String study() {
		return "study";
	}

	public static String study(String name) {

		return "study name: " + name;
	}

	private static String learning(String name, int age) {
		return "learning  name: " + name + ",age: " + age;
	}
}

输出:

study
study
study name: 小明
study name: 小张
learning  name: 小明,age: 12
learning  name: 小张,age: 20

小结: 此段代码演示当调用的static方法有返回值(这里以返回值为String为例)时,反射机制的处理情况,非常简单,只要打印调用方法后的结果即可。

当函数参数为可变参数(数组)时,如何处理,且见下面代码.

4.6 演示参数列表为可变参数(数组)时的情况

代码——演示参数列表为可变参数(数组)时的情况:

package mypackage5反射调用数组参数;

import java.lang.reflect.Method;
import java.util.Arrays;

public class Test {

	public static void main(String[] args) throws Exception {
		Class class1 = Student.class;
		Method method = class1.getMethod("learning1", int[].class);
		method.invoke(null, new Object[] { new int[] { 1, 2, 3, 4, 5 } });

		method = class1.getMethod("learning2", String[].class);
		method.invoke(null, new Object[] { new String[] { "A", "B", "C", "D", "E" } });

		method = class1.getMethod("learning3", int[].class);
		method.invoke(class1.newInstance(), new Object[] { new int[] { 1, 2, 3, 4, 5 } });

		method = class1.getMethod("learning4", String[].class);
		method.invoke(class1.newInstance(), new Object[] { new String[] { "A", "B", "C", "D", "E" } });

		System.out.println("=============================="); // 加一行分割线,看得清楚一点
		method = class1.getMethod("learning5", int[].class);
		Object object = method.invoke(null, new Object[] { new int[] { 1, 2, 3, 4, 5 } });
		System.out.println(object);

		method = class1.getMethod("learning6", String[].class);
		object = method.invoke(null, new Object[] { new String[] { "A", "B", "C", "D", "E" } });
		System.out.println(object);

		method = class1.getMethod("learning7", int[].class);
		object = method.invoke(class1.newInstance(), new Object[] { new int[] { 1, 2, 3, 4, 5 } });
		System.out.println(object);

		method = class1.getMethod("learning8", String[].class);
		object = method.invoke(class1.newInstance(), new Object[] { new String[] { "A", "B", "C", "D", "E" } });
		System.out.println(object);

	}

}

class Student {
	// static int数组 void返回值
	public static void learning1(int... array) {
		System.out.println("learning1被调用, " + Arrays.toString(array));
	}

	// static String数组 void返回值
	public static void learning2(String... array) {
		System.out.println("learning2被调用, " + Arrays.toString(array));
	}

	// 非static int数组 void返回值
	public void learning3(int... array) {
		System.out.println("learning3被调用, " + Arrays.toString(array));
	}

	// 非static String数组 void返回值
	public void learning4(String... array) {
		System.out.println("learning4被调用, " + Arrays.toString(array));
	}

	// static int数组 String返回值
	public static String learning5(int... array) {
		return "learning5被调用, " + Arrays.toString(array);
	}

	// static String数组 String返回值
	public static String learning6(String... array) {
		return "learning6被调用, " + Arrays.toString(array);
	}

	// 非static int数组 String返回值
	public String learning7(int... array) {
		return "learning7被调用, " + Arrays.toString(array);
	}

	// 非static String数组 String返回值
	public String learning8(String... array) {
		return "learning8被调用, " + Arrays.toString(array);
	}

}

输出:

learning1被调用, [1, 2, 3, 4, 5]
learning2被调用, [A, B, C, D, E]
learning3被调用, [1, 2, 3, 4, 5]
learning4被调用, [A, B, C, D, E]
==============================
learning5被调用, [1, 2, 3, 4, 5]
learning6被调用, [A, B, C, D, E]
learning7被调用, [1, 2, 3, 4, 5]
learning8被调用, [A, B, C, D, E]

小结:此段代码演示参数列表为可变参数(数组)的时候的情况,基本涵盖了所有的数组参数的情况。

4.7  小结

       字节码对象获取方法进而调用方法,通过代码1~代码5,演示了非static/static、返回值void/返回值非static、固定参数/可变参数列表的情况,通过上面的代码,字节码对象对方法的调用基本上实现所有类对象对方法的调用。

五、小结

       高级语言反射机制在框架设计广泛运用,本文浅析Java反射机制,从获取字节码对象,到构造方法获取与调用,普通方法获取与调用,希望可以在读者学习Java过程中略尽绵薄之力。

天天打码,天天进步!

发布了177 篇原创文章 · 获赞 31 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/qq_36963950/article/details/103038381