反射---

什么是反射?
 *  反射就是获取一个类的字节码文件,然后加载该类的所有的成员
 *  成员变量所在类---->Field
 *  成员方法所在类---->Method
 *  构造方法所在类--->Constructor
 *  给成员变量赋值通过Field,调用成员方法Method,通过构造器创建的对象...
 *
 *  获取一个类的字节码文件 (三种)
 *
 *
 *  Class类:
 *          public static Class<?> forName(String className):参数为当前类的全限定名称
 *                         throws ClassNotFoundException

public class RelectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {

        //获取一个类的字节码文件对象
        //1)Object类的getClass()
        Person p = new Person() ;
        Class c1 = p.getClass();
        System.out.println(c1);//class 包名.类名
        //Integer-->java.lang.Integer

        //Class
        //public String getName()
        System.out.println(c1.getName());//获取当前Person类的全限定名称 com.qf.reflect_01.Person
        System.out.println("-------------------------");

        //2)任意Java类型的class属性
        Class c2 = Person.class ;
        System.out.println(c2);
        System.out.println(c2.getName());
        System.out.println(c1==c2);


        System.out.println("-------------------------");

        //3)Class的静态功能
        Class c3 = Class.forName("com.qf.reflect_01.Person") ;
        System.out.println(c3);//class com.qf.reflect_01.Person


    }
}

通过反射获取指定的构造方法(非公共),并创建该类实例
 *
 * 私有的构造方法不能直接new的

public class Reflect_getCon2 {

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

        //获取Person类的字节码文件对象
        Class clazz = Class.forName("com.qf.reflect_01.Person");


        //获取指定的构造方法:Constructor
        //private Person(String name,int age)
        //获取指定的构造方法(包括私有),参数为当前参数类型的字节码文件对象
       // public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

        Constructor con = clazz.getDeclaredConstructor(String.class,int.class) ;

        //Constructor:构造器 Method:成员方法,Field:成员变量
        //公共的基类:AccessibleObject
        //public void setAccessible(boolean flag):取消Java语言访问检查 (参数为true)

        con.setAccessible(true);

        //创建当前类的实例
        //        Object obj =  con.newInstance("高圆圆",41) ;
        //        System.out.println(obj);//Person的toString方法
        //        //Person{name='高圆圆', age=41, address='null'}
        System.out.println("----------------------------");

//      Person p = new Person("高圆圆",41) ;//已经私有化

    }
}
访问Person类的默认修饰符的构造方法,并且创建当前类实例
 *
 * 类似于  Person p = new Person("高圆圆",41,""西安) ;
 */
public class Refelect_getCon3 {

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


        //获取当期类的字节码文件对象
        Class clazz = Class.forName("com.qf.reflect_01.Person") ;
        //获取构造器Constructor
        Constructor con =  clazz.getDeclaredConstructor(String.class,int.class,String.class) ;

       //构造方法:默认修饰符
        //取消Java语言访问检查
        con.setAccessible(true);

        //创建该类实例
        Object obj = con.newInstance("高圆圆",41,"鄠邑区") ;
        System.out.println(obj);

    }
}

/通过反射获取一个类的构造器并且创建当前类对象呢
 *
 *
 * 之前的写法:
 *      Person perons = new Person() ;

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

        //1)获取指定的类的字节码文件对象: com.qf.reflect_01.Person的字节码文件对象
        Class clazz = Class.forName("com.qf.reflect_01.Person") ;

        //2)通过字节码文件对象获取构造器(Constructor)
        //public Constructor<?>[] getConstructors() throws SecurityException
        //获取类的所有公共的构造方法
       // Constructor[] constructors = clazz.getConstructors();
        //public Constructor<?>[] getDeclaredConstructors():可获取当前类中的所有构造方法(包括私有以及默认)
        /*Constructor[] constructors = clazz.getDeclaredConstructors();
        for(Constructor con:constructors){
            System.out.println(con);
            *//**
             * public com.qf.reflect_01.Person() :
             *
             *
             * com.qf.reflect_01.Person(java.lang.String,int,java.lang.String)
             * private com.qf.reflect_01.Person(java.lang.String,int)
             * public com.qf.reflect_01.Person()
             *//*
        }*/


        //通过字节码文件对象获取单个构造方法:公共的
        //参数为:可变参数 ...(类似于数组:参数可以有很多个)
        //如果存在参数:必须参数类型的Class     String   ---->java.lang.String
                //Person(String name,Integer i)---->参数:java.lang.String, java.lang.Integer
        //无参的构造方法:不需要传参
        //public Constructor<T> getConstructor(Class<?>... parameterTypes)
        Constructor con = clazz.getConstructor() ;


        //获取了构造器之后:通过构造器创建当前类的实例
        // public T newInstance(Object... initargs):参数是给构造方法中赋值的实际参数

        Object obj = con.newInstance();
        System.out.println(obj);


        System.out.println("--------------------");

        //之前写法
        Person p = new Person() ;
        System.out.println(p);

       // Person p1 = new Person("高圆圆",20) ;

    }
}
public class ReflectDemo {

