Java反射机制(Reflection )

在说反射之前,让我们先来想一下这个问题:我们是否能调用某个类的私有方法或者私有成员变量呢???


我相信很多童鞋都会说:不能!


回答“不能”的童鞋,相信理由大家都懂,针对private的成员变量,只允许当前类的方法对其进行调用,这也就是封装的思想!但是童鞋们可能忽略了一个在Java中蛮重要的机制——反射机制!


而我对上面的问题回答是肯定的!


让我们来看一下Java反射机制主要提供了哪些功能:

1、在运行时可以判断任意的对象其所属的类;

2、在运行时可以构造任意一个类的对象;

3、在运行时可以判断任意一个类,其所拥有的成员变量和方法;

4、在运行时可以调用任意一个对象的方法。


因此,我们可以在程序运行时通过Reflection的APIs获取任意一个已经知道名称的类的内部信息,例如modifiers、fields、methods(不能获取到方法内的实现,也就是代码)、superclass和interfaces,更先进的是我们可以在程序运行时,通过APIs去改变fields的值或者调用methods!


所以Java也可以被认为是动态或准动态语言!(程序在运行的时候,可以改变程序结构或变量类型,这种语言称为动态语言)


我们来看一下JDK,主要由以下类来实现Java的反射机制的:

java.lang包下的有:

Class类:代表一个类;


java.lang.reflect包下的有:

Array类:提供了动态创建数组,以及访问数组元素的静态方法;

Constructor类:代表类的构造方法;

Field类:代表类的成员变量;

Method类:代表类的方法。


介绍完了基本信息,让我们来看一下代码,以下代码段的功能是,读取参数指定的类名,然后打印该类所具有的方法:

注意上面的注释,每个class对象都对应着一个Class类;查看源码会发现,Class类的构造方法的modifier却是private的,也就是说,我们并不能像一般类用new去实例化该类的对象,因此,创建Class类,是JVM的“职责”!


所输入的参数为:

输出的结果为:

