Java 反射机制
Java 反射机制 课程内容 1.理解Class类并实例化Class类对象
- 运行时创建类对象并获取类的完整结构
3.通过反射调用类的指定方法、指定属性
4.动态代理
- 反射相关的主要API:
- java.lang.Class:代表一个类
- java.lang.reflect.Method:代表类的方法
- java.lang.reflect.Field:代表类的成员变量
- java.lang.reflect.Constructor:代表类的构造方法
- 。。。
了解:ClassLoader
//1.获取一个系统类加载器
ClassLoader classloader = ClassLoader.getSystemClassLoader();
System.out.println(classloader);
//2.获取系统类加载器的父类加载器,即扩展类加载器
classloader = classloader.getParent();
System.out.println(classloader);
//3.获取扩展类加载器的父类加载器,即引导类加载器
classloader = classloader.getParent();
System.out.println(classloader);
//4.测试当前类由哪个类加载器进行加载
classloader =
Class.forName("exer2.ClassloaderDemo").getClassLoader();
System.out.println(classloader);
//5.测试JDK提供的Object类由哪个类加载器加载
classloader =
Class.forName("java.lang.Object").getClassLoader();
System.out.println(classloader);
//*6.关于类加载器的一个主要方法:getResourceAsStream(String str):获取类路径下的指定文件的输入流
InputStream in = null;
in = this.getClass().getClassLoader().getResourceAsStream("exer2\\test.properties");
System.out.println(in);
package nineteen;
import java.io.File;
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 {
//四、关于类的加载器:ClassLoader
@Test
public void test5() throws Exception{
ClassLoader loader1 = ClassLoader.getSystemClassLoader();
System.out.println(loader1);
ClassLoader loader2 = loader1.getParent();
System.out.println(loader2);
ClassLoader loader3 = loader2.getParent();
System.out.println(loader3);
Class clazz1 = Person.class;
ClassLoader loader4 = clazz1.getClassLoader();
System.out.println(loader4);
String className = "java.lang.String";
Class clazz2 = Class.forName(className);
ClassLoader loader5 = clazz2.getClassLoader();
System.out.println(loader5);
//掌握如下
//法一:文件在指定包下
System.out.println();
ClassLoader loader = this.getClass().getClassLoader();
InputStream is = loader.getResourceAsStream("nineteen\\jdbc.properties");
//法二:文件在工程目录下
// FileInputStream is = new FileInputStream(new File("jdbc1.properties"));
Properties pros = new Properties();
pros.load(is);
String name = pros.getProperty("user");
System.out.println(name);
String password = pros.getProperty("password");
System.out.println(password);
}
//三、如何获取Class的实例(4种)
@Test
public void test4() throws ClassNotFoundException{
//1.调用运行时类本身的.class属性
//前提:若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高
Class clazz1 = Person.class;
System.out.println(clazz1.getName());//nineteen.Person
Class clazz2 = String.class;
System.out.println(clazz2.getName());//java.lang.String
//2.通过运行时类的对象获取
//前提:已知某个类的实例,调用该实例的getClass()方法获取Class对象
Person p = new Person();
Class clazz3 = p.getClass();
System.out.println(clazz3.getName());//nineteen.Person
//3.通过Class的静态方法获取.通过此方式,体会一下,反射的动态性。
//前提:已知一个类的全类名,且该类在类路径下,可通过
// Class类的静态方法forName()获取,可能抛出ClassNotFoundException
String className = "nineteen.Person";
Class clazz4 = Class.forName(className);
// clazz4.newInstance();//具有通用性,创建一个实例后,可操作许多事
System.out.println(clazz4.getName());//nineteen.Person
//4.(了解)通过类的加载器
ClassLoader classLoader = this.getClass().getClassLoader();
Class clazz5 = classLoader.loadClass(className);
System.out.println(clazz5.getName());//nineteen.TestReflection
System.out.println(clazz1 == clazz3);//true 指向同一个地址,即都为同一个
System.out.println(clazz1 == clazz4);//true
System.out.println(clazz1 == clazz5);//true
}
//二、理解反射的源头之 Class类
/**
* java.lang.Class:是反射的源头。
* 我们创建了一个类,通过编译(javac.exe),生成对应的.class文件。之后我们使用java.exe加载(JVM的类加载器完成的)
* 此.class文件,此.class文件加载到内存以后,就是一个运行时类,存在在缓存区。那么这个运行时类本身就是一个Class的实例!
* 1.每一个运行时类只加载一次!
* 2.有了Class的实例以后,我们才可以进行如下的操作:
* 1)*创建对应的运行时类的对象
* 2)获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解、...)
* 3)*调用对应的运行时类的指定的结构(属性、方法、构造器)
* 4)反射的应用:动态代理
*/
@Test
public void test3(){
Person p = new Person();//实例化对象
Class clazz = p.getClass();//通过运行时类的对象,调用其getClass(),返回其运行时类。
System.out.println(clazz);//得到完整的“包类”名称
}
//一、反射的应用实例
//有了反射,可以通过反射创建一个类的对象,并调用其中的结构
@Test
public void test2() throws Exception{
Class clazz = Person.class;
// Class clazz1 = String.class;
//1.创建clazz对应的运行时类Person类的对象
Person p = (Person)clazz.newInstance();
System.out.println(p);
//2.通过反射调用运行时类的指定的属性
//2.1
Field f1 = clazz.getField("name");
f1.set(p,"LiuDeHua");
System.out.println(p);
//2.2
Field f2 = clazz.getDeclaredField("age");
f2.setAccessible(true);
f2.set(p, 20);
System.out.println(p);
//3.通过反射调用运行时类的指定的方法
Method m1 = clazz.getMethod("show");
m1.invoke(p);
Method m2 = clazz.getMethod("display",String.class);
m2.invoke(p,"CHN");
}
//在有反射以前,如何创建一个类的对象,并调用其中的方法、属性
@Test
public void test1(){
Person p = new Person();
// Person p1 = new Person();
p.setAge(10);
p.setName("TangWei");
System.out.println(p);
p.show();
// p.display("HK");
}
}
package nineteen;
public class Person{
public String name;
private int age;
//创建类时,尽量保留一个空参的构造器。
public Person() {
super();
// System.out.println("今天天气很闷热");
}
public Person(String name) {
super();
this.name = name;
}
private 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 nation) {
System.out.println("我的国籍是:" + nation);
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public static void info(){
System.out.println("中国人!");
}
}
韧桂 2020-01-11