概念:
JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
JAVA反射(放射)机制:"程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言"。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。下面结合代码看看如何在项目运行时动态的获取我们想要的类的各个内容:
package co.laola.Test;
import co.laola.pojo.User;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;
public class Test {
/**
*
*
*
* 对于反射而言一般都要操作最多的是:构造函数,字段,方法
* 1.创建class对象的三种方式:
* (1)用类.class();
* (2)用对象.getClass();
* (3)用class.forName();的方式
* Class.forName()-->getConstructor()"有参构造即为类型全名,无参即为‘null’或者不写也可以"
* -->获得构造器-->构造器.newInstance()用来创建实例,与普通new实例无异
* @throws Exception
*
*
*/
@org.junit.Test
public void testGetClass() throws Exception{
Class<String> stringClass = String.class;
System.out.println("stringclass:"+stringClass);
//对象.getClass
Class<? extends String> stringClass1 = new String().getClass();
System.out.println("stringClass1:"+stringClass1);
Class<?> forName = Class.forName("java.lang.String");
System.out.println("forname():"+forName);
}
@org.junit.Test
public void getConstructor()throws Exception{
Class<?> user = Class.forName("co.laola.pojo.User");
Class<? > user1=Class.forName("co.laola.pojo.User");
Constructor [] constructors=user.getConstructors();
System.out.println("constructors:"+constructors);
for (Constructor con:constructors){
System.out.println("单个:"+con);
}
//获取带参数的构造函数
Constructor<?>[] declaredConstructors = user.getDeclaredConstructors();
System.out.println(declaredConstructors);
Constructor<?> constructor = user1.getConstructor(String.class, int.class, String.class);
System.out.println("有参的构造器:"+constructor);
//获取无参的只需要给getConstructor()传入”null“即可
//创建一个带参数的实例
User user2=(User) constructor.newInstance("九见瑶歌",20,"male");
User user3=(User) user1.getConstructor(null).newInstance();
user2.show("九见瑶歌");
user3.show();
System.out.println(user2);
System.out.println(user3);
}
//通过反射获取私有属性
@org.junit.Test
public void getPrivateField()throws Exception{
//获取Class对象
Class<?> uClass = Class.forName("co.laola.pojo.User");
//获取构造函数
Constructor<?> uClassConstructor = uClass.getConstructor(null);
//创建一个实例
User user1 =(User) uClassConstructor.newInstance();
Field name = uClass.getDeclaredField("name");
//设置可以访问私有属性,注意:这里的name只是设置私有属性的name值,
// 不代表可以直接用name来显示结果,毕竟人家自己的东西,还得人家自己才能访问
name.setAccessible(true);
name.set(user1,"九见瑶歌");
System.out.println("名字:"+user1.getName());
}
@org.junit.Test
public void getMethod()throws Exception{
//获取Class对象
Class<?> uClass = Class.forName("co.laola.pojo.User");
//获取构造器
Constructor<?> uClassConstructor = uClass.getConstructor(null);
//新实例
User user =(User) uClassConstructor.newInstance();
Method eat = uClass.getDeclaredMethod("eat");
eat.setAccessible(true);
eat.invoke(user);
//访问私有方法,invoke()是调用的意思,setAccessible()设置私有属性可以访问
Method shoeInfo = uClass.getDeclaredMethod("shoeInfo", String.class, int.class);
shoeInfo.setAccessible(true);
shoeInfo.invoke(user,"tom",20);
}
@org.junit.Test
public void getPropertyFile()throws Exception{
//实例化Properties
Properties properties=new Properties();
//通过反射以及流的形式读取到文件
properties.load(Test.class.getClassLoader().getResourceAsStream("user.properties"));
//通过key获取对应的值
String className = properties.getProperty("className").trim();
String methodName = properties.getProperty("methodName").trim();
System.out.println(className);
System.out.println(methodName);
}
}