Java的反射技术(Class类,Constructor类,Method类, Field类)

Java编码时知道类和对象的具体信息,此时直接对类和对象进行操作即可,无需反射 如果编码时不知道类或者对象的具体信息,此时应该使用反射来实现

为什么要使用反射

  1. 反射就是把Java类中的各种成分映射成一个个的java对象。例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。

反射技术常见于框架中。
比如类的名称放在XML文件中,属性和属性值放在XML文件中,需要在运行时读取XML文件,动态获取类的信息。
在编译时根本无法知道该对象或类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息。

反射的作用:创建对象、操作属性、调用方法

如何使用反射

掌握反射技术的要点在于:如何从一个class中反射出各个组成部分。反射出来的对象怎么用。

Class类

Class类:代表一个类,是Java反射机制的起源和入口,用于获取与类相关的各种信息
提供了获取类信息的相关方法(Class类继承自Object类)

Class类是所有类的共同的图纸
每个类有自己的对象,同时每个类也看做是一个对象,有共同的图纸Class,存放类的结构信息,能够通过相应方法取出相应的信息:类的名字、属性、方法、构造方法、父类和接口。

总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int,void…
反射就是把Java类中的各种成分映射成一个个的java对象。例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。

那么,既然反射的作用是创建对象、操作属性、调用方法,要实现以上3个作用,需要用到下面介绍的3个类:Constructor类,Method类, Field类

Constructor类

(1)Constructor类代表某个类中的一个构造方法
得到某个类所有的构造方法:
例子:

Constructor [] constructors= Class.forName("java.lang.String").getConstructors();

得到某一个构造方法:
例子: //获得方法时要用到类型

 Constructor constructor = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);	

(2)创建实例对象:
通常方式:

String str = new String(new StringBuffer("abc"));

反射方式:

String str = (String)constructor.newInstance(new StringBuffer("abc"));

Class.newInstance()方法:
例子:


String obj = (String)Class.forName("java.lang.String").newInstance();

该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。

Method类

Method类代表某个类中的一个成员方法
得到类中的某一个方法——
例子:

Method charAt = Class.forName("java.lang.String").getMethod("charAt", int.class);

调用方法——
通常方式:

System.out.println(str.charAt(1));

反射方式:

System.out.println(charAt.invoke(str, 1)); 

如果传递给Method对象的invoke()方法的第一个参数为null,这有着什么样的意义呢?说明该Method对象对应的是一个静态方法!
jdk1.4和jdk1.5的invoke方法的区别:
Jdk1.5:public Object invoke(Object obj,Object… args)
Jdk1.4:public Object invoke(Object obj,Object[] args),即按jdk1.4的语法,需要将一个数组作为参数传递给invoke方法时,数组中的每个元素分别对应被调用方法中的一个参数,所以,调用charAt方法的代码也可以用Jdk1.4改写为 charAt.invoke(“str”, new Object[]{1})形式。

Field类

Field类代表某个类中的一个成员变量
问题:得到的Field对象是对应到类上面的成员变量,还是对应到对象上的成员变量?类只有一个,而该类的实例对象有多个,如果是与对象关联,哪关联的是哪个对象呢?所以字段fieldX 代表的是x的定义,而不是具体的x变量。(注意访问权限的问题)
示例代码:

ReflectPoint point = new ReflectPoint(1,7);
	Field y = Class.forName("cn.itcast.corejava.ReflectPoint").getField("y");
	System.out.println(y.get(point));
	//Field x = Class.forName("cn.itcast.corejava.ReflectPoint").getField("x");
	Field x = Class.forName("cn.itcast.corejava.ReflectPoint").getDeclaredField("x");
	x.setAccessible(true);
	System.out.println(x.get(point));

实例演示

首先,我们自定义一个Person类,它是我们将要进行反射的目标。.
在这个类里面,我们定义了:
1.构造方法
2.实例方法
3.属性

package cn.itcast.reflect;

import java.io.InputStream;
import java.util.List;

public class Person {

	public String name = "yaoer";
	private int password = 123;
	private static int age = 23;

	public Person() {
		System.out.println("person");
	}

	public Person(String name) {
		System.out.println(name);
	}

	public Person(String name, int password) {
		System.out.println(name + ":" + password);
	}

	private Person(List list) {
		System.out.println("list");
	}

	public void aa1() {
		System.out.println("aaa1");
	}

	public void aa1(String name, int password) {
		System.out.println(name + ":" + password);
	}

	public String aa1(String name, int[] password) {
		return new String("adad");
	}

	private void aa1(InputStream in) {
		System.out.println(in);
	}

	public static void aa1(int num) {
		System.out.println(num);
	}

	public static void main(String[] args) {
		System.out.println("main!");
	}
}

反射:类的构造函数 ,创建类的对象

package cn.itcast.reflect;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

//解剖(反射)类的构造函数 ,创建类的对象
public class Demo2 {

	// 1——反射构造函数:public Person()
	@Test
	public void test1() throws Exception {

		Class<?> clazz = Class.forName("cn.itcast.reflect.Person");
		Constructor<?> c = clazz.getConstructor(null);

		Person p = (Person) c.newInstance(null);

		System.out.println(p.name);
	}

	// 2——反射构造函数:public Person(String name)
	@Test
	public void test2() throws Exception {

		Class<?> clazz = Class.forName("cn.itcast.reflect.Person");
		Constructor<?> c = clazz.getConstructor(String.class);

		Person p = (Person) c.newInstance("xxxooo");

		System.out.println(p.name);
	}

