图一:
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 + "]"; } }