反射总结

1:反射

    (1)类的加载及类加载器

    (2)反射:

        1.概念:通过class文件对象,去使用该文件中的成员变量,构造方法,成员方法。        

        允许程序在运行期间,动态的创建某个对象,并调用其中的方法。是创建对象的另外一种方式

        要想使用,首先你必须得到class文件对象,其实也就是得到Class类的对象。

       

        2.获取class文件对象的方式:

               A:Object类的getClass()方法--Class cls=new 对象().getClass();


        Person p = new Person();

        Class c = p.getClass();



        Person p2 = new Person();

        Class c2 = p2.getClass();



        System.out.println(p == p2);// false

        System.out.println(c == c2);// true

               B:数据类型的静态属性class--Class cls=类名.class;

  Class c3 = Person.class;

        // int.class;

        // String.class;

        System.out.println(c == c3);

 

               C:Class类中的静态方法               

        public static Class forName(String className)--Class cls=Class.forName("类的完全限定名");



        Class c4 = Class.forName("cn.itcast_01.Person");

        System.out.println(c == c4);

    

               开发使用第三种:因为第三种是一个字符串,而不是一个具体的类名。这样我们就可以把这样的字符串配置到配置文件中。

 

               

3.Class对象封装了一个类的所有信息,包括:

    1,类继承自哪个类

    2,实现了哪些接口

    3,有哪些属性

    4,有哪些方法

    5,有哪些构造器

 

4.反射的优点:

    功能强大

    提供了很大的灵活性

    常用于高级编程,如开发Web容器

  反射的缺点:

    性能开销

    数据安全问题

   暴露隐藏的成员

 

    (3)反射的使用        

      Class常用的方法:

    1,class.new Instance();    //创建当前实例对象

    2,class.getName();        //获取类的完全限定名

    3,class.getSimpleName();    //获取类名

    4,class.getSuperClass();    //获取父类的class对象

 

        A:通过反射获取构造方法(Constructor)并使用

           public Constructor[] getConstructors():所有公共构造方法

           public Constructor[] getDeclaredConstructors():所有构造方法

           public Constructor<T> getConstructor(Class<?>... parameterTypes):获取单个构造方法

                     参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象

                     Constructor con = class .getConstructor();// 返回的是构造方法对象

                     Constructor con = class .getConstructor(String.class, int.class, String.class);//获取带参数的构造方法对象

           public T newInstance(Object... initargs)

                      使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。

                      Object obj = con.newInstance();

                      System.out.println(obj);

           con.setAccessible(true); 暴力访问,设置允许私有调用,值为true则指示反射的对象在使用时应该取消Java语言访问检查。


 


/*

 * 需求:通过反射获取私有构造方法并使用

 * private Person(String name){}

 *

 * Person p = new Person("风清扬");

 * System.out.println(p);

 */

public class ReflectDemo3 {

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

        // 获取字节码文件对象

        Class c = Class.forName("cn.itcast_01.Person");



        // 获取私有构造方法对象

        // NoSuchMethodException:没有这个方法异常

        Constructor con = c.getDeclaredConstructor(String.class);



        // 用该私有构造方法创建对象

        // IllegalAccessException:非法的访问异常。

        // 暴力访问

        con.setAccessible(true);// 值为true则指示反射的对象在使用时应该取消Java语言访问检查。

        Object obj = con.newInstance("风清扬");



        System.out.println(obj);

    }

}

        B:通过反射获取成员变量(Field)并使用

           class.getFields();        //获取所有的public修饰的属性

           class.getDeclaredFields();    //获取所有的属性,包含私有

           class.getDeclaredField(name);//获取指定的属性:name是属性名

          

 field.getName();        //获取属性名

 field.set(Obejct,value);    //向指定对象中设值

 field.get(Obejct);        //从指定对象中取值


 

/*

 * 通过反射获取成员变量并使用

 */

public class ReflectDemo {

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

        // 获取字节码文件对象

        Class c = Class.forName("cn.itcast_01.Person");



        // 通过无参构造方法创建对象

        Constructor con = c.getConstructor();

        Object obj = con.newInstance();



        // 获取单个的成员变量

        // 获取address并对其赋值

        Field addressField = c.getField("address");



        addressField.set(obj, "北京"); // 给obj对象的addressField字段设置值为"北京"



        // 获取name并对其赋值

        // NoSuchFieldException //没有这个字段-加上Declared获取指定字段

        Field nameField = c.getDeclaredField("name");

        // IllegalAccessException //安全权限异常

        nameField.setAccessible(true); //暴力访问

        nameField.set(obj, "林青霞");



        // 获取age并对其赋值

        Field ageField = c.getDeclaredField("age");

        ageField.setAccessible(true);

        ageField.set(obj, 27);

        System.out.println(obj);

    }

}

 

        C:通过反射获取成员方法(Method)并使用

           class.getMethods();        //获取自己的包括父亲的公共方法

           class.getDeclaredMethods();    //获取自己的所有的方法

           class.getMethod(String name,Class<?>... parameterTypes);  //获取指定的方法

           class.getDeclaredMethod(name,参数1类型.class); //获取指定的私有方法:第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型

 method.setAccessible(true);//设置允许私有调用

 method.invoke(Obejct, "参数","参数2","参数3");//调用方法:第一个参数表示对象是谁,第二参数表示调用该方法的实际参数

public class ReflectDemo {

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

        // 获取字节码文件对象

        Class c = Class.forName("cn.itcast_01.Person");



        Constructor con = c.getConstructor();

        Object obj = con.newInstance();



        // 获取单个方法并使用

        Method m1 = c.getMethod("show");

        m1.invoke(obj); // 调用obj对象的m1方法



        // public void method(String s)

        Method m2 = c.getMethod("method", String.class);