	// 3——反射构造函数:public Person(String name,int password)
	@Test
	public void test3() throws Exception {

		Class<?> clazz = Class.forName("cn.itcast.reflect.Person");
		Constructor<?> c = clazz.getConstructor(String.class,int.class);

		Person p = (Person) c.newInstance("xxxooo",20);

		System.out.println(p.name);
	}
	
	// 4——反射构造函数:private Person(List list)
		@Test
		public void test4() throws Exception {

			Class<?> clazz = Class.forName("cn.itcast.reflect.Person");
			Constructor<?> c = clazz.getDeclaredConstructor(List.class);

			c.setAccessible(true); //暴力反射
			Person p = (Person) c.newInstance(new ArrayList());

			System.out.println(p.name);
		}
		
		@Test
		public void test5() throws Exception {

			Class<?> clazz = Class.forName("cn.itcast.reflect.Person");
			Person p = (Person) clazz.newInstance();
			
		}
}

反射:类中的方法

/**
 * 
 */
package cn.itcast.reflect;

import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;

import org.junit.Test;

/**
 * 反射类中的方法
 *
 */
public class Demo3 {
	// 反射类的方法: public void aa1(){
	@Test
	public void test1() throws Exception {

		Class clazz = Class.forName("cn.itcast.reflect.Person");
		Method method = clazz.getMethod("aa1", null);
		Object obj = clazz.newInstance();
		method.invoke(obj, null);
	}

	// 反射类的方法: public void aa1(String name,int password){
	@Test
	public void test2() throws Exception {

		Class clazz = Class.forName("cn.itcast.reflect.Person");
		Method method = clazz.getMethod("aa1", String.class, int.class);
		Object obj = clazz.newInstance();
		method.invoke(obj, "yaoer", 24);
	}

	// 反射类的方法: public void aa1(String name,int[] password){
	@Test
	public void test3() throws Exception {

		Class clazz = Class.forName("cn.itcast.reflect.Person");
		Method method = clazz.getMethod("aa1", String.class, int[].class);
		int[] a = new int[] { 1, 2, 3 };
		Object obj = clazz.newInstance();
		System.out.println(method.invoke(obj, "yaoer", a));
	}

	// 反射类的方法:private void aa1(InputStream in)
	@Test
	public void test4() throws Exception {

		Class clazz = Class.forName("cn.itcast.reflect.Person");
		Method method = clazz.getDeclaredMethod("aa1", InputStream.class);// private
		method.setAccessible(true);
		Object obj = clazz.newInstance();
		System.out.println(method.invoke(obj, new FileInputStream("c://1.txt")));// 对应目录下需要存在此文件
	}

	// 反射类的方法:public static void aa1(int num) {
	@Test
	public void test5() throws Exception {

		Class clazz = Class.forName("cn.itcast.reflect.Person");
		Object obj = clazz.newInstance();
		Method m = clazz.getMethod("aa1", int.class);
		m.invoke(obj, 23);
	}

	// 反射类的方法: public static void main(){
	@Test
	public void test6() throws Exception {

		Class clazz = Class.forName("cn.itcast.reflect.Person");
		Method method = clazz.getMethod("main", String[].class);
		// method.invoke(null, new Object[] {new String[] {"aa","bb"}});
		method.invoke(null, (Object) new String[] { "aa", "bb" });
	}

}

反射:类中的字段(属性)

/**
 * 
 */
package cn.itcast.reflect;

import java.lang.reflect.Field;

import org.junit.Test;

/**
 * 反射字段
 *
 */
public class Demo5 {

	// 反射字段:public String name = "yaoer";
	@Test
	public void test1() throws Exception {
		Class clazz = Class.forName("cn.itcast.reflect.Person");
		Object obj = clazz.newInstance();
		Field f = clazz.getField("name");
		// 获取字段的值
		Object val = f.get(obj);

		// 获取字段的类型
		Class type = f.getType();

		if (type.equals(String.class)) {
			String sval = (String) val;
			System.out.println(sval);
		}

		// 设置字段的值
		f.set(obj, "zhuzhu");
		System.out.println(f.get(obj));

	}

	// 反射字段:private int password;;
	@Test
	public void test2() throws Exception {
		Class clazz = Class.forName("cn.itcast.reflect.Person");
		Object obj = clazz.newInstance();
		Field f = clazz.getDeclaredField("password");
		f.setAccessible(true);// 改变访问权限

		System.out.println(f.get(obj));

	}

	// 反射字段:private static int age = 23;
	@Test
	public void test3() throws Exception {
		Class clazz = Class.forName("cn.itcast.reflect.Person");
		Object obj = clazz.newInstance();
		Field f = clazz.getDeclaredField("age");
		f.setAccessible(true);// 改变访问权限

		System.out.println(f.get(obj));

	}

}

反射技术优缺点

  • 优点

反射提高了Java程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,无需提高硬编码目标类
反射是其他一些常用语言,如C、C++、Fortran或者Pascal等不具备的
Java反射技术应用领域很广,如软件测试、JavaBean等
许多流行的开源框架例如Struts、Hibernate、Spring在实现过程中都采用了该技术

  • 缺点

性能问题:使用反射基本上是一种解释操作哦,用于字段和方法接入时要远慢于直接代码。因此Java反射机制只要应用在对;灵活性和扩展性要求很高的系统框架上,普通程序不建议使用
使用反射会模糊程序内部逻辑:程序员希望在代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂

参考文章:https://blog.csdn.net/Elias94/article/details/80361035

你可能感兴趣的:(JavaSE,JavaWeb,反射,java,框架,解剖)