[b]阅读目录[/b]
[list=1]
[*]
[b]Java反射API[/b][/*]
[*]
[b]通过反射创建实例对象[/b][/*]
[*]
[b]通过反射调用私有方法[/b][/*]
[*]
[b]关于javap工具[/b][/*]
[*]
[b]参考资料[/b][/*]
[/list]
[b]Java反射API[/b]
[b]Java反射[/b]指的是在运行状态时,能够获取类的属性和方法或者修改类运行时行为的过程。
[b]java.lang.Class类[/b]提供了很多方法用于获取元数据、检查和改变类运行时的行为。
Java的反射主要涉及java.lang和java.lang.reflect包下的类。
[b]反射应用场景举例[/b]
[list=1]
[*]IDE, 如Eclipse、MyEclipse、NetBeans等;[/*]
[*]调试器;[/*]
[*]测试工具等;[/*]
[*]各大框架、spring、hibernate等;[/*]
[/list]
[b]java.lang.Class类[/b]
java.lang.Class主要提供了以下两个功能:
[list=1]
[*]提供方法用于访问运行期间类的元数据;[/*]
[*]提供方法用于检查和修改类的运行时行为;[/*]
[/list]
[b]java.lang.Class类常用方法[/b]
| Method |
Description |
| 1) public String getName() |
返回类名 |
| 2) public static Class forName(String className)throws ClassNotFoundException |
加载类并返回Class对象 |
| 3) public Object newInstance()throws InstantiationException,IllegalAccessException |
创建实例对象 |
| 4) public boolean isInterface() |
判断是否是接口 |
| 5) public boolean isArray() |
判断是否是数组 |
| 6) public boolean isPrimitive() |
判断是否是原始数据类型 |
| 7) public Class getSuperclass() |
返回父类Class引用 |
| 8) public Field[] getDeclaredFields()throws SecurityException |
返回类的成员属性字段数组 |
| 9) public Method[] getDeclaredMethods()throws SecurityException |
返回类的方法数组 |
| 10) public Constructor[] getDeclaredConstructors()throws SecurityException |
返回类的构造方法数组 |
| 11) public Method getDeclaredMethod(String name,Class[] parameterTypes)throws NoSuchMethodException,SecurityException |
返回类中指定参数类型的方法 |
[b]怎样获取Class对象[/b]
有三种方式,如下:
[list=1]
[*]Class类的forName()方法,动态加载,运行时,开始装入类, 并做类的静态初始化[/*]
[*]对象的getClass()方法,静态加载(编译时已加载)[/*]
[*].class语法, 静态加载(编译时已加载)[/*]
[/list]
[b]forName()方法示例[/b]
可用于动态加载,当你知道类的全限定名时,可以使用该方式。注意原始数据类型不适用该方法;
package tmp;
class Simple
{
}
public class Test
{
public static void main(String args[]) throws ClassNotFoundException
{
Class<?> c = Class.forName("tmp.Simple");
System.out.println(c.getName());
System.out.println(c.getSimpleName());
}
}
[b]getClass()方法示例:[/b]
从实例对象中获取Class对象
package tmp;
class Simple
{
}
public class Test
{
void printName(Object obj)
{
}
public static void main(String args[])
{
Simple s = new Simple();
Class<? extends Object> c = s.getClass();
System.out.println(c.getName());
System.out.println(c.getSimpleName());
}
}
[b].class语法示例[/b]
作用于类名上,也可应用于原始数据类型,如下所示:
package tmp;
public class Test
{
public static void main(String args[])
{
Class<Boolean> c = boolean.class;
System.out.println(c.getName());
Class<Test> c2 = Test.class;
System.out.println(c2.getName());
}
}
[b]判断Class对象对应的类型[/b]
以下方法可用于判断Class对象对应的类型:
| 1) public boolean isInterface(): 是否对应接口 |
| 2) public boolean isArray(): 是否对应数组 |
| 3) public boolean isPrimitive(): 是否对应原始数据类型 |
代码示例:
package tmp;
class Simple
{
}
interface My
{
}
public class Test
{
public static void main(String args[])
{
try
{
Class<?> c = Class.forName("tmp.Simple");
System.out.println(c.isInterface());
Class<?> c2 = Class.forName("tmp.My");
System.out.println(c2.isInterface());
}
catch (Exception e)
{
System.out.println(e);
}
}
}
[b]通过反射创建实例对象[/b]
有两种方式,如下:
[list=1]
[*]通过Class对象的newInstance()方法创建,这种方式只能调用无参构造方法;[/*]
[*]通过Constructor对象的newInstance()方法创建,这种方式适用于有参构造方法,并且还可以破坏单例模式,调用私有构造方法;[/*]
[/list]
所以,通常来讲,第二种方式比第一种使用范围更广。
[b]Class对象调用newInstance()方法示例[/b]
package tmp;
class Simple
{
void message()
{
System.out.println("Hello Java");
}
}
public class Test
{
public static void main(String args[])
{
try
{
Class<?> c = Class.forName("tmp.Simple");
Simple s = (Simple) c.newInstance();
s.message();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
[code]Hello Java[/code]
[b]Constructor对象调用newInstance()方法示例[/b]
注意这里可以根据传入参数的类型来得到指定的构造方法,还可以改变构造方法的访问权限限制。
package tmp;
import java.lang.reflect.Constructor;
class Simple
{
private String msg;
void message()
{
System.out.println("Hello Java," + msg);
}
private Simple(String s){
this.msg = s;
}
}
public class Test
{
public static void main(String args[])
{
try
{
Class<?> c = Class.forName("tmp.Simple");
Constructor<?> con = c.getDeclaredConstructor(String.class);
con.setAccessible(true);
Simple s = (Simple) con.newInstance("...");
s.message();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
[code]Hello Java,...[/code]
[b]通过反射调用私有方法[/b]
通过反射,我们可以调用其它类的私有方法,主要涉及java.lang.Class和java.lang.reflect.Method类;
其中主要是用到了Method类的setAccessible方法和invoke方法,前者修改访问权限,后者调用方法。
通过调用有参私有方法示例:
package tmp;
import java.lang.reflect.Method;
class A
{
private void cube(int n)
{
System.out.println(n * n * n);
}
}
class Test
{
public static void main(String args[]) throws Exception
{
Class<A> c = A.class;
Object obj = c.newInstance();
Method m = c.getDeclaredMethod("cube", new Class[]{ int.class });
m.setAccessible(true);
m.invoke(obj, 4);
}
}
[b]关于javap工具[/b]
使用javap命令可以反汇编java的字节码文件,展示class文件中的字段属性、构造方法、普通方法信息;
使用说明:
[img]http://files.jb51.net/file_images/article/201702/2017021716564629.png[/img]
javap java.lang.Object示例
javap -c Test示例:
[img]http://files.jb51.net/file_images/article/201702/2017021716564630.png[/img]
写个简单的Test类,如下:
package tmp;
class Simple
{
}
public class Test
{
public static void main(String args[])
{
System.out.println("Hello");
}
}
输入javap -c Test:
[img]http://files.jb51.net/file_images/article/201702/2017021716564631.png[/img]
[b]参考资料[/b]
基本属于翻译,做了小部分修改
[url=http://www.javatpoint.com/java-reflection]http://www.javatpoint.com/java-reflection[/url]
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持编程素材网!