图一:
java.lang.Class:是反射的源头。
我们创建了一个类,通过编译(javac.exe),生成对应的.class文件。之后我们使用java.exe加载(JVM的类加载器完成的)
此.class文件,此.class文件加载到内存以后,就是一个运行时类,存在在缓存区。那么这个运行时类本身就是一个Class的实例!
1.每一个运行时类只加载一次!
2.有了Class的实例以后,我们才可以进行如下的操作:
1)*创建对应的运行时类的对象
2)获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解、...)
3)*调用对应的运行时类的指定的结构(属性、方法、构造器)
4)反射的应用:动态代理
示例代码:
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;
import org.junit.Test;
public class TestReflection {
/*
* 有了反射,可以通过反射创建一个类的对象,并调用其中的结构
*/
@Test
public void test1() throws Exception {
Class clz = Person.class;
//1.创建clz对应的运行时类Person类的对象
Person p = (Person) clz.newInstance();
System.out.println(p);
//2.通过反射调用运行时类的指定属性
Field f1 = clz.getField("name");
f1.set(p, "小明");
System.out.println(p);
Field f2 = clz.getDeclaredField("age");//获取声明的属性
f2.setAccessible(true);//可见性设置为可见
f2.set(p, 23);
System.out.println(p);
//3.通过反射调用运行时类的指定的方法
Method m1 = clz.getMethod("show");
m1.invoke(p);
Method m2 = clz.getMethod("display", String.class);
m2.invoke(p, "CHN");
}
/*
* 获取Class实例的3种方式
*/
@Test
public void testGetClass() throws ClassNotFoundException {
//1.调用运行时类本身的.class属性
Class clz1 = Person.class;
System.out.println(clz1.getName());
Class clz2 = String.class;
System.out.println(clz2.getName());
//2.通过运行时类的对象获取
Person p = new Person();
Class clz3= p.getClass();
System.out.println(clz3.getName());
//3.通过Class的静态方法获取(通过此方法,体会一下反射的动态性)
String className = "com.iting.testJava.main.Person";
Class clz4 = Class.forName(className);
System.out.println(clz4.getName());
//4.(了解)通过类的加载器
ClassLoader classLoader = this.getClass().getClassLoader();
Class clz5 = classLoader.loadClass(className);
System.out.println(clz5.getName());
}
/*
* 关于类的加载器:ClassLoader
*/
@Test
public void testClassLoader() throws Exception {
ClassLoader loader1 = ClassLoader.getSystemClassLoader();
//System ClassLoader可直接获取
System.out.println(loader1);//sun.misc.Launcher$AppClassLoader@dad5dc
ClassLoader loader2 = loader1.getParent();
//Extension ClassLoader可直接获取
System.out.println(loader2);//sun.misc.Launcher$ExtClassLoader@9c9116
ClassLoader loader3 = loader2.getParent();
//Bootstrap ClassLoader无法直接获取
System.out.println(loader3);//null
//自定义类存放在System ClassLoader
Class clz1 = Person.class;
ClassLoader loader4 = clz1.getClassLoader();
System.out.println(loader4);//sun.misc.Launcher$AppClassLoader@dad5dc
//核心类库由Bootstrap ClassLoader加载
String className = "java.lang.String";
Class clz2 = Class.forName(className);
ClassLoader loader5 = clz2.getClassLoader();
System.out.println(loader5);//null
/*
* 需掌握如下:
*/
ClassLoader loader = this.getClass().getClassLoader();//获取自定类的加载器(System ClassLoader)
System.out.println(loader);//sun.misc.Launcher$AppClassLoader@dad5dc
//方法一:放在包下
InputStream is = loader.getResourceAsStream("com\\iting\\testJava\\main\\jdbc.properties");
//方法二:放在工程下
//FileInputStream is = new FileInputStream("jdbc1.properties");
Properties pro = new Properties();
pro.load(is);
String user = pro.getProperty("user");
System.out.println(user);
String password = pro.getProperty("password");
System.out.println(password);
}
}
class Person {
public String name;
private int age;
public Person() {
super();
}
public Person(String name) {
super();
this.name = name;
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void show() {
System.out.println("我是好人!");
}
public void display(String str) {
System.out.println("我的国籍是" + str);
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}