Java的动态性支持学习三 反射机制 取消属性、方法、构造器的访问限制

Java的动态性支持学习一 - 反射机制 概念概述
Java的动态性支持学习二 - 反射机制 属性、方法、对象的操作
Java的动态性支持学习三 - 反射机制 取消属性、方法、构造器的访问限制
Java的动态性支持学习四 - 反射调用的性能对比
Java的动态性支持学习五 - 方法句柄 概念和句柄类型
Java的动态性支持学习六 - 方法句柄 获取和调用
Java的动态性支持学习七 - 方法句柄调用的性能对比

这篇博文学习下如何取消属性、方法、构造器的访问限制。

通过上节我们知道,当用Class对象的getDeclaredXXXs方法获得Field、Method或Constructor时由于访问限制的作用,可能有些字段、方法或构造器是不能访问的。如:

package net.oseye;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectTest {

	public static void main(String[] args) throws NoSuchMethodException, 
		SecurityException, IllegalAccessException, IllegalArgumentException, 
		InvocationTargetException, InstantiationException{
		Class c=User.class;
		Method mth=c.getDeclaredMethod("sayHello");
		mth.invoke(c.newInstance(), new Object[0]);
	}
}

class User{	
	private void sayHello(){
		System.out.println("我是私有方法");		
	}
}

运行,或报异常:

Exception in thread "main" java.lang.IllegalAccessException: 
	Class net.oseye.ReflectTest can not access a member of class net.oseye.User with modifiers "private"
	at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
	at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(Unknown Source)
	at java.lang.reflect.AccessibleObject.checkAccess(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at net.oseye.ReflectTest.main(ReflectTest.java:11)

如果需要通过反射访问这些不允许访问的元素,则首先需要去除访问限制,然后在访问。去除访问限制,就需要使用到java.lang.reflect.AccessibleObject类,其中提供了一些用来去除访问限制的方法。Field、Method、Constructor类都是AccessibleObject类的子类。AccessibleObject类的常用方法:

  • boolean isAccessible() 返回是否可以访问
  • void setAccessible(boolean flag) 设置访问限制
  • static void setAccessible(AccessibleObject[] array, boolean flag) 批量设置访问限制

Demo:

package net.oseye;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectTest {

	public static void main(String[] args) throws NoSuchMethodException, 
		SecurityException, IllegalAccessException, IllegalArgumentException, 
		InvocationTargetException, InstantiationException{
		Class c=User.class;
		Method mth=c.getDeclaredMethod("sayHello");
		mth.setAccessible(true);
		mth.invoke(c.newInstance(), new Object[0]);
	}
}

class User{	
	private void sayHello(){
		System.out.println("我是私有方法");		
	}
}

输出:

我是私有方法
原文地址:https://www.cnblogs.com/zhaiqianfeng/p/4618323.html