定义
反射: 将类的各个组成部分封装为其他对象
获取Class类的对象
public class Test1 {
/*
关于java.Lang.cLass类的理解
1.类的加载过程:程序经过javac.exe命令以后,会生成一个或多个字节码文件(.cLass结尾)。
接着我们使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中。
此过程就称为类的加载。加载到内存中的类,我们就称为运行时类,此运行时类,就作为CLass的一个实例。
2.换句话说,CLass的实例就对应着一个运行时类。
3.加载到内存中的运行时类,会缓存一定的时间。在此时间之内,我们可以通过不同的方式来获取此运行时类。
*/
@Test
public void test1() throws ClassNotFoundException {
//方式一:类.class
Class clazz1= Person1.class;
//方式二:对象.getClass()
Person1 p1=new Person1();
Class clazz2=p1.getClass();
//方式三:Class.forName(String calssPath)//用得最多,更好的体现出动态性
Class clazz3=Class.forName("ReflectionTest.Person1");
//方式四:使用类的加载器:ClassLoader(了解)
ClassLoader classLoader= Test1.class.getClassLoader();
Class clazz4=classLoader.loadClass("ReflectionTest.Person1");
}
// 只要元素类型与维度(数组)一样,就是同一个Class
}
创建运行时类的对象newInstance()
@Test
public void test1() throws Exception {
class<Person> clazz=Person.class;
//newInstance()调用了运行时类的空参的构造器,且默认调用super()时,保证父类有空参构造器
Person p=clazz.newInstance();
}
获取运行时类的构造器,属性,方法
@Test
public void test1(){
//获取该类的运行时类
Class clazz= Person.class;
//构造器
Constructor[] con=clazz.getConstructors();//getConstructors():获取当前类中声明为public的构造器
Constructor[] dcon=clazz.getDeclaredConstructors();
//属性
Field[] fields = clazz.getFields();//getFields():获取当前运行时类及其父类中声明为public访问权限的属性
Field[] declaredFields = clazz.getDeclaredFields();//getDeclaredFields()获取当前类中声明的属性(不包含父类中声明的属性)
Class type=field.getType();//获取属性的数据类型
int modifiers = field.getModifiers();//获取属性的权限修饰符
//方法
Method[] methods=clazz.getMethods();//获取当前运行时类及其所有父类中声明为public权限的方法
Method[] declaredMethods=clazz.getDeclaredMethods();//获取当前运行是咧中声明的所有方法(不包含父类中声明的方法)
}
操作运行时类的构造器,属性,方法
public static void main(String[] args) throws Exception {
//获取该类的运行时类
Class personClass= Person.class;
Person person = (Person)personClass.newInstance();
/**
* 操作属性
*/
Field name = personClass.getDeclaredField("name");
//确保当前属性是可以访问的
name.setAccessible(true);
//赋值
name.set(person,"张三");
//取值
String personName = (String) name.get(person);
System.out.println(personName);
/**
* 操作方法
*/
Method show = personClass.getDeclaredMethod("show", String.class);
//3.保证当前方法是可访问的
show.setAccessible(true);
//调用方法invoke()其返回值即为对应类中调用的方法的返回值,没有返回值则返回null
Object helloWorld = show.invoke(person, "hello world");
/**
* 利用构造器创建对象
*/
Constructor declaredConstructor = personClass.getDeclaredConstructor(String.class);
declaredConstructor.setAccessible(true);
Person constructorPerson = (Person)declaredConstructor.newInstance("hello Constructor");
}
获取类的加载器
@Test
public void test1() {
//对于自定义类,使用系统类加载器进行加载
ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
//调用系统类加载器的getParent():获取扩展类加载器
ClassLoader classLoader1 = classLoader.getParent();
//调用扩展类加载器的getParent():无法获取引导类加载器
//引导类加载器主要负责加载Java核心类库,无法加载自定义类
ClassLoader classLoader2 = classLoader1.getParent();
System.out.println(classLoader2);/null
//举例:String:引导类加载器加载
ClassLoader classLoader3 = String.class.getClassLoader();
System.out.println(classLoader3);
}
读取配置文件Properties
@Test
public void test3() throws IOException {
Properties pros = new Properties();
//方式1:此时读取文件路径默认在module下
FileInputStream fis=new FileInputStream("src\\jdbc.properties");
pros.load(fis);
//方式2:此时读取文件路径默认在src下
// ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
// InputStream is=classLoader.getResourceAsStream("jdbc.properties");
// pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
System.out.println(user + "/" + password);
}