黑马程序员——反射机制

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

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

Java反射机制主要提供下面几种用途:

  •  1.在运行时判断任意一个对象所属的类。
  •  2.在运行时构造任意一个类的对象。
  •  3.在运行时判断任意一个类所具有的成员变量和方法。
  •  4.在运行时调用任意一个对象的方法。
 5.生成动态代理。

反射优点和缺点

 优点:就是可以实现动态创建对象和编译,体现出很大的灵活性。
 缺点:是对性能有影响。

Class类代表一个类。
.class文件加载到内存中就是一个class对象。
获取class对象的方式有3种

1.class.forName(类名)
2.类名.class
3.对象.getClass

示例代码

package ReflectDemo;
import ObjectDemo.extend;
import ObjectDemo.polyDemo;
public class ReflectDemo
{
    public static void main(String[] args) throws ClassNotFoundException
    {
        Class c = Class.forName("ObjectDemo.extend"); //方式一:通过class.foName("class名")获取class的字节码对象。
        Class c1 = extend.class; //方式二:通过类名.class获取class的字节码对象。
        Class c2 = new extend().getClass(); //方式三:通过对象.getClass获取class的字节码对象。
        System.out.println(c.getName()==c1.getName()); //都是true,因为clas的字节码文件只有一份,不同方式获取的都是那一份。
        System.out.println(c.getName()==c2.getName());
    }
}
Constructor: 获取指定的构造函数对象的构造器
getConstructor(参数的类型class),可以得到该类的构造函数。
获得构造函数的函数:
1.newInstance()无参数就创建无参数的该类对象,有参数就要传入参数(newInstance(参数))来创建该类对象。
2.Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数。
3.Constructor[] getConstructors() -- 获得类的所有公共构造函数。
4.Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数(与接入级别无关)。
5.Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数(与接入级别无关)。

示例代码:

package ReflectDemo;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ReflectDemo2
{
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
    {
        Class c = Class.forName("ReflectDemo.Person");
        Constructor con= c.getConstructor(String.class,int.class); //获取指定带参数的构造对象。
        Object obj = con.newInstance("李四",10); //用newInstance创建对应构造函数的对象。
        Constructor con1 = c.getConstructor(); //获取无参数的构造对象。
        Object obj1 = con1.newInstance(); //用newInstance创建对应构造函数的对象。
    }
}
Field 类代表类的成员变量(成员变量也称为类的属性),提供有关类或接口的单个字段的信息,以及对它的动态访问权限。

1.Class.getField(String)方法可以获取类中的指定字段(可见的), 如果是私有的可以用getDeclaedField("name")方法获取。

2.set(obj, "李四")方法可以设置指定对象上该字段的值, 如果是私有的需要先调用setAccessible(true)设置访问权限(暴力反射)。

3.get(obj)可以获取指定对象中该字段的值。

获得成员变量信息的函数:
1.Field getField(String name) -- 获得命名的公共字段。
2.Field[] getFields() -- 获得类的所有公共字段。
3.Field getDeclaredField(String name) -- 获得类声明的命名的字段。
4.Field[] getDeclaredFields() -- 获得类声明的所有字段。
示例代码:
package ReflectDemo;
import java.io.ObjectInputStream.GetField;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class ReflectDemo3
{
    public static void main(String[] args) throws NoSuchFieldException, SecurityException, ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
    {
        Class c = Class.forName("ReflectDemo.Person");
         Field f = c.getField("name"); //获取本来对象中的公共的字段。
         Field f1 = c.getDeclaredField("age"); //获取本来对象中的声明了的字段。
         Field[] f2 = c.getFields(); //获取本类的对象中的所有公共字段。
         Field[] f3 = c.getDeclaredFields(); //获取本类对象中的所有声明的字段。
         System.out.println(f);
         System.out.println(f1);
         for (Field field:f2) //循环遍历存放本类对象公共字段的数组。
        {
             System.out.println("--"+field);
        }
        for (Field field:f3) //循环遍历存放本类对象声明字段的变量数组。
        {
             System.out.println("----"+field);
        }
         Constructor con = c.getConstructor(String.class,int.class);
         Object obj = con.newInstance("李四",10);  //创建一个该类实例对象。
         f.set(obj, "王五"); //修改该类实例对象的name字段的值。
         f1.setAccessible(true); //修改私有属性时,必须用setAccessible(true)设置访问权限。
         f1.set(obj, 20);  //当访问权限设计好后才可以修改私有属性。
         System.out.println(f.get(obj)); //打印修改后的对象的某属性,看有没有修改成功。
         System.out.println(f1.get(obj));
    }
}
Method类代表类的方法,用于获得类的方法信息。
1.Class.getMethod(String, Class...) 和 Class.getDeclaredMethod(String, Class...)方法可以获取类中的指定方法。
2.invoke(Object, Object...)可以调用实例对象的方法,有参数的方法需要传递参数。

获得方法信息的函数:
Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方法。
Method[] getMethods() -- 获得类的所有公共方法。
Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型,获得类声明的命名的方法。
Method[] getDeclaredMethods() -- 获得类声明的所有方法。
示例代码:
package ReflectDemo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectDemo4
{
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException
    {
        Class c = Class.forName("ReflectDemo.Person"); //获取类的字节码对象。
        Method mt = c.getMethod("toString", null); //获取本类的公共命名的方法,有参数的带参数,无参数的为null。
        Method[] mt1 = c.getMethods(); //获取本类的所有公共方法。
        Method mt2 = c.getDeclaredMethod("setSex", String.class); //获取本类中声明的方法。
        Method[] mt3 = c.getDeclaredMethods(); //获取本类中所有声明的方法。
        System.out.println("获取指定的公共方法:"+mt);
        System.out.println("获取指定的本类方法:"+mt2);
        for (Method method:mt1)
        {
            System.out.println("获取本类的所有公共方法:"+method);    
        }
        for (Method method:mt3)
        {
            System.out.println("获取本类中声明的所有方法:"+method);    
        }
        Constructor con = c.getConstructor(String.class,int.class); //获取带参数的构造函数。
        Object obj = con.newInstance("张三",19); //通过刚获取的构造函数创建一个本类实例对象。
        mt2.invoke(obj, "男"); //调用实例对象的setSex方法,并传入参数。
        Field f = c.getField("sex"); //获取本类的属性字段。
        System.out.println(f.get(obj)); //获取到对象的sex属性字段,看是否改成了"男"。
    }
}
Array类提供了动态创建数组,以及访问数组的元素的静态方法
1.class.forName()可以用来获得创建数组的元素类型。
2.newInstance(元素类型,数组长度)创建一个固定长度的数组。
3.getClass().getComponentType()获取数组的元素类型。

获得数组信息的函数:
1.get(Object array, int index)获取指定索引的值。
2.set(Object array, int index)修改指定索引的值。
3.getLength(Object array)返回数组的长度。
4.set基本数据类型(Object array, int index, 基本数据类型 类型变量)修改指定位置指定的数据类型的值。
5.get基本数据类型(Object array, int index)获取指定索引的指定基本数据类型的值。
示例代码:
import java.awt.List;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
public class ReflectDemo5
{
    public static void main(String[] args )
    {
        Object array = Array.newInstance(int.class,10); //Array.newInstance(元素类型,数组长度)静态创建数组。
        Array.setInt(array,1,5); //修改指定索引的值。
        int i = (int) Array.get(array, 1); //取得指定索引的值
        int length = Array.getLength(array); //获取数组的长度。
        Class<?> c = array.getClass().getComponentType(); //获取数组的类型。
        System.out.println(c);
        System.out.println(i);
        System.out.println(length);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值