public boolean java.lang.String.equals(java.lang.Object)
public java.lang.String java.lang.String.toString()
public int java.lang.String.hashCode()
public int java.lang.String.compareTo(java.lang.String)
public int java.lang.String.compareTo(java.lang.Object)
public int java.lang.String.indexOf(int)
public int java.lang.String.indexOf(int,int)
public int java.lang.String.indexOf(java.lang.String)
public int java.lang.String.indexOf(java.lang.String,int)
static int java.lang.String.indexOf(char[],int,int,char[],int,int,int)
public static java.lang.String java.lang.String.valueOf(int)
public static java.lang.String java.lang.String.valueOf(char)
public static java.lang.String java.lang.String.valueOf(boolean)
public static java.lang.String java.lang.String.valueOf(float)
public static java.lang.String java.lang.String.valueOf(char[],int,int)
public static java.lang.String java.lang.String.valueOf(double)
public static java.lang.String java.lang.String.valueOf(char[])
public static java.lang.String java.lang.String.valueOf(java.lang.Object)
public static java.lang.String java.lang.String.valueOf(long)
public char java.lang.String.charAt(int)
private static void java.lang.String.checkBounds(byte[],int,int)
public int java.lang.String.codePointAt(int)
public int java.lang.String.codePointBefore(int)
public int java.lang.String.codePointCount(int,int)
public int java.lang.String.compareToIgnoreCase(java.lang.String)
public java.lang.String java.lang.String.concat(java.lang.String)
public boolean java.lang.String.contains(java.lang.CharSequence)
public boolean java.lang.String.contentEquals(java.lang.CharSequence)
public boolean java.lang.String.contentEquals(java.lang.StringBuffer)
public static java.lang.String java.lang.String.copyValueOf(char[])
public static java.lang.String java.lang.String.copyValueOf(char[],int,int)
public boolean java.lang.String.endsWith(java.lang.String)
public boolean java.lang.String.equalsIgnoreCase(java.lang.String)
public static java.lang.String java.lang.String.format(java.lang.String,java.lang.Object[])
public static java.lang.String java.lang.String.format(java.util.Locale,java.lang.String,java.lang.Object[])
public byte[] java.lang.String.getBytes(java.lang.String) throws java.io.UnsupportedEncodingException
public void java.lang.String.getBytes(int,int,byte[],int)
public byte[] java.lang.String.getBytes()
public byte[] java.lang.String.getBytes(java.nio.charset.Charset)
public void java.lang.String.getChars(int,int,char[],int)
void java.lang.String.getChars(char[],int)
public native java.lang.String java.lang.String.intern()
public boolean java.lang.String.isEmpty()
public int java.lang.String.lastIndexOf(java.lang.String)
public int java.lang.String.lastIndexOf(int,int)
public int java.lang.String.lastIndexOf(int)
public int java.lang.String.lastIndexOf(java.lang.String,int)
static int java.lang.String.lastIndexOf(char[],int,int,char[],int,int,int)
public int java.lang.String.length()
public boolean java.lang.String.matches(java.lang.String)
public int java.lang.String.offsetByCodePoints(int,int)
public boolean java.lang.String.regionMatches(boolean,int,java.lang.String,int,int)
public boolean java.lang.String.regionMatches(int,java.lang.String,int,int)
public java.lang.String java.lang.String.replace(java.lang.CharSequence,java.lang.CharSequence)
public java.lang.String java.lang.String.replace(char,char)
public java.lang.String java.lang.String.replaceAll(java.lang.String,java.lang.String)
public java.lang.String java.lang.String.replaceFirst(java.lang.String,java.lang.String)
public java.lang.String[] java.lang.String.split(java.lang.String)
public java.lang.String[] java.lang.String.split(java.lang.String,int)
public boolean java.lang.String.startsWith(java.lang.String)
public boolean java.lang.String.startsWith(java.lang.String,int)
public java.lang.CharSequence java.lang.String.subSequence(int,int)
public java.lang.String java.lang.String.substring(int)
public java.lang.String java.lang.String.substring(int,int)
public char[] java.lang.String.toCharArray()
public java.lang.String java.lang.String.toLowerCase()
public java.lang.String java.lang.String.toLowerCase(java.util.Locale)
public java.lang.String java.lang.String.toUpperCase()
public java.lang.String java.lang.String.toUpperCase(java.util.Locale)
public java.lang.String java.lang.String.trim()

我们先来看一下,使用传统方法,调用另一个类的私有方法,会提示些啥:

package com.gdut.reflection;

public class PrivateMethod {

	private void privateMethod() {
		System.out.println("通过java反射机制,调用了class PrivateMethod的私有方法");
	}

}

这样调用PrivateMethod类的privateMethod方法,提示方法不可见!


现在我们通过反射机制,调用另外一个类的私有方法:

还是调用上面PrivateMethod类的privateMethod方法,代码如下:

package com.gdut.reflection;

import java.lang.reflect.Method;

public class PrivateTest {
	
	private static void invocation(Object obj) throws Exception {
		// 获得obj的Class类
        Class<?> cls = obj.getClass();
        
        // 获得类的私有方法
        // 参数:第一个为方法名; 第二个为方法参数数组, 此处为空
        Method method = cls.getDeclaredMethod("privateMethod", new Class[] {});
        
        // 调用private方法的关键一句话,没有设置就会报错
        method.setAccessible(true);
        
        // 调用obj的method方法,method方法的参数列表为第二个参数指定
        method.invoke(obj, new Object[] {});
        
    }
	
	public static void main(String[] args) throws Exception {
		PrivateTest.invocation(new PrivateMethod());
	}

}

输出结果:

这样做(调用其他类的私有方法),是否和封装的思想相悖呢???哈哈,仁者见仁,智者见智!!


推荐大家看一下书:Manning - java reflection in action  好像没中文版的!点击打开下载书籍


=================

有空我再写一些其他反射程序上来,和大家共同学习


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值