一、通过反射获取对象,并操作属性
public class Person {
public int age;
public String name;
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/*
反射第一步:获取Class类的对象
*/
public class ReflectionTest {
@Test
public void test1() {
Person person = new Person();
person.setName("aa");
person.setAge(11);
System.out.println(person);
}
// 有了反射,可通过反射创建一个类的对象,并且可以调用其中的方法和属性
@Test // 此为类找不到异常
public void test() throws Exception{
//正常获取对象方法
Person person = new Person();
System.out.println(person);
//通过反射获取对象方法!!!
//1、获取的是Class类的对象,而不是Person类的对象(Class是类类,不是类)
Class> personClass = Class.forName("com.gr.Person");
//2、通过反射创建出Person类的对象(如果不转换,他是一个Object对象)
Person o = (Person) personClass.newInstance();
System.out.println(personClass);
//3、通过反射调用运行时类的属性
Field name = personClass.getField("name"); //只能获取public修饰的属性
//为o这个对象的name属性赋值
name.set(o,"姓名");
//getDeclaredField是可以获取一个类的所有字段.
//getField只能获取类的public 字段.
Field age = personClass.getDeclaredField("age");
// 在Java中可以通过反射进行获取实体类中的字段值,当未设置Field的setAccessible方法为true时,会在调用的时候进行访问安全检查,会抛出异常.
//将此对象的accessible标志设置为指示的布尔值。true的值表表示反射对象应该在使用时抑制Java访问检查。false表示反映的对象应该强制执行Java访问
//检查
age.setAccessible(true);
age.set(o,23);
}
}
二、通过反射获取并调用方法
public class Person {
public int age;
public String name;
public void show(){
System.out.println("this is show method");
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/*
反射第一步:获取Class类的对象
*/
public class ReflectionTest {
@Test
public void test1() {
Person person = new Person();
person.setName("aa");
person.setAge(11);
System.out.println(person);
}
// 有了反射,可通过反射创建一个类的对象,并且可以调用其中的方法和属性
@Test // 此为类找不到异常
public void test() throws Exception{
//正常获取对象方法
Person person = new Person();
System.out.println(person);
//通过反射获取对象方法!!!
//1、获取的是Class类的对象,而不是Person类的对象(Class是类类,不是类)
Class> personClass = Class.forName("com.gr.Person");
//2、通过反射创建出Person类的对象(如果不转换,他是一个Object对象)
Person o = (Person) personClass.newInstance();
//通过反射获取并调用方法
// 如果方法有参数,就在“show”后面加,参数
Method showmethod = personClass.getMethod("show");
//如果有参数就在o后面加,参数
showmethod.invoke(o);
}
}
三、通过反射获取并调用有参方法
public class Person {
public int age;
public String name;
public void run(int a,String str){
System.out.println("a="+a+"and string"+str);
}
// 用于反射调用方法时候使用
public void show(){
System.out.println("this is show method");
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/*
反射第一步:获取Class类的对象
*/
public class ReflectionTest {
@Test
public void test1() {
Person person = new Person();
person.setName("aa");
person.setAge(11);
System.out.println(person);
}
// 有了反射,可通过反射创建一个类的对象,并且可以调用其中的方法和属性
@Test // 此为类找不到异常
public void test() throws Exception{
//正常获取对象方法
Person person = new Person();
System.out.println(person);
//通过反射获取对象方法!!!
//1、获取的是Class类的对象,而不是Person类的对象(Class是类类,不是类)
Class> personClass = Class.forName("com.gr.Person");
//2、通过反射创建出Person类的对象(如果不转换,他是一个Object对象)
Person o = (Person) personClass.newInstance();
//反射调用有参方法
Method showmethod1 = personClass.getMethod("run",Integer.class,String.class);
showmethod1.invoke(o,123,"string类型");
}
}
提出问题:为什么要通过3方法来这么麻烦的进行属性赋值,而不是简单的o.setAge(12);???(看楼下=====处代码)
// 有了反射,可通过反射创建一个类的对象,并且可以调用其中的方法和属性
@Test // 此为类找不到异常
public void test() throws Exception{
//正常获取对象方法
Person person = new Person();
System.out.println(person);
//通过反射获取对象方法!!!
//1、获取的是Class类的对象,而不是Person类的对象(Class是类类,不是类)
Class> personClass = Class.forName("com.gr.Person");
//2、通过反射创建出Person类的对象(如果不转换,他是一个Object对象)
Person o = (Person) personClass.newInstance();
System.out.println(personClass);
// ============= 提出一个问题:为什么要通过3方法来这么麻烦的进行属性赋值,而不是简单的
// o.setAge(12);???
// 答:因为楼上是在编译时就进行了加载,而楼下可以在编译时不去确定他要获取什么,可以通过 // 楼下方式来在运行时进行特性方法的加载。
//3、通过反射调用运行时类的属性
Field name = personClass.getField("name"); //只能获取public修饰的属性
//为o这个对象的name属性赋值
name.set(o,"姓名");
//getDeclaredField是可以获取一个类的所有字段.
//getField只能获取类的public 字段.
Field age = personClass.getDeclaredField("age");
// 在Java中可以通过反射进行获取实体类中的字段值,当未设置Field的setAccessible方法为true时,会在调用的时候进行访问安全检查,会抛出异常.
//将此对象的accessible标志设置为指示的布尔值。true的值表表示反射对象应该在使用时抑制Java访问检查。false表示反映的对象应该强制执行Java访问
//检查
age.setAccessible(true);
age.set(o,23);
}
总结:
获取Class对象的几种方式
public void test3() throws Exception{
//1、调用运行时类本身的.class属性
Class personClass = Person.class;
System.out.println(personClass);
//2、通过运行时类的对象获取
Person person = new Person();
Class aClass = person.getClass();
System.out.println(aClass);
//3、通过Class的静态方法来获取,体现了反射的动态性
String name = "com.gr.Person"; //包名+类名的全路径
Class aClass1 = Class.forName(name);
System.out.println(aClass1);
//4、通过类加载器获取 获取当前类对象,再用ClassLoader加载器加载
ClassLoader classLoader = this.getClass().getClassLoader();
Class aClass2 = classLoader.loadClass(name);
System.out.println(aClass2);
}
java.lang.Class是反射的源头。
我们创建一个类,通过编译(javac.exe)生成字节码文件.class文件,之后我们使用java.exe加载(JVM的类加载器完成的) *bootstap ClassLoader是引导类加载器,用c++编写的,是JVM自带的类加载器,负责java平台核心库,用来加载核心类库。该加载器无法直接获取。 *Extension ClassLoader是扩展类加载器:负责jre/lib/ext目录下的jar包装入工作库 *System ClassLoader是负责java-classpath所有目录下的类包装入类库最常见的加载器
此.class文件加载到内存中去以后,就是一个运行时类,存在缓冲区,那么这个运行时类本身就是Class的实例
每个运行时类只加载一次
有了Class的实例之后,我们可以做如下操作
*创建对应的运行时类的对象
*获取对应的运行时类的属性,方法,构造方法,父类,所在的包,异常,接口等
*调用对应的运行时类的属性,方法,构造方法等
如果觉得这篇文章对你有小小的帮助的话,多多支持网站