Java中的反射机制让初学者感觉比较难理解.为啥认为难理解,我个人感觉其实就是一个思维的逆过程而已.只是思维方式的问题;
Java Reflection 之所以称之为反射就是如同我们照镜子一样而已;
反射是被称为动态语言的关键.反射机制是允许程序在执行期借助于相关api取得任何类的内部信息.并能直接操作任意对象的属性及其方法
Java 机制能提供的功能
在运行时判断任意一个对象所属类
在运行时判断任何一个类的对象
在运行是判断任何一个类所具有的成员变量和方法
在运行时判断任何一个对象的成员变量也方法
生成动态代理
反射的源头就是一个Class类.这里是类不是我们经常见的关键字class.为啥说Class类是反射的源泉.因为有了相关的Class基本上想要的都可以实现了.我们先说说怎么获得Class
方法有如下几种:
@Test
public void test1() throws Exception{
//1 Class 是反射的源头,获取到Class后就可以动态的知道相对应的类的结构
//包括 属性 方法 构造方法 内部类等等
//获取Class的方法
//第一种
Class perClass = Person.class;
//第二种
Person p = new Person();
Class perClass2 = p.getClass();
//第三种
String className = "com.wfg.Person";
Class perClass3 = Class.forName(className);
//第四种 通过类加载器
Class perClass4 = this.getClass().getClassLoader().loadClass(className);
System.out.println(perClass);
System.out.println(perClass2);
System.out.println(perClass3);
System.out.println(perClass4);
}
获取到Class就可以获取对象:
//创建实例
Person p = (Person)perClass.newInstance();
获取属性并对属性赋值
//获取属性
Field[] fields = perClass.getFields(); //
for (Field field : fields) {
System.out.println(field); //这时候并没有获取到,原因是属性是private
//这种方法好像只能获取到public的属性
}
Field[] fields1 = perClass.getDeclaredFields(); //这种可以获取到private的方法
for (Field field : fields1) {
System.out.println(field);
}
//获取特定的属性并赋值
Field ageField = perClass.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(p, 11);
System.out.println(p);
获取相应的方法
@Test
public void test3() throws Exception {
Class perClass = Person.class;
//创建实例
Person p = (Person)perClass.newInstance();
//获取public的方法
Method showMethod = perClass.getMethod("show");
showMethod.invoke(p);
//获取私有方法
Method displayMethod = perClass.getDeclaredMethod("display");
displayMethod.setAccessible(true);
displayMethod.invoke(p);
//获取重写方法
Method displayMethod1 = perClass.getDeclaredMethod("display",String.class);
displayMethod1.setAccessible(true);
displayMethod1.invoke(p,"hk");
}
我们可以看api获取其他的一些信息如:构造器,继承类,接口,内部类等等一些信息
下面再随便说说类加载器,后面的篇章会详细介绍类加载器
@Test
public void Test4() throws Exception{
//系统类加载器
ClassLoader cl1 =ClassLoader.getSystemClassLoader();
System.out.println(cl1);
// 扩展类加载器
ClassLoader cl2 = cl1.getParent();
System.out.println(cl2);
//引导类加载器 该加载器不能直接获取
ClassLoader cl3 = cl2.getParent();
System.out.println(cl3);
//类加载器的使用
String fileName = "com//wfg//jdbc.txt";
InputStream is = this.getClass().getClassLoader().getResourceAsStream(fileName);
Properties p = new Properties();
p.load(is);
System.out.println(p.getProperty("username"));
}