    public static void main(String[] args) throws  Exception{
        //1)获取指定的类的字节码文件对象
        Class clazz = Class.forName("com.qf.reflect_01.Person") ;


        //方式1:通过无参构造器创建实例
        //2)通过反射获取单个公共的构造方法,无参
       /* Constructor constructor = clazz.getConstructor();
        //System.out.println(constructor);
        //3)通过构造器创建当前类实例
        Object obj = constructor.newInstance();
        System.out.println(obj);*/


       //方式2:直接创建当前类实例
       //Class类的功能:直接通过当前类的字节码文件对象创建当前类对象
        //public T newInstance()
        Object obj = clazz.newInstance();
        System.out.println(obj);


        //public Field[] getFields():获取当前类或者指定接口中的所有的公共的字段
        //public Field[] getDeclaredFields():获取当前类中所有的字段(公共的,受保护的,私有的,默认的)
       // Field[] fields = clazz.getFields();
       /* Field[] fields  =clazz.getDeclaredFields() ;
        for(Field field:fields){
            System.out.println(field);
            //公共的字段(成员变量)
            //public java.lang.String com.qf.reflect_01.Person.name

            *//**
             * public java.lang.String com.qf.reflect_01.Person.name
             * private int com.qf.reflect_01.Person.age
             * java.lang.String com.qf.reflect_01.Person.address
             *//*
        }*/

        //获取指定的单个的字段(成员变量):公共字段
        //name:公共的字段
        //public Field getField(String name):参数名称为"成员变量名称"
        Field nameField = clazz.getField("name");
        //给当前Field所代表的的指定的字段name来进行赋值
//        public void set(Object obj,Object value)
        //将指定的值绑定在当前类的实例上
        nameField.set(obj,"高圆圆");

        //age:私有的属性
        //address:默认修饰符
        //在设置值之前,需要取消Java语言访问检查



        System.out.println(obj);

        System.out.println("---------------------");


        //获取age所在的Field对象,为其赋值
        //Field getDeclaredField(String name):获取指定的字段Field
        Field ageField = clazz.getDeclaredField("age");

        //取消Java语言访问检查
        //私有属性
        ageField.setAccessible(true);
        //赋值
        ageField.set(obj,41);
        System.out.println(obj);

        System.out.println("----------------------------");
        Field addressField = clazz.getDeclaredField("address");
        addressField.setAccessible(true);
        addressField.set(obj,"西安市");
        System.out.println(obj);


    }
}

通过反射方式来调用Person类中的成员方法(非静态的)

 通过反射方式来调用Person类中的成员方法(非静态的)
 */
public class ReflectDemo {

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

        //获取Person类的字节码文件对象
        Class clazz = Class.forName("com.qf.reflect_01.Person");

        //获取当前类的所有的公共的成员方法:有自己的,还有继承的
        //public Method[] getMethods()
        //public Method[] getDeclaredMethods():获取类或者接口中的指定的成员方法(公共,默认,私有,受保护)
       /* Method[] methods = clazz.getDeclaredMethods() ;

//        Method[] methods = clazz.getMethods();
        for(Method method :methods){
            System.out.println(method);
        }*/


