黑马程序员_反射

---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------

        今天学习了张老师高新技术里面的反射,因为以前没有接触过反射机制,所以学起来感觉有些费劲,而且很多地方都是反复看了好几遍,不过好在终于看明白了。

1:反射的定义:

          反射可以理解为一种动态技术,它可以将类中的组成部分在运行阶段将其抽取出来,映射成一个个Java对象,通过这些对象可以完成功能。

2:反射的作用:反射用于简化代码,提高代码的复用性。反射一般用于框架中,写出复用性高的通用代码。

3:映射对象的分类:

        类是由构造方法,成员变量和成员方法组成的,所以在映射的过程中,类也被映射成三种对象,构造方法被映射成Constructor对象,成员变量被映射成Field对象,成员方法被映射成Method对象。

        抽取出来的Constructor对象用于创建对象,Field对象用于封装数据,Method对象用于调用,完成功能。

4:获取方式:

        Constructor,Field,Method都是通过Class获取的。

        Class类:

                Class类的实例表示正在运行的Java应用程序中的接口和类,简单理解就是字节码文件对象。

        获取Class的方式有三种,分别是:

                类名.Class;

                new对象().getClass();

                Class.("类名.包名");

        在一般的开发中,推荐使用第三种方式获取,因为这种方式耦合度低。

5:Constructor类:

        Constructor类代表的是构造器对象,得到构造器就可以创建对象。

        Constructor类对象的获取方式:

                A:获取public修饰的构造器: 

                Constructor c = Class.getConstructor(Class ... c);

                参数代表的是构造方法的参数类型的Class,返回的是一个构造其对象。

                Constructor[] c = Class.getConstructors();

                获取所有的构造器对象。返回的是一个Constructor类型的数组。

                B:获取非公共的构造器:

                Constructor c = Class.getDeclaredConstructors(Class...c);

                Constructor c = Class.getDeclaredConstructors();

        Constructor对象的使用:

                getName();                            获取构造器的名称

                newInstance(Object...obj);         创建实例对象

        注意:如果是非公共的构造器,我们可以通过getDeclaredConstructor()去获取构造器对象,但是不能直接使用。

        如果在Constructor,Field,Method中所使用的操作是有权限范围的(非公有的),这是 可以通过从父类:AccessibleObject继承的setAccessible(true)这样的方式,将权限检查取消。

例如:

package cn.itcast;
public class Person {
 
 public String name = "哈哈";
 //定义类的构造方法
 public Person(){
  System.out.println("person");
 }
 
 public Person(String name) {
  System.out.println(name);
 }
 
 public Person(String name,int age) {
  System.out.println(name + "---" + age);
 }
 
} 

// 反射构造方法:public Person(String name){}
 @Test
 public void test2() throws Exception {
//  1:先加载类
  Class c = Class.forName("cn.itcast.Person");
//  2:获取构造方法
  Constructor ct = c.getConstructor(String.class);
//  3:调用已经获取到的构造方法创建对象
  Person p = (Person)ct.newInstance("王璐");
//  4:访问创建的对象
  System.out.println(p.name);
 }

 这个例子中就是利用反射获取类构造器,然后进行创建对象的。

6:Field类:

        A:获取Field类的对象:

                获取public修饰的Field:

                Field f = Class.getField(String name);

                Filed[] f = Class.getFields();        返回的是一个Field类型的数组

                获取非公有的Field类的的对象:

                Field f = Class.getDeclaredField(String name);

                Field[] f = Class.getDeclaredFields();

                其中的参数name代表的是成员变量的名称,是一个字符串类型。

        B:对成员变量进行赋值操作:

                set(Object obj,Object value)        赋值操作

                其中的obj是要进行操作的对象,value是要给指定对象赋的值。

                get(Object obj)

                这是对获取到的成员变量进行取值。

例如下面就是一个对Field进行反射的例子:

 package cn.itcast.field;
public class Student {
 public String name; 
 public String sex;
 private int age;
 public Student() {
  super();
 }
 public Student(String name,String sex,int age) {
  super();
  this.name = name;
  this.sex = sex;
  this.age = age;
 }
 public Student(int age) {
  super();
  this.age = age;
 }
 public Student(String name) {
  super();
  this.name = name;
 }
 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;
 }
}

package cn.itcast.field;
import java.lang.reflect.Field;
import org.junit.Test;
public class StudentTest {
 @Test
 public void test2() throws Exception {
  
  Student s = new Student();
  //获取Class类对象
  Class c = Class.forName("cn.itcast.field.Student");
  //获取Field对象
  Field f = c.getField("sex");
  Field f1 = c.getField("name");
  Field f2 = c.getDeclaredField("age");
  //对非公有变量的Field对象进行暴力反射(取消权限检查)
  f2.setAccessible(true);
  //对Field对象进行赋值
  f.set(s, "男");
  f1.set(s, "王璐");
  f2.set(s,20);
  System.out.println(f.get(s));
  System.out.println(f1.get(s));
  System.out.println(f2.get(s));
 }
}

7:Method类:

        A:获取Method类的对象:

                getMethod(String s,Class...c);

                用于获取指定名称的public修饰的方法。

                getDeclaredMethod(String s,Class c);   

                用于获取指定名称的方法,不考虑方法的权限。

                getMethods();

                得到所有的方法,包括从父类继承的方法,返回的是一个方法的集合。

                getDeclaredMethods();

                获取本类的所有方法。

        B:调用Method对象:

                Object invoke(Object obj,Objevt...args);

                其中obj代表的是执行当前方法的对象,args是该方法的参数。

        注意:invoke()方法返回的是Method对象代表的方法执行后的结果。

                通过反射调用一个静态方法时,它的调用者可以是null。

                在调用invoke()方法时,如果传入的参数是一个数组,那么在传参数时,会将数组中的元素拆分开来,这样传入参数的参数类型和所需的参数类型就不匹配了,就会报错。解决方法是在数组外面再报一层数组,就相当于一个二维数组,或者将要传入的数组强转成Object类型。 

例如下面就是一个获取Method对象并进行调用的例子:

 package cn.itcast.field;
public class Student {
 public String name; 
 public String sex;
 private int age;
 public Student() {
  super();
 }
 public Student(String name,String sex,int age) {
  super();
  this.name = name;
  this.sex = sex;
  this.age = age;
 }
 public Student(int age) {
  super();
  this.age = age;
 }
 public Student(String name) {
  super();
  this.name = name;
 }
 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;
 }
}

package cn.itcast.field;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.junit.Test;
public class StudentTest {
 @Test
 public void test3() throws Exception {
  Student s = new Student();
  //获取Class对象
  Class c = Class.forName("cn.itcast.field.Student");
  //获取Method对象
  Method m_set = c.getDeclaredMethod("setName", String.class);

  Method m_get = c.getDeclaredMethod("getName");
  //调用Method对象完成功能
  String name = (String) m_set.invoke(s, "haha");
   
  System.out.println(m_get.invoke(s));
 } 
}

         在反射中,Method类是最重要的,也是最难理解的,尤其是后面的出入参数是数组的内容,感觉非常的绕,思维很难转过那个弯,多看了好几遍,以后还要多多理解啊       

---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------详细请查看:<a href="http://www.itheima.com" target="blank">www.itheima.com</a>

                            

 

      

转载于:https://my.oschina.net/u/1390204/blog/287131

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值