黑马程序员-----反射

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

反射

一、概述

反射技术:

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

    动态获取类中信息,就是java反射。可以理解为对类的解剖。    如果想要对指定名称的字节码文件进行加载并获取其中的内容并调用,这时就使用到了反射技术。

二、反射的基础Clsss类

      用于描述字节码的类就是Class类,创建对象,可以提取字节码文件中的内容,如字段、构造函数、一般函数。该类就可以获取字节码文件中的所有内容,那么反射就是依靠该类完成的。想要对一个类文件进行解剖,只要获取到该类的字节码文件对象即可。

获取Class对象的三种方式

方式一:

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

        如:Class clazz=new Person().getClass();//Person是一个类名

        弊端:每次都需要具体的类和该类的对象,以及调用getClass方法。

方式二:

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

        如:Class clazz=Person.class;//Person是一个类名

        比第一种较为简单,不用创建对象,不用调用getClass方法,但是还是要使用具体的类,和该类中的一个静态属性class完成。

方式三:

        这种方式较为简单,只要知道类的名称即可。不需要使用该类,也不需要去调用具体的属性和行为。就可以获取到Class对象了。

        如:Class clazz=Class.forName("包名.Person");//Person是一个类名

        这种方式仅知道类名就可以获取到该类字节码对象的方式,更有利于扩展。

package cn.itcast.bean;
public class Person//Person类
{
        private int age;
        private String name;
    public Person(int age,String name){
                super();
                this.age = age;
                this.name = name;

                System.out.println("Person param run..." + this.name + ":" + this.age);
        }

        public Person(){
                super();

                System.out.println("person run");
        }

        public void show(){
                System.out.println(name + "...show run..." + age);
        }

        private void privateMethod(){
                System.out.println("method run");
        }

        public void paramMethod(String str,int num){
                System.out.println("paramMethod run..." + str + ":" + num);
        }

        public static void staticMethod(){
                System.out.println("static method run...");
        }
}

练习:获取字节码对象的三种方式:

import cn.itcast.bean.Person;

//要想要对字节码文件进行解剖,必须要有字节码文件对象。
public class ReflectDemo
{
        public static void main(String[] args) throws ClassNotFoundException {
                getClassObject_1();
                System.out.println("--------------------");
                getClassObject_2();
                System.out.println("--------------------");
                getClassObject_3();
        }

        // 方式一:Object类中的getClass()方法的。        
        public static void getClassObject_1(){
                
                Person p = new Person();
                Class clazz = p.getClass();

                Person p1 = new Person();
                Class clazz1 = p1.getClass();

                System.out.println(clazz == clazz1);
        }

        /*
        * 方式二:任何数据类型都具备一个静态的属性.class来获取其对应的Class对象。
       
        public static void getClassObject_2(){
                
                Class clazz = Person.class;
                Class clazz1 = Person.class;

                System.out.println(clazz == clazz1);
        }
        //方式三
        public static void getClassObject_3() throws ClassNotFoundException {
                
                //可以把类的字符串名称写到配置文件中,然后读取出来。
                String className = "cn.itcast.bean.Person";
                Class clazz = Class.forName(className);

                System.out.println(clazz);
        }
}

二、Constructor类

获取构造方法:

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

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

        2)获取某一个构造方法:

              Constructor con=Person.class.getConstructor(String.class,int.class);

import cn.itcast.bean.Person;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ReflectDemo
{
        public static void main(String[] args) throws Exception {
                createNewObject_1();
                System.out.println("--------------------");
                createNewObject_2();
        }

        public static void createNewObject_1() throws ClassNotFoundException,InstantiationException,IllegalAccessException {
                String name = "cn.itcast.bean.Person";
                //找寻该文件类文件,并加载进内存,并产生Class对象。
                Class clazz = Class.forName(name);
                //如何产生该类的对象呢?
                Object obj = clazz.newInstance();//调用Person的空参构造函数
        }

        public static void createNewObject_2() throws ClassNotFoundException,InstantiationException,NoSuchMethodException,IllegalAccessException,InvocationTargetException {

                //Person p = new Person("小强",39);

                String name = "cn.itcast.bean.Person";
                //找寻该名称类文件,并加载进内存,并产生Class对象。
                Class clazz = Class.forName(name);
                //获取到了指定的构造函数对象
                Constructor constructor = clazz.getConstructor(int.class,String.class);
                //通过该构造器对象的newInstance方法进行对象的初始化。
                Object obj = constructor.newInstance(38,"小明");
        }
}

三、Field类

1、Field类代表某个类中一个成员变量

2、方法

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

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

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

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

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

示例:

import cn.itcast.bean.Person;
import java.lang.reflect.Field;

public class ReflectDemo
{
        public static void main(String[] args) throws Exception {
                getFieldDemo();
        }
        
        /*
        * 获取字节码文件中的字段。
        */
        public static void getFieldDemo() throws Exception {

                Class clazz = Class.forName("cn.itcast.bean.Person");
                
                //getField只能获取所有可访问公共字段,private获取不到。
                //Field field = claszz.getField("age");

                //getDeclaredField可以获取到公共字段,也可以获取到私有字段。
                Field field = clazz.getDeclaredField("age");

                //对私有字段的访问取消权限检查,暴力访问。
                field.setAccessible(true);

                Object obj = clazz.newInstance();
                
                //为对象的属性赋值
                field.set(obj,89);
                
                //获取某对象的某属性值
                Object o = field.get(obj);

                System.out.println(field);
        }
}

四、Method类

方法

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

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

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

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

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

import cn.itcast.bean.Person;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;

public class ReflectDemo
{
        public static void main(String[] args) throws Exception {
                getMethodDemo_1();
                System.out.println("---------------------------");
                getMethodDemo_2();
                System.out.println("---------------------------");
                getMethodDemo_3();
        }
        
        /*
        * 获取指定Class中的公共函数。
        */
        public static void getMethodDemo_1() throws Exception {

                Class clazz = Class.forName("cn.itcast.bean.Person");
                
                Method[] methods = clazz.getMethods();//获取的都是公有的方法

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

                for(Method method : methods){
                        System.out.println(method);
                }
        }

        public static void getMethodDemo_2() throws Exception {

                Class clazz = Class.forName("cn.itcast.bean.Person");
                
                Method method = clazz.getMethod("show",null);//获取空参数一般方法

                Object obj = clazz.newInstance();

                Constructor constructor = clazz.getConstructor(int.class,String.class);
                obj = constructor.newInstance(37,"张三");

                method.invoke(obj,null);
        }

        public static void getMethodDemo_3() throws Exception {

                Class clazz = Class.forName("cn.itcast.bean.Person");
                
                Method method = clazz.getMethod("paramMethod",String.class,int.class);//获取空参数一般方法

                Object obj = clazz.newInstance();

                Constructor constructor = clazz.getConstructor();
                obj = constructor.newInstance();

                method.invoke(obj,"李四",89);
        }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值