Java高级特性——反射
本文内容是我在网上所学习总结的,如有侵权,请联系我,我立刻删除。
定义
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
用途 (网上看的)
在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法。当然,也不是所有的都适合反射,之前就遇到一个案例,通过反射得到的结果与预期不符。阅读源码发现,经过层层调用后在最终返回结果的地方对应用的权限进行了校验,对于没有权限的应用返回值是没有意义的缺省值,否则返回实际值起到保护用户的隐私目的。
首先创建Student类
public class Student {
public int age;
public String name;
public Student() {
}
public Student(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
编写反射类 Reflect.java
在这里我用测试类来运行方法,先一个方法来编写,最后在最后放上总代码。
demo1()
/**
* 通过java的反射机制来得到类的包名和类名
*/
@Test
public void demo1(){
Student student=new Student();//实例化Student类
String name = student.getClass().getName();//获取Student的类名
String name1 = student.getClass().getPackage().getName();//获取Student的包名
System.out.println("类名"+name);//输出类名
System.out.println("包名"+name1);//输出包名
}
demo2()
/**
* 验证所有的类都是Class类的实例对象
* 异常ClassNotFoundException
*/
@Test
public void demo2() throws ClassNotFoundException{
//定义两个类型都是未知的Class,初始赋值为null,下面赋值成Student类
Class<?> class1=null;
Class<?> class2=null;
//方法一:会抛出ClassNotFoundException异常(建议使用这个写法)
class1=Class.forName("web.reflect.Student");
String name2 = class1.getName();//获取Student的类名
String name3 = class1.getPackage().getName();//获取Student的包名
System.out.println("类名"+name2);//输出类名
System.out.println("包名"+name3);//输出包名
System.out.println("========================");
//方法二:
class2=Student.class;
String name4 = class2.getName();
String name5 = class2.getPackage().getName();
System.out.println("类名"+name4);
System.out.println("包名"+name5);
}
demo3()
/**
* 利用java的反射机制,用Class类创建对象
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*/
@Test
public void demo3() throws ClassNotFoundException,IllegalAccessException,InstantiationException{
//定义一个类型都是未知的Class,初始赋值为null。
Class<?> class1=null;
class1=Class.forName("web.reflect.Student");
//由于这里不能带参数,所以你要实例化的这个类Person,一定要有无参构造函数
Student student=(Student) class1.newInstance();
student.setAge(20);
student.setName("大猩猩");
System.out.println("我叫"+student.getName()+";今年"+student.getAge()+"岁了");
}
demo4()
/**
* 通过Java反射机制得到一个类的构造函数,并实现创建带参实例对象
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
@Test
public void demo4() throws ClassNotFoundException,InstantiationException, InvocationTargetException,IllegalAccessException {
Class<?> class1=null;
Student student1=null;
Student student2=null;
class1=Class.forName("web.reflect.Student");
//得到一系列构造函数集合
Constructor<?>[] constructors=class1.getConstructors();
student1=(Student) constructors[0].newInstance();
student1.setAge(30);
student1.setName("张三");
student2=(Student) constructors[1].newInstance(20,"王五");
System.out.println("demo4:"+student1.getName()+":"+student1.getAge()+","+student2.getName()+":"+student2.getAge());
}
demo5()
/**
*通过Java反射机制操作成员变量, set 和 get
* @throws NoSuchFieldException
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IllegalAccessException
*/
@Test
public void demo5()throws NoSuchFieldException,ClassNotFoundException,InstantiationException,IllegalAccessException{
Class<?> class1=null;
class1=Class.forName("web.reflect.Student");
Object obj=class1.newInstance();
Field studentNameField=class1.getDeclaredField("name");
studentNameField.setAccessible(true);
studentNameField.set(obj,"刘德华");
System.out.println("修改属性之后得到属性变量的值:"+studentNameField.get(obj));
}
demo6()
写一个接口ReflectInterface
public interface ReflectInterface {
public void sweet(int m);
}
这里创建一个SugarMan类继承Student类和接口
SugarMan.java
public class SugarMan extends Student implements ReflectInterface{
private boolean BlueBriefs;
public void sugar(){
System.out.println("我是糖人,很甜的糖。");
}
public boolean isBlueBriefs(){
return BlueBriefs;
}
public void setBlueBriefs(boolean blueBriefs){
BlueBriefs=blueBriefs;
}
@Override
public void sweet(int m){
System.out.println("唐人的甜度是:"+m);
}
}
测试方法
/**
* 通过java反射机制得到类的一些属性:继承接口,父类,函数的信息,成员信息,类型等;
* @throws ClassNotFoundException
*/
@Test
public void demo6() throws ClassNotFoundException{
Class<?> class1=null;
class1=Class.forName("web.reflect.SugarMan");
//获取父类名称
Class<?> sugarClass=class1.getSuperclass();
System.out.println("SugarMan父类名称是:"+sugarClass.getName());
System.out.println("-------------------------------");
Field[] fields=class1.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
System.out.println("类中的成员:"+fields[i]);
}
System.out.println("-------------------------------");
//获取类方法
Method[] methods=class1.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
System.out.println("Demo6,取得SuperMan类的方法:");
System.out.println("函数名:"+methods[i].getName());
System.out.println("函数返回类型:" +methods[i].getReturnType());
System.out.println("函数访问修饰符:" + Modifier.toString(methods[i].getModifiers()));
System.out.println("函数代码写法: " + methods[i]);
}
System.out.println("-------------------------------");
//取得类实现的接口,因为接口类也属于Class,所以得到接口中的方法也是一样的方法得到
Class<?>[] interfaces=class1.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
System.out.println("实现的接口类名: " +interfaces[i].getName());
}
}
demo7()
/**
* 通过Java反射机制调用类方法
* @throws ClassNotFoundException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws InstantiationException
*/
@Test
public void demo7() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException
{
Class<?> class1 = null;
class1 = Class.forName("web.reflect.SugarMan");
System.out.println("Demo7: \n调用无参方法sugar():");
Method method = class1.getMethod("sugar");
method.invoke(class1.newInstance());
System.out.println("调用有参方法sweet(int m):");
method = class1.getMethod("sweet",int.class);
method.invoke(class1.newInstance(),100);
}
}
最后放上测试的总代码
Reflect.java
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Reflect {
/**
* 通过java的反射机制来得到类的包名和类名
*/
@Test
public void demo1(){
Student student=new Student();//实例化Student类
String name = student.getClass().getName();//获取Student的类名
String name1 = student.getClass().getPackage().getName();//获取Student的包名
System.out.println("类名"+name);//输出类名
System.out.println("包名"+name1);//输出包名
System.out.println("--------------------------");
}
/**
* 验证所有的类都是Class类的实例对象
* 异常ClassNotFoundException
*/
@Test
public void demo2() throws ClassNotFoundException{
//定义两个类型都是未知的Class,初始赋值为null,下面赋值成Student类
Class<?> class1=null;
Class<?> class2=null;
//方法一:会抛出ClassNotFoundException异常(建议使用这个写法)
class1=Class.forName("web.reflect.Student");
String name2 = class1.getName();//获取Student的类名
String name3 = class1.getPackage().getName();//获取Student的包名
System.out.println("类名"+name2);//输出类名
System.out.println("包名"+name3);//输出包名
System.out.println("========================");
//方法二:
class2=Student.class;
String name4 = class2.getName();
String name5 = class2.getPackage().getName();
System.out.println("类名"+name4);
System.out.println("包名"+name5);
}
/**
* 利用java的反射机制,用Class类创建对象
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*/
@Test
public void demo3() throws ClassNotFoundException,IllegalAccessException,InstantiationException{
//定义一个类型都是未知的Class,初始赋值为null。
Class<?> class1=null;
class1=Class.forName("web.reflect.Student");
//由于这里不能带参数,所以你要实例化的这个类Person,一定要有无参构造函数
Student student=(Student) class1.newInstance();
student.setAge(20);
student.setName("大猩猩");
System.out.println("我叫"+student.getName()+";今年"+student.getAge()+"岁了");
}
/**
* 通过Java反射机制得到一个类的构造函数,并实现创建带参实例对象
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
@Test
public void demo4() throws ClassNotFoundException,InstantiationException, InvocationTargetException,IllegalAccessException {
Class<?> class1=null;
Student student1=null;
Student student2=null;
class1=Class.forName("web.reflect.Student");
//得到一系列构造函数集合
Constructor<?>[] constructors=class1.getConstructors();
student1=(Student) constructors[0].newInstance();
student1.setAge(30);
student1.setName("张三");
student2=(Student) constructors[1].newInstance(20,"王五");
System.out.println("demo4:"+student1.getName()+":"+student1.getAge()+","+student2.getName()+":"+student2.getAge());
}
/**
*通过Java反射机制操作成员变量, set 和 get
* @throws NoSuchFieldException
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IllegalAccessException
*/
@Test
public void demo5()throws NoSuchFieldException,ClassNotFoundException,InstantiationException,IllegalAccessException{
Class<?> class1=null;
class1=Class.forName("web.reflect.Student");
Object obj=class1.newInstance();
Field studentNameField=class1.getDeclaredField("name");
studentNameField.setAccessible(true);
studentNameField.set(obj,"刘德华");
System.out.println("修改属性之后得到属性变量的值:"+studentNameField.get(obj));
}
/**
* 通过java反射机制得到类的一些属性:继承接口,父类,函数的信息,成员信息,类型等;
* @throws ClassNotFoundException
*/
@Test
public void demo6() throws ClassNotFoundException{
Class<?> class1=null;
class1=Class.forName("web.reflect.SugarMan");
//获取父类名称
Class<?> sugarClass=class1.getSuperclass();
System.out.println("SugarMan父类名称是:"+sugarClass.getName());
System.out.println("-------------------------------");
Field[] fields=class1.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
System.out.println("类中的成员:"+fields[i]);
}
System.out.println("-------------------------------");
//获取类方法
Method[] methods=class1.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
System.out.println("Demo6,取得SuperMan类的方法:");
System.out.println("函数名:"+methods[i].getName());
System.out.println("函数返回类型:" +methods[i].getReturnType());
System.out.println("函数访问修饰符:" + Modifier.toString(methods[i].getModifiers()));
System.out.println("函数代码写法: " + methods[i]);
}
System.out.println("-------------------------------");
//取得类实现的接口,因为接口类也属于Class,所以得到接口中的方法也是一样的方法得到
Class<?>[] interfaces=class1.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
System.out.println("实现的接口类名: " +interfaces[i].getName());
}
}
/**
* 通过Java反射机制调用类方法
* @throws ClassNotFoundException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws InstantiationException
*/
@Test
public void demo7() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException
{
Class<?> class1 = null;
class1 = Class.forName("web.reflect.SugarMan");
System.out.println("Demo7: \n调用无参方法sugar():");
Method method = class1.getMethod("sugar");
method.invoke(class1.newInstance());
System.out.println("调用有参方法sweet(int m):");
method = class1.getMethod("sweet",int.class);
method.invoke(class1.newInstance(),100);
}
}
如果不想用测试类可以写主函数,然后调用方法,建议用静态的,这样代码量少,比较清晰。
如果测试类出错误了,可以看我的另一篇文章。