码迷,mamicode.com
首页 > 编程语言 > 详细

黑马程序员----Java高新技术之反射学习总结

时间:2015-06-17 02:06:37      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:反射

------- android培训java培训、期待与您交流! ----------

反射的概念

         1、Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

    精妙的总结就是:反射就是将Java类中的各个成分映射成相应的Java类。

    3、在Java中,描述事物的各种类同样也是一种事物,也可以用面向对象的方法来描述,即也有一个类来描述众多的Java类。

    4、反射也称为对类的解剖。例如一个类有成员变量、构造方法、成员方法,包等信息,通过反射,就可以拿到这个类的各种信息。

    5、使用java的反射机制,一般需要遵循三步:
             获得你想操作类的Class对象
             通过第一步获得的Class对象去取得操作类的方法或是属性名
             操作第二步取得的方法或是属性复制代码

Class类--反射的基础

    Java中所有的类文件都有一些相同的特征,向上抽取,把共性内容封装形成了新的类Class,它是描述字节码文件的对象。

    Class类描述的信息:类的名字,类的访问属性,类所属于的包名,字段名称列表,方法名称列表等

每一个字节码都是Class类的实例对象。

获取Class对象方法
    1、通过所有数据类型都有的静态属性.class来获取

        类名.class  例如:String.class

    2、通过对象的getClass()方法获取

        对象.getClass()  例如:new String("123").getClass();

    3、通过Class类的静态方法forName()和要获得Class对象的类名来获取

        Class.forName(包名.类名);  例如:Class.forName("java.lang.String");

 方法实例:

public class ClassTest{
  public static void main(String[]args)throws Exception{
    String str = "123456";
    Class cls1 =String.class;
    Class cls2 = str.getClass();
    Class cls3 = Class.forName("java.lang.String");
    System.out.println(cls1 == cls2);//true
    System.out.println(cls2 == cls3);//true
  }
}

上面实例也说明:同一个类只存在一份字节码文件。就是同一个Class实例对象。

java中预定义的九个实例对象:

    基本数据类型(byte、boolean、short、int、long、double、float、char)字节码对象和一种返回值为void类型的void.class

    Integer.TYPE是Integer类的一个常量,代表的是此包装类型包装的基本类型的字节码,也就是int类型的字节码,所以它和int.Class是相等的。

    另外,具有相同的数据类型和维数的数组在java中映射成同一个Class对象。判断是否是数组类型,用Class.isArray()。

Class类中常用方法

    1)   forName(String className) 返回与给定字符串名的类或接口的相关联的Class对象。

    2)  getClass()  返回的是Object运行时的类,即返回Class对象即字节码对象

    3)  getConstructor()    返回Constructor对象,它反映此Class对象所表示的类的指定公共构造方法。

    4)  getField(String name)     返回一Field对象,此Class对象所代表的类或接口的指定公共成员字段。

    5) getFields()    返回包含某些Field对象的数组,表示所代表类中的成员字段。

    6)  getMethod(String name,Class… parameterTypes)    返回一个Method对象,它表示的是此Class对象所代表的类的指定公共成员方法。

    7)   getMehtods()    返回一个包含某些Method对象的数组,是所代表的的类中的公共成员方法。

     8)  String getName()    以String形式返回此Class对象所表示的实体名称。

    9)  String getSuperclass()    返回此Class所表示的类的超类的名称

    10) boolean isArray()    判定此Class对象是否表示一个数组

    11) boolean isPrimitive()    判断指定的Class对象是否是一个基本类型。

    12) newInstance()    创建此Class对象所表示的类的一个新实例。注意:此方法会使用该的空参数构造函数进行初始化实例对象。

 
Constructor类.........(构造方法的反射)

1、Constructor的实例对象代表类的一个构造方法。

 2、获取构造方法:

    获取一个类中所有的构造方法  

        Constructor[] con=Class.forName("java.lang.String").getConstructors ();

    获取一个类中的某一个构造方法

        Constructor con=String.class.getConstructor(StringBuffer.class);

 

3、创建实例对象 和反射创建之间比较    

    一般方式:String s = “123”;

    利用反射:String s =(String) constructor.newInstance("123");//可以指定使用哪个构造函数创建。

 

注意事项:

       1、创建实例时newInstance方法中的参数列表必须与获取Constructor的方法getConstructor方法中的参数列表一致。

        2、newInstance():构造出一个实例对象,每调用一次就构造一个对象。

        3、利用Constructor类来创建类实例的好处是可以指定构造函数,而Class类只能利用无参构造函数创建类实例对象。

代码实例

package   day24;

import java.lang.reflect.Constructor;

public class ConsDemo

{

    public static void main(String [] args) throws Exception

    {

        Class cl =Class.forName("java.lang.String");//获取Sring类的Class对象。

        Constructor con =cl.getConstructor(StringBuffer.class);//获取String类的Class对象的构造方法

        String st= (String) constructor.newInstance(new StringBuffer("Constructor创建实例对象的练习")

    }

}

Field 类.........(成员变量的反射)

1、代表的是反射中某个类中的成员变量

2、常用方法:

    1)  Field getField(String s);//只能获取公有和父类中公有

    2)  Field getDeclaredField(String s);//获取该类中任意成员变量,包括私有

    3)  setAccessible(ture);//如果是私有字段,要先将该私有字段进行取消权限检查的能力。也称暴力访问。

    4)  set(Object obj, Object value);//将指定对象变量上此Field对象表示的字段设置为指定的新值。

    5)  Object get(Object obj);//返回指定对象上Field表示的字段的值。


Method类........(成员方法的反射)

1、代表某个类中的一个成员方法。

2、常用的方法

      1) Method [ ] getMethods();  只获取公共和父类中的所有方法

      2) Method [ ] getDeclaredMethods(); 获取本类中方法包含私有方法

      3) Method [ ] getMethod("方法名" ,参数.class(空参可以写null));

      4)Object invoke ( Object obj,参数);     调用方法:如果方法是静态的,invoke中的参数可写null

3、调用方法

    得到类中的一个方法:Sting str="123";

        Method mcharAt = Class.forName("java.lang.String").getMethod("charAt", int.class);

    调用方法:

    一般方式:str.mcharAt(2);

    反射方式:mcharAt.invoke(str,2)

如果传递给Method对象的invoke()方法的第一个参数为null,说明Method对象对应的是一个静态方法.

4、JDK1.4和JDK1.5的invoke方法的区别:

    JDK1.4:public Object invoke(Object obj,Object[] args)

    JDK1.5:public Object invoke(Object obj,Object... args)

    按JDK1.4的语法,需要将一个数组作为参数传递给invoke方法时,这时它会把一个数组作为一个元素。这时如果我们要取出其中的元素,需要将数组中的元素通过数组一个个的取出。

    所以,调用mcharAt方法的代码也可以用JDK 1.4改写为 charAt.invoke("str", new Object[]{1})形式。

代码实例:

import java.lang.reflect.*;

import java.util.*;

class Invok

{

    public static void main(String[] args) throw Exception

    {

        String s ="123";

        Method mCharAt=String.class.getMethod("charAt",int.class);

        System.out.println(mCharAt.invoke(s,1);             //1.5的写法

        System.out.println(mCharAt.invoke(s,new Object[]{1}));    //1.4的写法

    }

}

对接收数组参数的成员方法进行反射。

    需求:用反射方法运行某一个类的main函数

代码实例:

package com.ithema.day1

import java.lang.reflect.*;

import util.*;

public class MainMethod

{

    public static void main(String[] args)throw Exception{

        Class cl=Class.forName("com.itheima.day1.Test");  //这里完全可以用一个变量来表示类名,如

        Method me=cl.getMethod("main",String[].class);      此就能体现出反射的作用,当不清楚类名只有

        me.invoke(null,new String[]{"aa","bb","cc"})             变量用反射依旧运行可以类的main函数

    }

}

class Test

    public static void main(String[] args)

    {

        for(String s:args)

        {System.out.println(s);}

    }

}

这段代码会发生异常:非法参数异常

启用java程序中的main方法的参数是一个字符串数组。通过反射来调用main方法,invoke怎么传递参数:JDK1.5中一个数组是一个参数,1.4是一个数组中的每个元素是一个参数,1.5兼容1.4,所以传递时候会按照1.4的方法传递。所以红标记部分是错误的

解决办法:

    1.me.invoke(null,new object[](new String[]{"11","22","33"}));

    2.me.invoke(null,(Object)new String[]{"11","22","33"});  编译器会做特殊处理,不把参数当数组看待

 

数组的反射

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

2、数组的字节码文件名字是 [数组类型的第一个字母大写,如:int[] 为 [I;

3、数组对应Class的实例对象的getSuperclass()返回的是父类Object类的Class对象。

4、基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。

5、Arrays.asList()方法处理int[]和String[]时的差异:1.4和1.5新特性差别。1.4无法处理int数组,返回给1,5处理,1.5将int数组作为一个参数处理

6、数组的反射:Array工具类用于完成数组反射的操作。

    Array.getLength(Object obj);//获取数组长度

    Array.get(Object obj,int x);// 获取数组中的元素

7、如何得到某个数组中的某个元素的类型,

    例: int a = new int[3];Object[] obj=new Object[]{”ABC”,1};

    无法得到某个数组的具体类型,只能得到其中某个元素的类型,

    如: Obj[0].getClass().getName()得到的是java.lang.String

反射的作用

    框架与框架要解决的核心问题
    我做房子卖给用户住,由用户自己安装门窗和空调,我做的房子就是框架,用户需要使用我的框架,把门窗插入进我提供的框架中。框架与工具类有区别,工具类被用户的类调用,而框架则是调用用户提供的类。
    框架要解决的核心问题
    我在写框架时,你这个用户可能还在上小学,还不会写程序呢?我写的框架程序怎么样调用你以后写的类(门窗)呢?
    因为在写程序时无法知道要被调用的类名,所以吗,在程序中无法直接new某个类的实例对象了,而要使用反射的方式来做。

 

本文出自 “点点滴滴” 博客,请务必保留此出处http://arctictern.blog.51cto.com/10120640/1662452

黑马程序员----Java高新技术之反射学习总结

标签:反射

原文地址:http://arctictern.blog.51cto.com/10120640/1662452

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!