黑马程序员—java技术blog—第十三篇反射的基础概述与总结

------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com"
反射基础概述总结:

  反射的基本: Class类

           Java程序中的各个Java类属于内同一类食物,描述这类事物的Java类名就是Class

         类似于Person类代表人,那么同样的Class类代表着一个个的CLass类
          Person类可以是一个实例,名叫张三,Class类也可以有一个对象,名叫String.class

         如何得到各个类字节码对应的实例对象(Class类型)
        类名.class 如:String.class
       对象.getClass() 如:new Date().getClass()
      Class.forName("类名") 如:Class.forNmae("java.util.Date")

      九个预定义Class实例对象

       参看Class.isPrimitive方法的帮助文档
       Int.class == Integer.TYPE

      数组类型的Class实例对象
     Class.isArray()
             总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如:int[], void ...

2、反射的概念

      反射就是把Java类中的各种成份映射成相应的java类。

        例如:一个Java类中用一个Class类的对象来表示,
       一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示。
       表示Java类中的Class类显然要提供一系列的方法,来获得其中的变量(Field),方法(Method),构造方法(Constructor),修饰符,       包(Package)等信息

      一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示。
      通过调用Class类方法可以得到这些实例对象

3、Constructor类

    代表某个类中的构造方法

   得到某一个类的所有构造方法
   Constructorcon=Class.forName("java.lang.String").getConstructor();

   得到某一个类的某一个构造方法
   Constructorcon=Class.forName("java.lang.String").getConstructor(StringBuffer.class);

   创建实例对象:
   通常方法:String str =new String(newStringBuffer("abc"));
   反射方法:
  String str = (String)con.newInstance(new StringBuffer("abc"));

   Class.newInstance()方法:
  例子:String obj=(String)Class.foName("java.lang.String").newInstance();
  该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象
   用到了缓存机制来保存默认构造方法的实例对象

4、Field类

  代表某个类中的成员变量

  得到的Field对象是对应到类上的成员变量

5、Method类

  代 表某个类中的成员方法

  得到类中的某一个方法:
Method chatAt =Class.forName("java.lang.String").getMethod("charAt",int.class);

  调用方法:
  通常方式:System.out.println(str.charAt(1));
  反射方法:System.out.println(chatAt.invoke(str,1));
  如果传递给Method对象的invoke()方法的一个参数为null,说明该Method对象对应的是一个静态方法

  jdk1.4和jdk1.5的invoke方法的区别
  jdk 1.5:public Object invoke(Object obj,Object ...arge)
  jdk 1.4 public Object invoke(Object obj,Object[] agrs)
  即:jdk 1.4传递的参数是数组形式,jdk 1.5是可变参数形式

6、数组的反射

  具有相同维数的数组属于同一个类型,即具有相同的Class实例对象

  代表数组的Class实例对象的getSuperClass()方法返回的父类位Object类对应的Class

  基本类型的以为数组可以被当作Object类型使用,不能当作Object[]类型使用
  非基本类型的一维数组,既可以当作Object类型使用,又可以当作Object[]类型使用
  Array.asList()方法处理int[]和String[]是的差异,
  Array工具类用于完成对数组的反射的操作。

7、反射的作用——实现框架功能

  框架与框架要解决的核心问题

  我们在写的框架,相当一间毛坯房,写好了之后又用户住进来会进行装修,变成自己的个性的房子。相当于其他程序员调用我们这  个框架,在这个基础上来写他的程序。
  因为在写程序是无法知道要被调用的类名,所以,在程序中无法new某个类的实例对象,所以要用反射方式来做。

--------------------------------------------------------------------------------------

 

// 如何生成获取到字节码文件对象的实例对象。

        Classclazz = Class.forName("classTest.User");// 类加载