       //之前的写法:
        //无参构造方法创建对象:
        //Person p = new Person() ;
        // p.show() ;
        Constructor con = clazz.getConstructor();
        //创建Person类的实例
        Object obj = con.newInstance();

        //通过反射获取成员方法所代表的的Method对象
        //获取公共的成员方法
        //参数1:方法名
        //参数2:当前该方法的形式参数类型的Class
        //public Method getMethod(String name ,Class<?>... parameterTypes)
        Method showMethod = clazz.getMethod("show");
        //要执行showMethod方法: show()

        //Method
        //参数1:当前类的实例
        //参数2:给方法形式参数传递的实际参数
        //返回值:就是调用当前方法本身的时候,如果方法是没有具体返回值,那么直接单独调用
        //如果有返回值类型,那么就使用Object来结束即可!

        //public Object invoke(Object obj, Object... args):
        Object returnObj = showMethod.invoke(obj);
        System.out.println(returnObj);


        System.out.println("----------------------");
        //获取function方法并调用
        //Method getDeclaredMethod(String name,Class...parameterNames)
        //获取指定的Method
        Method functionMethod = clazz.getDeclaredMethod("function", int.class);
        //取消Java语言访问检查
        functionMethod.setAccessible(true);

        Object retunrObj2 = functionMethod.invoke(obj, 27);
        System.out.println(retunrObj2);

        System.out.println("----------------------");
        Method methodM = clazz.getDeclaredMethod("method") ;
        methodM.setAccessible(true );
        Object returnObj3 = methodM.invoke(obj);
        System.out.println(returnObj3);



     /*   Person p = new Person() ;
        System.out.println(p.show());*/
        //通过反射调用function方法以及method 方法
    }
}
反射的应用1
 * 面试题
 *      现在有一个ArrayList<String>,如何实现给里面存储Integer类型呢?
 *
 *     可以,通过反射方式操作:-----获取Class---->Method--->invoke(当前类实例,方法实际参数)
 */
public class Test {

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

        //创建一个ArrayList<String>
        ArrayList<String> array = new ArrayList<String>() ;
        array.add("hello") ;
        array.add("world") ;
        array.add("javaee") ;
        System.out.println(array);
        System.out.println("--------------------");
       // array.add(100) ;

        //通过反射方式调用add方法
        //Object的getClass()获取字节码文件对象
        Class clazz = array.getClass() ;
        //clazz创建当前类实例
        Object obj = clazz.newInstance();//通过反射创建

        //获取Method对象:方法名 add
        Method addMethod = clazz.getMethod("add", Object.class);
        //调用方法
        addMethod.invoke(obj,"mysql") ;
        addMethod.invoke(obj,100) ;
        addMethod.invoke(obj,50) ;

        System.out.println(obj);



    }
}

反射的应用2:
 *      Class.forName("全限定名称"):参数为字符串:被经常用在配置文件中

public class Test2 {
    public static void main(String[] args) throws IOException, ClassNotFoundException,
            IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

        //创建一个学生类
        Student s = new Student() ;
        s.love();
        //代码不断变化
        //工人类
        Worker worker = new Worker() ;
        worker.love();

        //Java设计开发原则:
                //开闭原则: 对现有代码的修改关闭,在现有代码基础进行扩展!

        System.out.println("-----------------------------------");

        //提供了一个扩展:在src下(类路径下)配置文件class.properties
        //读取配置文件获取里面keyvalue属性列表,将它载入到Properties属性集合类中
        InputStream inputStream = Test2.class.getClassLoader().
                getResourceAsStream("class.properties");

        //创建属性集合列表
        Properties prop = new Properties() ;
        prop.load(inputStream);
        System.out.println(prop);

        //通过key获取value
        String className = prop.getProperty("className");
        String methodName = prop.getProperty("methodName");

        //反射获取当前className里面的类的字节码文件对象
        Class clazz = Class.forName(className) ;
       // System.out.println(clazz);
        //直接当前类实例
        Object obj = clazz.newInstance();

        //反射获取Method对象
        Method method = clazz.getMethod(methodName);
        method.invoke(obj) ;


    }

}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值