您的位置:首页 > 职场人生

黑马程序员__java基础__反射

2015-06-09 13:07 435 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
反射
一.反射的概述
        反射就是把Java类中的各种成分映射成相应的java类。
        例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示。就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。

二.反射的基础——Class类

(1)所有的类文件都有共同属性,所以可以向上抽取,把这些共性内容封装成一个类,这个类就叫Class(描述字节码文件的对象)。 Class类中就包含属性有field(字段)、method(方法)、construction(构造函数)。

        field中有修饰符、类型、变量名等复杂的描述内容,因此也可以将字段封装称为一个对象。用来获取类中field的内容,这个对象的描述叫Field。同理方法和构造函数也被封装成对象Method、Constructor。要想对一个类进行内容的获取,必须要先获取该字节码文件的对象。该对象是Class类型。

        Class类描述的信息:类的名字,类的访问属性,类所属于的包名,字段名称的列表,方法名称的列表等。每一个字节码就是class的实例对象。

(2)获取Class对象的三种方法

第一种方法:

       通过实例对象的getClass方法进行获取。

       例如:Class cla=new Person().getClass();

第二种方法:

       任何数据类型都具备着一个静态的属性class,这个属性直接获取到该类型的对应字节码对象。

       例如 :Class cla=Person.class;

第三种方法:

       通过Class类的forName方法,就可以获得字节码对象,这种方法比较常见。

       例如:Class cla=Class.forName("day25.Person")其中"day25.Person"为  包名.类名

(3)Class类中的方法

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

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

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

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

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

        Method getMethod(String name,Class… parameterTypes)

        返回一个Method对象,它表示的是此Class对象所代表的类的指定公共成员方法。

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

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

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

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

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

        T newInstance():创建此Class对象所表示的类的一个新实例。

三.构造方法(Constructor)的反射应用

(1)构造函数概述:

         构造函数是给对象进行初始化的,通过构造函数可以创建对象。

(2)获取构造函数的方法有两种;

         获取某一个构造方法:

         Constructor con=Class.forName(“day25.Person”).getConstructor(String.class,int.class);

         获取这个类的所有构造方法:如得到上面示例中Person类的所有构造方法

         Constructor[] cons = Class.forName(“day25.Person”).getConstructors();

(3)创建实例对象:

         通常方式:
b72d
Person p = new Person(“lisi”,30);

         反射方式:Person p= (Person)con.newInstance(“lisi”,30);

注:

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

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

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

例子:

package day25;
import java.lang.reflect.*;
class Person
{
private String name;
public int age;
Person()
{
System.out.println("haha");
}
public Person(String name,int age )
{
this.name=name;
this.age=age;
}
public String toString()
{
return name+"  "+age;
}
}
public class ReflecDemo {

public static void main(String[] args) throws Exception
{
Constructor();
}
public static void Constructor()throws Exception
{
Class cla=Class.forName("day25.Person");//获取字节码对象
Constructor con=cla.getConstructor(String.class,int.class);//通过字节码对象获取带参数的构造函数
Person p=(Person)con.newInstance("lisi",23);//通过构造函数创建对象并初始化
System.out.println(p.toString());
}

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

(1)类中的成员变量包括公共的、私有的,都属于Field类。

(2)获取成员变量的方法:

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

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

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

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

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

例子:

package day25;
import java.lang.reflect.*;
class Person
{
private String name;
public int age;
Person()
{
System.out.println("haha");
}
public Person(String name,int age )
{
this.name=name;
this.age=age;
}
public String toString()
{
return name+"  "+age;
}
}
public class ReflecDemo {

public static void main(String[] args) throws Exception
{
Field();
}
public static void Field() throws Exception
{
Class cla=Class.forName("day25.Person");
Person p=(Person)cla.newInstance();//调用空参构造函数并创建对象
Field fname=cla.getDeclaredField("name");//获取私有成员变量
Field fage=cla.getField("age");//获取公有成员变量
fage.set(p, 30);//给指定对象赋值
fname.setAccessible(true);//暴力访问私有成员变量
fname.set(p, "zhangsan");//给指定对象赋值
System.out.println(fage.get(p));//返回指定成员变量的值
System.out.println(fname.get(p));
//System.out.println(p.toString());
}

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

(1)Method类代表某个类中的一个成员方法。调用某个对象身上的方法,要先得到方法,再针对某个对象调用。

(2)获取方法:

          Method[] getMethods();//只获取公共和父类中的方法。

         Method[] getDeclaredMethods();//获取本类中包含私有。

         Method   getMethod("方法名",参数.class(如果是空参可以写null));

         Object invoke(Object obj ,参数);//调用方法

         如果方法是静态,invoke方法中的对象参数可以为null。例如:invoke(null,参数)

例子:

package day25;
import java.lang.reflect.*;
class Person
{
private String name;
public int age;
Person()
{
System.out.println("haha");
}
public Person(String name,int age )
{
this.name=name;
this.age=age;
}
public String toString()
{
return name+"  "+age;
}
public static int setAge(int age)
{
return age;

}
}
public class ReflecDemo {

public static void main(String[] args) throws Exception
{
Method();
}
public static void Method() throws Exception
{
Class cla=Class.forName("day25.Person");
Constructor con=cla.getConstructor(String.class,int.class);
//获取非私有方法
Person p =(Person)con.newInstance("wangwu",27);
Method me=cla.getMethod("toString",null);//获取非私有、无参toString的方法
Object returnVaule=me.invoke(p, null);//调用对象(p)的toString方法
System.out.println(returnVaule);//打印函数返回值
//获取私有方法
Method me1=cla.getMethod("setAge",int.class);//获取私有、有参数setAge的方法
Object returnVaule1=me1.invoke(null, 20);//调用私有、有参数setAge的方法
System.out.println(returnVaule1);//打印函数返回值
}
}

(3)练习:

package day25;
/**
*  写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法。
*/
import java.lang.reflect.*;
public class ReflecText
{
public static void main(String[] args) throws Exception
{
String claName=args[0];
Class cla=Class.forName(claName);//获取字节码对象
Method methodMain=cla.getMethod("main",String[].class);//获取main方法
//强制转换为超类Object,不用拆包
methodMain.invoke(null, (Object)new String[]{"haha","567","heiehi"});
}
}
class Text
{
public static void main(String[] args)
{
for(String arg : args)
{
System.out.println(arg);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: