java反射机制详解

1. 反射机制:是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java的反射机制。
动态语言:在程序运行时,允许改变程序结构或变量类型。
2. 反射的实现
(1)获取Class对象的三种方式
先定义一个user实体类

package test;

public class User {

	private String phone;
	private String userName;
	private String password;

	public User() {

	}

	public User(String phone, String userName, String password) {
		this.phone = phone;
		this.userName = userName;
		this.password = password;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Override
	public String toString() {
		return "User [phone=" + phone + ", userName=" + userName
				+ ", password=" + password + "]";
	}

}

得到class的三种方法

package test;

public class ReflectService {

	public static void main(String[] args) {
		// 第一种方式获取Class对象
		// 通过对象调用 getClass() 方法来获取
		User user = new User();
		Class userClass1 = user.getClass();
		System.out.println(userClass1.getName());

		// 第二种方式获取Class对象
		// 直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高
		Class userClass2 = User.class;
		System.out.println(userClass2.getName());
		// 判断两种方式获取的Class对象是否为同一个
		System.out.println(userClass1 == userClass2);

		// 第三种方式获取Class对象
		// 通过 Class 对象的 forName() 静态方法来获取,用的最多,但会抛出ClassNotFoundException异常,必须是类的全路径。
		try {
			Class userClass3 = Class.forName("test.User");
			System.out.println(userClass3.getName());
			// System.out.println(userClass1 ==userClass2);
			System.out.println(userClass3 == userClass1);
			System.out.println(userClass3 == userClass2);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//

	}

}

运行结果
在这里插入图片描述
一个类在 JVM 中只能有一个 Class 实例
(2) 通过反射获取构造方法。
public Constructor[] getConstructors():获取所有"公有的"构造方法;
public Constructor[] getDeclaredConstructors():获取所有构造方法(包括私有的、受保护的、默认的、公有的);
public Constructor getConstructor(Class… parameterTypes):获取单个的"公有的"构造方法;
public Constructor getDeclaredConstructor(Class… parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;

测试:

package test;

public class User {

	public User() {
		System.out.println("调用公有的无参构造方法!");
	}

	public User(String userName) {
		System.out.println("调用一个有参的构造方法:" + userName);
	}

	User(int age) {
		System.out.println("调用一个默认的构造方法:" + age);
	}

	protected User(char ca) {
		System.out.println("调用一个受保护的构造方法:" + ca);
	}

	private User(String userName, int age) {
		System.out.println("调用一个私有的构造方法:" + userName + "--" + age);
	}

	private int id;
	String userName;
	protected String password;
	public boolean flag;

	@Override
	public String toString() {
		return "User [id=" + id + ", userName=" + userName + ", password="
				+ password + ", flag=" + flag + "]";
	}

}

package test;

import java.lang.reflect.Constructor;

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

		Class clazz = Class.forName("test.User");
		System.out.println("**********所有公有构造方法**************");
		Constructor[] conArray = clazz.getConstructors();
		for (Constructor con : conArray) {
			System.out.println(con);
		}

		System.out.println("*****所有的构造方法(私有、受保护、默认、公有)*****");
		conArray = clazz.getDeclaredConstructors();
		for (Constructor con : conArray) {
			System.out.println(con);
		}
		System.out.println("*********获取私有构造方法,并调用*********");
		Constructor con = clazz.getDeclaredConstructor(String.class, int.class);
		System.out.println(con);

		System.out.println("*********获取公有构造方法,并调用*********");
		Constructor cons = clazz.getConstructor();
		System.out.println(cons);
		// 调用构造方法
		Object obj = cons.newInstance();
		System.out.println("obj = " + obj);
		User user = (User) obj;
		System.out.println(user);

	}
}

测试结果:
**********所有公有构造方法**************public test.User(java.lang.String)public test.User()*****所有的构造方法(私有、受保护、默认、公有)*****private test.User(java.lang.String,int)protected test.User(char)test.User(int)public test.User(java.lang.String)public test.User()*********获取私有构造方法,并调用*********private test.User(java.lang.String,int)*********获取公有构造方法,并调用*********public test.User()调用共有的无参构造方法!obj = test.User@15093f1test.User@15093f1
(3)通过反射获取成员变量
Field[] getFields():获取所有的"公有字段";
Field[] getDeclaredFields():获取所有字段(私有、受保护、默认、公有);
public Field getField(String fieldName):获取某个"公有的"字段;
public Field getDeclaredField(String fieldName):获取某个字段;
public void set(Object obj,Object value): obj:表示操作的目标对象;value:字段所要设置的值;如果成语变量为基本类型,可以使用Filed类中带有类型名的值设置方法,如 setBoolean(Object obj,Object value), setInt(Object obj,Object value).

测试

package test;

import java.lang.reflect.Field;

public class FiledTest {

	public static void main(String[] args) throws Exception {
		Class Clazz = Class.forName("test.User");
		System.out.println("获取所有公有的字段");
		Field[] fieldArray = Clazz.getFields();
		for (Field f : fieldArray) {
			System.out.println(f);
		}
		System.out.println("获取所有的字段(包括私有、受保护、默认的)");
		fieldArray = Clazz.getDeclaredFields();
		for (Field f : fieldArray) {
			System.out.println(f);
		}
		System.out.println("获取公有字段**并调用");
		User user = (User) Clazz.getConstructor().newInstance();
		Field filed = Clazz.getField("flag");
		System.out.println(filed);
		// 为字段设置值
		filed.setBoolean(user, false);// 为user中的flag赋值
		System.out.println("flag:" + user.flag);

		System.out.println("获取私有字段****并调用");
		filed = Clazz.getDeclaredField("id");
		System.out.println(filed);
		/**在访问private,protected成员变量和方法时,必须使用setAccessible(Boolean flag)取消java语言检查**/
		filed.setAccessible(true);
		filed.setInt(user, 111);

		System.out.println("获取受保护字段****并调用");
		filed = Clazz.getDeclaredField("password");
		System.out.println(filed);
		filed.setAccessible(true);
		filed.set(user, "123456");
		System.out.println("获取默认字段****并调用");
		filed = Clazz.getDeclaredField("userName");
		System.out.println(filed);
		filed.setAccessible(true);
		filed.set(user, "登录");

		System.out.println("用户信息:" + user);

	}
}

测试结果:
在这里插入图片描述
(4)通过反射获取成员方法
public Method[] getMethods():获取所有"公有方法"(这就包括自身的所有public方法,和从基类继承的、从接口实现的所有public方法);
public Method[] getDeclaredMethods():获取的是类自身声明的所有方法;
public Method getMethod(String name,Class<?>… parameterTypes) name : 方法名,Class … : 形参的Class类型对象
public Method getDeclaredMethod(String name,Class<?>… parameterTypes)

测试

package test;

public class User {

	public void login1(String userNmae, int userId) {
		System.out.println("调用公有的login1()方法: userNmae = " + userNmae
				+ ";password=" + userId);
	}

	protected int login2(int userId) {
		System.out.println("调用受保护的login2()方法:userId=" + userId);
		return userId;
	}

	void login3() {
		System.out.println("调用默认的login3()方法");
	}

	private void login4(String telephone) {
		System.out.println("调用私有的方法login4(): telephone = " + telephone);

	}
}
package test;

import java.lang.reflect.Method;

public class MethodTest {

	public static void main(String[] args) throws Exception {
		// 1.获取Class对象
		Class clazz = Class.forName("test.User");
		// 2.获取所有公有方法
		System.out.println("获取所有的公有方法");
		clazz.getMethods();
		Method[] methodArray = clazz.getMethods();
		for (Method m : methodArray) {
			System.out.println(m);
		}
		System.out.println("获取所有的方法,包括私有的");
		methodArray = clazz.getDeclaredMethods();
		for (Method m : methodArray) {
			System.out.println(m);
		}
		User user = (User) clazz.getConstructor().newInstance();
		System.out.println("获取公有的方法");
		Method method = clazz.getMethod("login1", String.class, int.class);
		System.out.println(method);

		method.invoke(user, "denglu", 11);

		System.out.println("获取私有的login2()方法");
		method = clazz.getDeclaredMethod("login2", int.class);
		System.out.println(method);
		method.setAccessible(true);
		Object result = method.invoke(user, 123);
		System.out.println("返回值:" + result);

		System.out.println("获取私有的login3()方法");
		method = clazz.getDeclaredMethod("login3", null);
		System.out.println(method);

		System.out.println("获取私有的show4()方法");
		method = clazz.getDeclaredMethod("login4", String.class);
		System.out.println(method);
		method.setAccessible(true);
		method.invoke(user, "12345678901");

	}

}

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值