反射-JavaEE

本文详细介绍了JavaEE中的反射机制,包括通过Class、Constructor、Method、Field等类动态获取类信息、创建对象、调用方法和访问属性。此外,还展示了如何通过反射实例化不同构造方法的对象,调用无参、有参及私有方法,以及获取和修改属性值。反射机制在JavaEE开发中扮演重要角色,提供灵活性和可扩展性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、介绍

1.前言

2.作用

3.概述

二、类类

1.类类的作用

2.类类的读取

2.1.Class.forName("");

2.2.实例化.getClass();

2.3.类.class

三、反射实例化

1.无参构造

2.有一参构造

3.多参构造

4.有一参且私有构造

5.有多且私有构造

四、反射方法

1.无参

2.有参

3.私有且多参

五、反射属性

1.获取属性

2.获取属性修改


一、介绍

JavaEE中的反射(Reflection)指的是通过Java代码动态地获取类、方法、属性等信息的机制。JavaEE应用程序通常需要处理大量的类和对象,有时候我们需要在代码中动态地获取这些类、对象的信息或者动态地创建这些对象,这就需要利用反射机制。

1.前言

JavaEE(Java Enterprise Edition)是Java平台上的一种开发规范和标准。它包含了一系列API和技术,可以帮助开发者构建企业级的Java应用程序。反射是Java语言中的一种机制,它允许程序在运行时动态地获取类的信息、创建类的对象、调用类的方法、访问/修改类的属性等。JavaEE中的一些技术,如Servlet和JSP,也使用了反射机制。通过反射,我们可以在运行时动态地获取类的信息,从而使得编程更加灵活和便捷。在JavaEE开发中,反射是一种非常重要的技术,它可以帮助我们实现很多高级功能。对于JavaEE开发者来说,掌握反射技术是十分必要的。

2.作用

JavaEE开发中的反射机制主要有以下几个作用:

  1. 动态获取类的信息:JavaEE应用程序通常需要处理大量的类和对象。有时候,我们需要在代码中获取一个类的名字、父类、接口、构造函数列表、方法列表、属性列表等信息。通过反射机制,我们可以在运行时动态地获取这些信息,从而使得程序更加灵活和可扩展。

  2. 动态创建对象:有时候,我们不知道程序运行时需要创建哪些类的对象。通过反射机制,我们可以在运行时动态地创建对象,并调用它们的方法或修改它们的属性。

  3. 动态调用方法:JavaEE开发中的许多技术(如Servlet和JSP)都使用了反射机制来动态地调用方法。通过反射机制,我们可以在运行时动态地调用一个对象的方法,而不需要提前知道这个方法的具体名称、参数类型和返回值类型。

  4. 动态修改属性值:有时候,我们需要在程序运行时动态修改对象的属性值。通过反射机制,我们可以在程序运行时得到一个对象的属性列表,然后像访问和修改普通属性一样来处理它们。

3.概述

反射机制极大地提高了JavaEE应用程序的灵活性和可扩展性。利用反射机制,我们可以在程序运行期间动态地获取类、创建对象、调用方法、访问属性等,这使得我们可以在不知道对象类型、方法名等信息的情况下动态地调用方法,或者动态地获取属性值。比如在Servlet、JSP等技术中就大量使用了反射机制。同时,反射机制也为一些高级技术的实现提供了基础,如动态代理、AOP、ORM等。总之,反射是JavaEE开发中非常常用的技术之一,熟练掌握反射机制是JavaEE开发人员必须的技能之一。

二、类类

1.类类的作用

以下五类是JavaEE中反射的类类核心

1. Class 类:Class 类是 Java 反射机制的核心。所有 Java 类都有一个对应的 Class 对象用于反射。通过 Class 类,我们可以获取一个类的名字、父类、接口、构造函数列表、方法列表、属性列表等。我们还可以通过 Class 类创建对象实例,或者动态调用类的方法。

2. Constructor 类:Constructor 类用于描述 Java 类中的构造函数。通过 Constructor 类,我们可以获取构造函数的参数类型列表,以及创建该类的对象实例。

3. Method 类:Method 类用于描述 Java 类中的方法。通过 Method 类,我们可以获取方法的名字、参数类型列表、返回值类型等信息,以及动态地调用方法。

4. Field 类:Field 类用于描述 Java 类中的属性。通过 Field 类,我们可以获取属性的名字、类型、修饰符等信息,以及动态地访问和修改属性值。

5. Modifier 类:Modifier 类用于描述 Java 类中修饰符的信息。通过 Modifier 类,我们可以获取修饰符的名称、值以及与修饰符相关的一些操作。

通过使用这些类,我们可以在 JavaEE 开发中实现许多高级功能,比如动态创建对象、动态调用方法、动态修改属性值等。同时,我们也可以利用反射机制来调试、测试、分析和优化 Java 应用程序。

2.类类的读取

例如:现在创建一个人类[实体对象]代码如下

