java 反射.问题_Java 反射原理详解及使用反射解决的问题

一、通过反射获取对象,并操作属性

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的实例之后,我们可以做如下操作

*创建对应的运行时类的对象

*获取对应的运行时类的属性,方法,构造方法,父类,所在的包,异常,接口等

*调用对应的运行时类的属性,方法,构造方法等

如果觉得这篇文章对你有小小的帮助的话,多多支持网站

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值