// 直接获得指定的类型

       clazz= User.class;

       // 根据对象获得类型

       Objectobj = new User("ly", 123456);

       clazz= obj.getClass();

 

        Objectobj = clazz.newInstance();//该实例化对象的方法调用就是指定类中的空参数构造函数,给创建对象进行初始化。当指定类中没有空参数构造函数时,该如何创建该类对象呢?请看method_2();

    public staticvoid method_2() throws Exception {

        Classclazz = Class.forName("classTest.User");

        //既然类中没有空参数的构造函数,那么只有获取指定参数的构造函数,用该函数来进行实例化。

        //获取一个带参数的构造器。

        Constructorconstructor = clazz.getConstructor(String.class,int.class);

        //想要对对象进行初始化,使用构造器的方法newInstance();

        Objectobj = constructor.newInstance("ly",123456);

        //获取所有构造器。

        Constructor[]constructors = clazz.getConstructors();//只包含公共的

        constructors= clazz.getDeclaredConstructors();//包含私有的

        for(Constructorcon : constructors) {

            System.out.println(con);

        }

    }

------------------------------------------------------

反射指定类中的方法:

    //获取类中所有的方法。

    public staticvoid method_1() throws Exception {

        Classclazz = Class.forName("classTest.User");

        Method[]methods = clazz.getMethods();//获取的是该类中的公有方法和父类中的公有方法。

        methods= clazz.getDeclaredMethods();//获取本类中的方法,包含私有方法。

        for(Methodmethod : methods) {

            System.out.println(method);

        }

    }

    //获取指定方法;

    public staticvoid method_2() throws Exception {

        Classclazz = Class.forName("classTest.User");

        //获取指定名称的方法。

        Methodmethod = clazz.getMethod("abc", String.class,int.class);

        //想要运行指定方法,当然是方法对象最清楚,为了让方法运行,调用方法对象的invoke方法即可,但是方法运行必须要明确所属的对象和具体的实际参数。

        Objectobj = clazz.newInstance();

        method.invoke(obj,"user",123);//执行一个方法

    }

    //想要运行私有方法。

    public staticvoid method_3() throws Exception {

        Classclazz = Class.forName("classTest.User");

        //想要获取私有方法。必须用getDeclearMethod();

        Methodmethod = clazz.getDeclaredMethod("method", null);

        // 私有方法不能直接访问,因为权限不够。非要访问,可以通过暴力的方式。

        method.setAccessible(true);//一般很少用,因为私有就是隐藏起来,所以尽量不要访问。

    }

    //反射静态方法。

    public staticvoid method_4() throws Exception {

        Classclazz = Class.forName("classTest.User");

        Methodmethod = clazz.getMethod("function",null);

        method.invoke(null,null);

    }

 

反射的一些具体用法

首先我们先准备一个实体类

package classTest;

 

importjava.io.InputStream;

import java.util.List;

 

public class User {

      

       //==========================字段(属性)=====================

       publicString name = "abc";

       privateint password = 123;

       privatestatic int age =20;

      

      

       //====================构造方法===================

       publicUser(){

              System.out.println("User");

       }

      

       publicUser(String name){

              System.out.println(name);

       }

      

       publicUser(String name,int password){

              System.out.println(name+"+"+password);

       }

      

       privateUser(List list){

              System.out.println("list");

       }

      

      

       //==================普通方法========================

       publicvoid abc(){

              System.out.println("abc");

       }

      

       publicvoid abc(String name,int password){

              System.out.println(name+":"+password);

       }

      

       publicClass[] abc(String name,int[] password){

              returnnew Class[]{String.class};

       }

      

       privatevoid abc(InputStream in){

              System.out.println(in);

       }

      

       publicstatic void abc(int num){

              System.out.println(num);

       }

      

       publicstatic void main(String[] args) {

              System.out.println("main!");

       }

      

       publicstatic void abc(int[] args){

              System.out.println("aaaa");

       }

      

}

这个实体类中基本包含了对象的各种成分,之后我们就对这个实体类举例

 

1)、需要获得java类的各个组成部分,首先需要获得类的Class对象,获得Class对象的三种方式:

package classTest;

 

 

public class Test1 {

 