package com.SAME_LOVE.reflective;
/**
 * @author SAME_LOVE
 * @com.SAME_LOVE.reflective
 * @Person(说明):人类[实体对象]
 */
public class Person {

	private String pid;
	private String name;
	private Integer age;
	
	static {
		System.out.println("已加载到jvm中");
	}
	
	public Person() {
		super();
		System.out.println("已调用无参构造方法创建了一个人类对象");
	}
	
	public Person(String pid) {
		super();
		System.out.println("已调用带一个参数构造方法创建了一个人类对象");
		this.pid = pid;
	}
	
	public Person(String pid, String name, Integer age) {
		super();
		System.out.println("已调用多参构造方法创建了一个人类对象");
		this.pid = pid;
		this.name = name;
		this.age = age;
	}
	
	@SuppressWarnings("unused")
	private Person(Integer age) {
		this.age = age;
		System.out.println("已调用Person类中带一个参数并且私有的构造方法创建了一个人类对象");
	}


    @SuppressWarnings("unused")
	private Person(String name,Integer age) {
		this.name = name;
		this.age = age;
		System.out.println("已调用Person类中多参数并且私有的构造方法创建了一个人类对象");
	}


	public void hello() {
		System.out.println("你好!我是" + this.name);
	}

	public void hello(String name) {
		System.out.println(name + ";你好!我是" + this.name);
	}

	@SuppressWarnings("unused")
	private Integer add(Integer a, Integer b) {
		return new Integer(a.intValue() + b.intValue());
	}
	
	

	@Override
	public String toString() {
		return "Person [pid=" + pid + ", name=" + name + ", age=" + age + "]";
	}
	public String getPid() {
		return pid;
	}
	public void setPid(String pid) {
		this.pid = pid;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	
}
2.1.Class.forName("");

通过类的全限定名获取Class对象:

