2021-10-25 Java的反射技术(Class类,Constructor类,Method类, Field类)

目录

为什么要使用反射 

如何使用反射

Class类

class类的常用方法 

Constructor类

1.Constructor类代表某个类中的一个构造方法

2.创建实例对象

Method类

1.Method类代表某个类中的一个成员方法

2.调用方法

Field类

1.Field类代表某个类中的一个成员变量

实例演示

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

反射:类中的方法 Method

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

反射技术优缺点


原文链接——https://blog.csdn.net/z714405489/article/details/84641183

这章看的人好晕,好in的知识,,,代码能看懂看不懂解释,,,

为什么要使用反射 

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

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

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

如何使用反射

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

Class类

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

Class类是所有类的共同的图纸:

  • 每个类有自己的对象,同时每个类也看做是一个对象,有共同的图纸Class,存放类的结构信息,能够通过相应方法取出相应的信息:类的名字、属性、方法、构造方法、父类和接口。
  • 总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int,void…

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

  • Constructor类,Method类, Field类

class类的常用方法 

    • static <?>forName(String className)

      返回与给定字符串名称的类或接口相关联的类对象。

    • Constructor<T>getConstructor(<?>... parameterTypes)

      返回一个 Constructor对象,该对象反映 Constructor对象表示的类的指定的公共类函数。

      Constructor<?>[]getConstructors()

      返回包含一个数组 Constructor对象反射由此表示的类的所有公共构造类对象

    • TnewInstance()

      创建由此类对象表示的类的新实例。 

    • 方法getMethod(String name, <?>... parameterTypes)

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

      方法[]getMethods()

      返回包含一个数组方法对象反射由此表示的类或接口的所有公共方法类对象,包括那些由类或接口和那些从超类和超接口继承的声明。

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类

1.Method类代表某个类中的一个成员方法

  • 得到类中的某一个方法

例子:

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

2.调用方法

  • 通常方式://charAt() 方法可返回指定位置的字符
System.out.println(str.charAt(1));
  • 反射方式://invoke
System.out.println(charAt.invoke(str, 1)); 

如果传递给Method对象的invoke()方法的第一个参数为null,这有着什么样的意义呢?说明该Method对象对应的是一个静态方法!

Field类

1.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!");
	}
}

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

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();
			
		}
}

反射:类中的方法 Method

/**
 * 
 */
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" });
	}

}

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

/**
 * 
 */
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反射机制只要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用
    • 使用反射会模糊程序内部逻辑:程序员希望在代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值