       public static void main(String[] argsthrows Exception {

             

              //第一种:没有类也没有对象

              Class class1 = Class.forName("classTest.User");

             

             

              //第二种:已知对象

              Class class2 = new User().getClass();

             

              //第三种:已知类

              Class class3 = User.class;

             

              System.out.println(class1.hashCode());

              System.out.println(class2.hashCode());

              System.out.println(class3.hashCode());

 

       }

 

}

运行结果:

User

366712642

366712642

366712642

 

从结果上我们可以看到三种方式都是调用了无参的构造方法,得到的字节码都是一样的

2)、反射类的成员方法:

importjava.io.FileInputStream;

importjava.io.InputStream;

importjava.lang.reflect.Method;

 

import org.junit.Test;

 

 

public class Test3 {

 

       // 反射类的 方法:public void abc()

       @Test

       publicvoid test1() throws Exception {

              Useruser = new User();

              // 加载User

              Classclass1 = Class.forName("classTest.User");

              // 解剖User类的方法

              Methodmethod = class1.getMethod("abc", null); // 1、那个方法 2、可变参数

              method.invoke(user,null);// 1、对象 2、可变参数

       }

 

       // 反射类的 方法:public void abc(Stringname,int password)

       @Test

       publicvoid test2() throws Exception {

              Useruser = new User();

              // 加载User

              Classclass2 = Class.forName("classTest.User");

              // 解剖User类的方法

              Methodmethod = class2.getMethod("abc", String.class, int.class); // 1、那个方法 2、可变参数

              //通过invoke()调用方法或传参数

              method.invoke(user,"fmh", 18);// 1、对象 2、可变参数

       }

 

       // 反射类的 方法:public Class[]abc(String name,int[] password)

       @Test

       publicvoid test3() throws Exception {

              Useruser = new User();

              // 加载User

              Classclass3 = Class.forName("classTest.User");

              // 解剖User类的方法

              Methodmethod = class3.getMethod("abc", String.class, int[].class); // 1、那个方法 // 2、可变参数

              //通过invoke()调用方法或传参数

              Classclass2[] = (Class[]) method.invoke(user, "fmh", new int[] { 1, 2,3});// 1、对象 2、可变参数

              System.out.println(class2[0]);

 

       }

 

       // 反射类的 方法:private voidabc(InputStream in)

       @Test

       publicvoid test4() throws Exception {

              Useruser = new User();

              // 加载User

              Classclass4 = Class.forName("classTest.User");

              // 解剖User类的方法

              Methodmethod = class4.getDeclaredMethod("abc", InputStream.class); // 1、那个方法 2、可变参数

              method.setAccessible(true);// 暴力放射

              //通过invoke()调用方法或传参数

              method.invoke(user,new FileInputStream("d:\\fruit.jpg"));// 1、对象 2、可变参数

 

       }

 

       // 反射类的 方法:public static voidabc(int num)

       @Test

       publicvoid test5() throws Exception {

              //User user = new User();

              // 加载User

              Classclass5 = Class.forName("classTest.User");

              // 解剖User类的方法

              Methodmethod = class5.getMethod("abc", int.class); // 1、那个方法 2、可变参数

              // 静态方法 可以不用传对象

              //通过invoke()调用方法或传参数

              method.invoke(null,23);// 1、对象 2、可变参数

       }

      

       // 反射类的 方法:public static voidmain(String[] args)

              @Test

              publicvoid test6() throws Exception {

                     //User user = new User();

                     // 加载User

                     Classclass6 = Class.forName("classTest.User");

                     // 解剖User类的方法

                     Methodmethod = class6.getMethod("main", String[].class); // 1、那个方法 2、可变参数

                     // 静态方法 可以不用传对象

                     //通过invoke()调用方法或传参数

                     method.invoke(null,(Object)newString[]{"aaa","bbb"});// 1、对象 2、可变参数  

                     //反射数组时一定要注意  :::: 数组都拆成这样//main(String s1,Strings2)

                     //解决方案一:new Object[]{newString[]{"aa","bb"}}

                     //解决方案二:(Object)newString[]{"aaa","bbb"}

                     //jdk1.5  method.invoke(Stringmenthodname,object...args)

                     //jdk1.4  method.invoke(Stringmenthodname,object...obj[])

              }

 

}

 

以上是反射方法,以及对方法的一些操作

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值