		//实例化
		Person p = new Person();
		try {
			//类的读取
			Class c1 = Class.forName("com.SAME_LOVE.reflective.Person");
//			System.out.println(c1);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
2.2.实例化.getClass();

通过类的实例获取Class对象:

		//实例化
		Person p = new Person();
		Class c2 = p.getClass();
		System.out.println(c2);
2.3.类.class

通过类字面常量获取Class对象:

	//实例化
    Person p = new Person();   
    Class c3 = Person.class;
    System.out.println(c3);

以上测试后输出的结果皆为:

三、反射实例化

通过反射机制可以实现在运行时根据类的名称动态地创建对象实例,实例化过程中可以指定构造函数及其参数。

综上Person类的所以代码进行测试

1.无参构造

		// 实例化
		Person p = new Person();
		Class c = null;
		try {
			// 类的读取
			c = Class.forName("com.SAME_LOVE.reflective.Person");
			// System.out.println(c1);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		// 1.调用无参构造方法反射实例化
		try {
		 //强制类型转换为实际对象
			Person p1 = (Person) c.newInstance();
			System.out.println(p1);
		} catch (Exception e) {
			e.printStackTrace();
		}

输出结果:

2.有一参构造

        // 实例化
		Person p = new Person();
		Class c = null;
		try {
			// 类的读取
			c = Class.forName("com.SAME_LOVE.reflective.Person");
			// System.out.println(c1);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		// 2.调用有一个参数构造方法反射实例化
        //parameterTypes:代表参数类别的Class,例如:String.class
		 try {
		 Constructor cr2= c.getConstructor(String.class);
		 //强制类型转换为实际对象
		 Person p2 = (Person) cr2.newInstance("p001");
		 System.out.println(p2);
		 } catch (Exception e) {
		 e.printStackTrace();
		 }

输出结果:

3.多参构造

        // 实例化
		Person p = new Person();
		Class c = null;
		try {
			// 类的读取
			c = Class.forName("com.SAME_LOVE.reflective.Person");
			// System.out.println(c1);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		// 3.调用有多个参数构造方法反射实例化
        // parameterTypes:代表参数类别的Class,例如:String.class
		 try {
		 Constructor cr3= c.getConstructor(String.class,String.class,Integer.class);
		 Person p3 = (Person) cr3.newInstance("p001","ikun",18);
		 System.out.println(p3);
		 } catch (Exception e) {
		 e.printStackTrace();
		 }

输出结果:

4.有一参且私有构造

		// 实例化
		Person p = new Person();
		Class c = null;
		try {
			// 类的读取
			c = Class.forName("com.SAME_LOVE.reflective.Person");
			// System.out.println(c1);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		//4.调用有一个参数且私有的构造方法反射实例化
		try {
			Constructor cr4=c.getDeclaredConstructor(Integer.class);
			//打开私有权限
			cr4.setAccessible(true);
			//反射实体
			Person p4 = (Person)cr4.newInstance(18);
			System.out.println(p4);
		} catch (Exception e) {
			e.printStackTrace();
		}

输出结果:

5.有多且私有构造

		// 实例化
		Person p = new Person();
		Class c = null;
		try {
			// 类的读取
			c = Class.forName("com.SAME_LOVE.reflective.Person");
			// System.out.println(c1);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		//5.调用多参数且私有的构造方法反射实例化
		try {
			Constructor cr5=c.getDeclaredConstructor(String.class,Integer.class);
			//打开私有权限
			cr5.setAccessible(true);
			//反射实体
			Person p5 = (Person)cr5.newInstance("ikun",18);
			System.out.println(p5);
		} catch (Exception e) {
			e.printStackTrace();
		}

输出结果:

在上述代码中,使用getConstructor()方法获取一个包含两个参数的构造方法,然后使用newInstance()方法来实例化类对象,并传入相应的参数。

需要注意,在使用反射实例化类对象时,要确保类对象可以被实例化,必须有可访问的构造方法,同时也要正确处理异常。反射操作虽然灵活,但同时也需要注意性能问题,避免多次重复反射导致性能下降。

四、反射方法

Java反射机制可以通过Method类来获取类中的方法,包括公有方法和私有方法,获取到方法后,可以使用invoke()方法来调用方法。

综上Person类的所以代码进行测试。

1.无参

         Class c = Person.class;
		 try {
		 Person p = (Person) c.newInstance();
		 //name:方法名称,parameterTypes:这个方法的参数类型
		 Method m1 = c.getMethod("hello");
		 //obj:类实例,args:参数值,invoke:方法返回值
		 Object invoke = m1.invoke(p);
		 System.out.println(invoke);
		 } catch (Exception e) {
		 e.printStackTrace();
		 }

输出结果:

2.有参

       Class c = Person.class;	
       try {
			Person p = (Person) c.newInstance();
			// name:方法名称,parameterTypes:这个方法的参数类型
			Method m2 = c.getMethod("hello", String.class);
			// obj:类实例,args:参数值,invoke:方法返回值 Object
			Object invoke = m2.invoke(p, "p001");
			System.out.println(invoke);
		} catch (Exception e) {
			e.printStackTrace();
		}

输出结果:

3.私有且多参

	   Class c = Person.class;	
     try {
			Person p = (Person) c.newInstance();
			// name:方法名称,parameterTypes:这个方法的参数类型
			Method m3 = c.getDeclaredMethod("add", Integer.class,Integer.class);
			//打开私有权限
			m3.setAccessible(true);
			// obj:类实例,args:参数值,invoke:方法返回值
			Object invoke = m3.invoke(p,10,15);
			System.out.println(invoke);
		} catch (Exception e) {
			e.printStackTrace();
		}

输出结果:


Java反射机制可以通过Method类来获取类中的方法,包括公有方法和私有方法,获取到方法后,可以使用invoke()方法来调用方法。

五、反射属性

Java反射机制可以通过Field类来获取类中的属性信息,包括公有属性和私有属性,获取到属性后可以进行读取或者操作。

属性指的是类中的字段,也就是成员变量。Field类提供了许多方法,包括获取属性名称、获取属性类型、获取属性的访问修饰符、获取属性值、设置属性值等方法。通过这些方法可以得到属性的详细信息,包括修饰符、类型、值等。

综上Person类的所以代码进行测试。

1.获取属性

Person p = new Person("p001","ikun",18);
		Class c = p.getClass();
		
		System.out.println(p);
System.out.println("-------------------------");
//调用getDeclaredFields获取Person的所有属性名称
		Field[] fields = c.getDeclaredFields();
		try {
			//循环这个属性集合
			for (Field f : fields) {
				//打开私有权限
				f.setAccessible(true);
				//getName():获取属性名称,get:根据实例化对象获取属性值
				System.out.println(f.getName()+":"+f.get(p));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 

输出结果:

2.获取属性修改

package com.SAME_LOVE.reflective;

import java.lang.reflect.Field;

/**
 * @author SAME_LOVE
 * @com.SAME_LOVE.reflective
 * @Demo04(说明):反射读取属性
 */
public class Demo04 {

	public static void main(String[] args) {
		
		Person p = new Person("p001","ikun",18);
		Class c = p.getClass();
		
		System.out.println(p);
		System.out.println("+++++++修改属性值+++++++");
		try {
			/*getDeclaredField("name");
			 * 根据属性名称返回属性
			 */
			Field namefield = c.getDeclaredField("name");
			//打开私有权限
			namefield.setAccessible(true);
			//重写修改后的值
			//obj:实例化对象
			//value:修改后的值
			namefield.set(p, "小卡拉米");
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		System.out.println("-------------------------");
		//调用getDeclaredFields获取Person的所有属性名称
		Field[] fields = c.getDeclaredFields();
		try {
			//循环这个属性集合
			for (Field f : fields) {
				//打开私有权限
				f.setAccessible(true);
				//getName():获取属性名称,get:根据实例化对象获取属性值
				System.out.println(f.getName()+":"+f.get(p));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
		
		
	}
}

输出结果:

 需要注意,在使用反射操作属性时,要确保属性可见和有权限,同时也要正确处理异常和数据类型。反射操作虽然灵活,但同时也需要注意性能问题,避免多次重复反射导致性能下降。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值