Java反射机制小结

一、概念定义

反射机制:反射提供了一种动态的功能,这种动态功能非常强大。它主要体现 在通过反射相关的API就可以知道一个陌生Java类的所有信息,包括属性、方法、构造器等。而且元素完全可以在运行时动态的进行创建或调用,而不必在JVM运行时就进行确定。即运行状态中对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能即反射机制。

反射机制也是Java被视为动态语言的关键原因,提供以下功能:

(1)在运行时判断任意一个对象所属的类
(2)在运行时构造任意一个类对象
(3)在运行时判断任意一个类所具有的成员变量和方法
(4)在运行时调用任一个对象的方法

(5)在运行时创建新类对象

二、类的加载分析

1、 Java用Class类代表所有的类,方便了开发者掌控类信息。通过Class开发者可以得到属性(Field)、方法(Method)、构造器(Constructor)、修饰符(Modifier)等信息。在动态获取这些信息以后,开发者就可以用该Class创建实例、调用方法、访问方法、访问属性等操作,这也是反射的主要用途。反射机制的API主要集中在java.lang.reflect包下面。

通过上面的一段话,我们知道Class是用来记录一个类的各种信息的,它伴随类的加载而创建,问题随之而来:类会在什么时候被加载到JVM中呢?总结以下几种情况:

(1)需要使用该类创建对象,如下所示:

Student stu = new Student();

(2)访问该类的静态成员,如下所示:

System.out.println(Student.count);
(3)使用Class类的静态forName()方法,动态加载一个指定类名的类,如下所示:
Class.forName("com.test.Student");
2、不论以什么样的方式类一旦被加载到JVM中,就会为它创建一个Class类实例对象。所以问题又来了,开发者如何得到 这个Class对象呢?总结以下三种途径:

(1)Object类的getClass()方法,它返回的是对象的运行时类的Class对象。

Student stu = new Student();
Class<?> clazz = stu.getClass();

(2)类的Class静态属性,每个类都会有这个静态属性通过它可以获取到Class对象

Class<?> clazz = Student.class;

(3)Class的forName()方法,该方法返回值就是Class类型,也就是动态导入类的Class对象的引用

Class<?> clazz = Class.forName("com.test.Student");
三、应用举例