        m2.invoke(obj, "hello");



        // public String getString(String s, int i)

        Method m3 = c.getMethod("getString", String.class, int.class);

        Object objString = m3.invoke(obj, "hello", 100);  

        // String s = (String)m3.invoke(obj, "hello",100);

        // System.out.println(s);



        // private void function()

        Method m4 = c.getDeclaredMethod("function");

        m4.setAccessible(true);

        m4.invoke(obj);

    }

}


 

    (4)反射案例

        A:通过反射运行配置文件的内容

/*

 * 通过配置文件运行类中的方法

 *

 * 反射:

 *         需要有配置文件配合使用。

 *         用class.txt代替。  

               className=cn.itcast.test.Worker

               methodName=love

 *         并且你知道有两个键。

 *             className

 *             methodName

 */

public class Test {

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

        // 加载键值对数据

        Properties prop = new Properties();

        FileReader fr = new FileReader("class.txt");

        prop.load(fr);

        fr.close();



        // 获取数据

        String className = prop.getProperty("className");

        String methodName = prop.getProperty("methodName");



        // 反射

        Class c = Class.forName(className);



        Constructor con = c.getConstructor();

        Object obj = con.newInstance();



        // 调用方法

        Method m = c.getMethod(methodName);

        m.invoke(obj);

    }

}


 

        B:通过反射越过泛型检查


/*

 * 我给你ArrayList<Integer>的一个对象,我想在这个集合中添加一个字符串数据,如何实现呢?

 */

public class ArrayListDemo {

    public static void main(String[] args) throws NoSuchMethodException,

            SecurityException, IllegalAccessException,

            IllegalArgumentException, InvocationTargetException {

        // 创建集合对象

        ArrayList<Integer> array = new ArrayList<Integer>();



        Class c = array.getClass(); // 集合ArrayList的class文件对象

        Method m = c.getMethod("add", Object.class);



        m.invoke(array, "hello"); // 调用array的add方法,传入的值是hello

        m.invoke(array, "world");

        m.invoke(array, "java");



        System.out.println(array);

    }

}



        C:通过反射给任意的一个对象的任意的属性赋值为指定的值


public class Tool {

    public void setProperty(Object obj, String propertyName, Object value)

            throws NoSuchFieldException, SecurityException,

            IllegalArgumentException, IllegalAccessException {

        // 根据对象获取字节码文件对象

        Class c = obj.getClass();

        // 获取该对象的propertyName成员变量

        Field field = c.getDeclaredField(propertyName);

        // 取消访问检查

        field.setAccessible(true);

        // 给对象的成员变量赋值为指定的值

        field.set(obj, value);

    }

}

public class ToolDemo {

    public static void main(String[] args) throws NoSuchFieldException,

            SecurityException, IllegalArgumentException, IllegalAccessException {

        Person p = new Person();

        Tool t = new Tool();

        t.setProperty(p, "name", "林青霞");

        t.setProperty(p, "age", 27);

        System.out.println(p);



        Dog d = new Dog();

        t.setProperty(d, "sex", '男');

        t.setProperty(d, "price", 12.34f);

        System.out.println(d);

    }

}



class Dog {

    char sex;

    float price;



    @Override

    public String toString() {

        return sex + "---" + price;

    }

}



class Person {

    private String name;

    public int age;



    @Override

    public String toString() {

        return name + "---" + age;

    }

}

 

    (5)动态代理


import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;



public class MyInvocationHandler implements InvocationHandler {

    private Object target; // 目标对象



    public MyInvocationHandler(Object target) {

        this.target = target;

    }



    @Override

    public Object invoke(Object proxy, Method method, Object[] args)

            throws Throwable {

        System.out.println("权限校验");

        Object result = method.invoke(target, args);

        System.out.println("日志记录");

        return result; // 返回的是代理对象

    }

}

public interface StudentDao {

    public abstract void login();



    public abstract void regist();

}

public class StudentDaoImpl implements StudentDao {



    @Override

    public void login() {

        System.out.println("登录功能");

    }



    @Override

    public void regist() {

        System.out.println("注册功能");

    }



}

/*

 * 用户操作接口

 */

public interface UserDao {

    public abstract void add();



    public abstract void delete();



    public abstract void update();



    public abstract void find();

}

public class UserDaoImpl implements UserDao {



    @Override

    public void add() {

        System.out.println("添加功能");

    }



    @Override

    public void delete() {

        System.out.println("删除功能");

    }



    @Override

    public void update() {

        System.out.println("修改功能");

    }



    @Override

    public void find() {

        System.out.println("查找功能");

    }



}

public class Test {

    public static void main(String[] args) {

        UserDao ud = new UserDaoImpl();

        ud.add();

        ud.delete();

        ud.update();

        ud.find();

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

        // 我们要创建一个动态代理对象

        // Proxy类中有一个方法可以创建动态代理对象

        // public static Object newProxyInstance(ClassLoader loader,Class<?>[]

        // interfaces,InvocationHandler h)

        // 我准备对ud对象做一个代理对象

        MyInvocationHandler handler = new MyInvocationHandler(ud);

        UserDao proxy = (UserDao) Proxy.newProxyInstance(ud.getClass()

                .getClassLoader(), ud.getClass().getInterfaces(), handler);

        proxy.add();

        proxy.delete();

        proxy.update();

        proxy.find();

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



        StudentDao sd = new StudentDaoImpl();

        MyInvocationHandler handler2 = new MyInvocationHandler(sd);

        StudentDao proxy2 = (StudentDao) Proxy.newProxyInstance(sd.getClass()

                .getClassLoader(), sd.getClass().getInterfaces(), handler2);

        proxy2.login();

        proxy2.regist();

    }

}



 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值