(参考博客http://blog.csdn.net/yongjian1092/article/details/7364451,在此声明微笑):

public class Test {
	
	public int pubIntField;
	public String pubStringField;
	private int prvIntField;
	
	public Test(){
		Log("Default Constructor.");
	}
	
	Test(int arg1, String arg2){
		pubIntField = arg1;
		pubStringField = arg2;
		Log("Constructor with parameters.");
	}
	
	public void setIntField(int val){
		this.prvIntField = val;
	}
	public int getIntField(){
		return prvIntField;
	}
	
	private void Log(String msg) {
		System.out.println("Test: " + msg);
	}
	
}
public class ExtendTest extends Test {

	public int pubIntExtendField;
	public String pubStringExtendField;
	private int prvIntExtendField;
	
	public ExtendTest(){
		Log("Default Constructor.");
	}
	
	ExtendTest(int arg1, String arg2){
		pubIntExtendField = arg1;
		pubStringExtendField = arg2;
		Log("Constructor with parameters.");
	}
	
	public void setIntExtendField(int val){
		this.prvIntExtendField = val;
	}
	public int getIntExtendField(){
		return prvIntExtendField;
	}
	
	private void Log(String msg){
		System.out.println("ExtendTest: " + msg);
	}
}
1、通过反射机制获取Class对象
调用getClass

Boolean var1 = true;

Class<?> classType2 = var1.getClass();

System.out.println(classType2);

输出:class java.lang.Boolean

运用.class 语法

Class<?> classType4 = Boolean.class;

System.out.println(classType4);

输出:class java.lang.Boolean

运用static method Class.forName()

Class<?> classType5 = Class.forName("java.lang.Boolean");

System.out.println(classType5);

输出:class java.lang.Boolean

运用primitive wrapper classes的TYPE 语法

这里返回的是原生类型,和Boolean.class返回的不同

Class<?> classType3 = Boolean.TYPE;

System.out.println(classType3);        

输出:boolean

/**获取类的Class对象*/
//1、调用getClass()方法来获取Class
ExtendTest test = new ExtendTest(12,"Ok");
Class<?> classType = test.getClass();
System.out.println(classType);
//2、运用.class语法
Class<?> classType1 = ExtendTest.class;
System.out.println(classType1);
//3、运用static method Class.forName()
Class<?> classType2 = Class.forName("ReflectionTest.ExtendTest");
System.out.println(classType2);
System.out.println();

2、通过反射机制获取类的Fields属性

 

public FieldgetField(String name) 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段
public Field[] getFields() 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段
public FieldgetDeclaredField(Stringname) 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段
public Field[] getDeclaredFields()

返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段

/**获取类的Fields,通过反射机制获取类的某个属性
 * getFields()与getDeclaredFields()区别:
 * (1)getFields()返回的是声明为public的属性,包括父类中定义
 * (2)getDeclaredFields()返回的是指定类定义的所有定义的属性,不包括父类的
 * */
//1、通过getFields()方法获取属性
Field[] fields = classType.getFields();
for(Field field : fields)
	System.out.println(field);
System.out.println();
//2、通过getDeclaredFields()方法获取属性
fields = classType.getDeclaredFields();
for(Field field : fields)
	System.out.println(field);
System.out.println();
3、通过反射机制获取类的Method方法

public MethodgetMethod(String name,Class<?>... parameterTypes)

返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法

public Method[] getMethods()

返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法

public MethodgetDeclaredMethod(Stringname,Class<?>... parameterTypes)

返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法

public Method[] getDeclaredMethods()

返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法

/**获取类的Method,通过反射机制获取类的某个方法*/
//1、使用getMehtods()方法获取函数
Method[] methods = classType.getMethods();
for(Method method : methods)
	System.out.println(method);
System.out.println();
//2、使用getDeclaredMethod获取函数
methods = classType.getDeclaredMethods();
for(Method method : methods)
	System.out.println(method);
System.out.println();
4、通过反射机制获取类的Constructor构造函数

public Constructor<T> getConstructor(Class<?>... parameterTypes)

返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法

public Constructor<?>[] getConstructors()

返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法

public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法

public Constructor<?>[] getDeclaredConstructors()

返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。它们是公共、保护、默认(包)访问和私有构造方法

/**获取类的Constructor,通过反射机制获取类的构造器*/
//1、使用getConstructors获取构造器
Constructor<?>[] constructors = classType.getConstructors();
for(Constructor<?> constructor : constructors)
	System.out.println(constructor);
System.out.println();
//2、使用getDeclaredConstructor获取构造器
constructors = classType.getDeclaredConstructors();
for(Constructor<?> constructor : constructors)
	System.out.println(constructor);
System.out.println();
5、通过反射机制创建类实例、调用类函数,通过反射机制调用类函数

调用无自变量ctor

1、调用类的Class对象的newInstance方法,该方法会调用对象的默认构造器,如果没有默认构造器,会调用失败.

Class<?> classType = ExtendType.class;

Object inst = classType.newInstance();

System.out.println(inst);

输出:

Type:Default Constructor

ExtendType:Default Constructor

com.quincy.ExtendType@d80be3

 

2、调用默认Constructor对象的newInstance方法

Class<?> classType = ExtendType.class;

Constructor<?> constructor1 = classType.getConstructor();

Object inst = constructor1.newInstance();

System.out.println(inst);

输出:

Type:Default Constructor

ExtendType:Default Constructor

com.quincy.ExtendType@1006d75

调用带参数ctor

3、调用带参数Constructor对象的newInstance方法

Constructor<?> constructor2 =

classType.getDeclaredConstructor(int.class, String.class);

Object inst = constructor2.newInstance(1, "123");

System.out.println(inst);

输出:

Type:Default Constructor

ExtendType:Constructor with parameters

com.quincy.ExtendType@15e83f9

Object instance = classType.newInstance();
Method logMethod = classType.getDeclaredMethod("Log", String.class);
logMethod.invoke(instance, "OK?");

6、通过反射机制获取/设置类属性值

Field intField = classType.getField("pubIntExtendField");
intField.setInt(instance, 100);
int val = intField.getInt(instance);


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java反射机制是指在运行时动态地获取一个类的信息,并可以操作类的属性、方法和构造器等。Java反射机制可以使程序员在运行时动态地调用类的方法和属性,扩展类的功能,并可以实现注解、工厂模式以及框架开发等。 Java反射机制的原理如下:首先,Java编译器将Java源代码编译为字节码文件,字节码文件中包含着类的信息,这些信息包括类的名称、方法、属性和构造器等等。接着,Java虚拟机将字节码文件加载到内存中,然后通过类加载器将类加载到内存中形成一个类对象,这个类对象可以操作字节码文件中的信息。 使用Java反射机制的过程如下:首先获取类对象,通过类对象来获取类的构造器、属性、方法等信息,然后调用构造器来创建对象,通过属性获取和设置类的成员属性,通过方法调用类的方法等。 Java反射机制的优点是可以在运行时动态地得到类的信息,使得程序员在程序运行时能够对类进行更加灵活的操作,并可以使得程序更加通用化,同时也存在着一定的性能问题,因为Java反射机制需要Java虚拟机进行一定的额外处理,所以在程序运行时需要进行额外的时间和资源消耗。 总之,Java反射机制Java语言的一项重要特性,在Java开发中广泛应用,在代码编写、框架开发以及API开发中具有重要作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值