第二节:反射学习

2017-06-29  本文已影响15人  cf许我向你看

1.反射机制:

java运行期间动态的加载一些不确定的类的对象。大多数的情况下我们使用的是一个确定的类,通过在内存中的加载,再使用。
反射机制提供的功能

1.1 动态加载类

image.png

通过以上的代码可以总结使用Reflection.需要如下几步:

  1. 获取目标对象的Class对象
  2. 调用Class对象内省方法获取目标对类成员信息
  3. 调用目标的成员属性

1.2 解析类的结构

1.2.1 定义一个Teacher的类

public class Teacher {
private String name;
    private  int age;
    private  static  int total;
    public Teacher(String name, int age) {
        this.name = name;
        this.age = age;
        total++;
    }
    public Teacher() {
       total++;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public static int getTotal() {
        return total;
    }
    public static void setTotal(int total) {
        Teacher.total = total;}
    @Override
    public String toString() {
        return "Teacher{" + "name='" + name + '\'' + ", age=" + age + '}';
    }
}

1.2.2 对Teacher进行解析

  public class RflectionTeacher {
    private  final  static  String TEACHER_CLASS="reflection.Teacher";
    public static void main(String[] args) {
        try {
            Class<?> clazz = Class.forName(TEACHER_CLASS);
            Field[] fields = clazz.getDeclaredFields();//获取该类中的属性属性成员
            Method[] methods = clazz.getDeclaredMethods();//获取该类的成员方法
            Constructor<?>[] constructors = clazz.getConstructors();//获取该类的所有的构造方法
            System.out.println("------打印成员属性-------");
            for(Field field:fields){
                System.out.println("属性 :"+field);
                System.out.println("名称 :"+field.getName());
                System.out.println("修饰符 :"+ Modifier.toString(field.getModifiers()));
                System.out.println("--------------------------------------------------");
            }
            for (Method method:methods){
                System.out.println("方法 :"+method.toString());
                System.out.println("方法名称 :"+method.getName());
                System.out.println("方法修饰符 :"+Modifier.toString(method.getModifiers()));
                System.out.println("------方法参数列表------");
                Class<?>[] types = method.getParameterTypes();
                System.out.println(types.length!=0?"有参数":"无参数:");
                for (Class c:types){
                    System.out.println(c.getName()+"类型\t");
                }
                System.out.println("\n方法返回类 型 :"+method.getReturnType().getName());
                System.out.println("=====================================");
            }
            System.out.println("***************打印构造方法 ***************");
            for(Constructor constructor:constructors){
                System.out.println("构造方法 :"+constructor.toString());
                System.out.println("构造方法名 :"+constructor.getName());
                System.out.println("构造方法修饰符 :"+Modifier.toString(constructor.getModifiers()));
                Class[] mClass=constructor.getParameterTypes();
                System.out.print(mClass.length!=0?"有参数:":"无参数:");
                for(Class c:mClass){
                    System.out.print(c.getName()+"类型\t");
                }
                System.out.println("\n=====================================");
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

1.2.3 输出结果

------打印成员属性-------
属性 :private java.lang.String reflection.Teacher.name
名称 :name
修饰符 :private
--------------------------------------------------
属性 :private int reflection.Teacher.age
名称 :age
修饰符 :private
--------------------------------------------------
属性 :private static int reflection.Teacher.total
名称 :total
修饰符 :private static
--------------------------------------------------
方法 :public java.lang.String reflection.Teacher.toString()
方法名称 :toString
方法修饰符 :public
------方法参数列表------
无参数:

方法返回类 型 :java.lang.String
=====================================
方法 :public java.lang.String reflection.Teacher.getName()
方法名称 :getName
方法修饰符 :public
------方法参数列表------
无参数:

方法返回类 型 :java.lang.String
=====================================
方法 :public void reflection.Teacher.setName(java.lang.String)
方法名称 :setName
方法修饰符 :public
------方法参数列表------
有参数
java.lang.String类型  

方法返回类 型 :void
=====================================
方法 :public static int reflection.Teacher.getTotal()
方法名称 :getTotal
方法修饰符 :public static
------方法参数列表------
无参数:

方法返回类 型 :int
=====================================
方法 :public int reflection.Teacher.getAge()
方法名称 :getAge
方法修饰符 :public
------方法参数列表------
无参数:

方法返回类 型 :int
=====================================
方法 :public void reflection.Teacher.setAge(int)
方法名称 :setAge
方法修饰符 :public
------方法参数列表------
有参数
int类型   

方法返回类 型 :void
=====================================
方法 :public static void reflection.Teacher.setTotal(int)
方法名称 :setTotal
方法修饰符 :public static
------方法参数列表------
有参数
int类型   

方法返回类 型 :void
=====================================
***************打印构造方法 ***************
构造方法 :public reflection.Teacher(java.lang.String,int)
构造方法名 :reflection.Teacher
构造方法修饰符 :public
有参数:java.lang.String类型  int类型   
=====================================
构造方法 :public reflection.Teacher()
构造方法名 :reflection.Teacher
构造方法修饰符 :public
无参数:
=====================================

1.3 访问类的属性和方法

1.3.1 Student类

public class Student {
private String name;
    private static  int count=100;
    public Student() {
    }
    public Student(String name) {
        this.name = name;
    }
    public void setValue(String name){
        this.name = name;
    }
    public void showCount(){
        System.out.println("Student对象被实例化了"+count+"次");
    }
    public String toString(){
        return "Name:"+this.name+",调用次数:"+count;
    }
}

1.3.2 访问 name 属性的操作方法:

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
         //访问name属性的操作方法
        Student student = new Student("zhangsan");
        Class<? extends Student> claszz = student.getClass();
        Field field = claszz.getField("name");
        Object o = field.get(student);
        System.out.println("修改前 "+ field.getName()+" 的值 "+o);
        field.set(student,"李思");
        o=field.get(student);
        System.out.println("修改后:"+field.getName()+"的值:"+o);
    }

1.3.3 访问 setValue 方法的操作方法

 public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //访问 setValue 方法的操作方法
        Student student = new Student("zhangsan");
        Class<? extends Student> claszz = student.getClass();
        Method m = claszz.getMethod("setValue", new Class[]{String.class});
        m.invoke(student, new Object[]{"张三"});
        System.out.println(student.toString());

    }

1.3.4 访问类的有参构造方法

 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //访问类的有参构造方法
        Class<?> clazz = Class.forName("reflection.Student");
        Constructor<?> constructor = clazz.getConstructor(new Class[]{String.class});
        Student student= (Student)constructor.newInstance(new Object[]{"陈飞"});
        System.out.println("----->>>>-----"+student);
    }

1.4 如何使用反射机制

使用反射机制,就是因为不知道运行的时候不知道使用哪一个类,所以就需要运行的时候动态加载。先加载动态的类,然后再解析类。最后使用反射API对类的成员信息进行访问。

1.5 静态代理

若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的。 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类

public interface Subject {
    public  int add(int a ,int b);
}
public class ReadSubject implements  Subject {
    @Override
    public int add(int a, int b) {
        return a+b;
    }
}
public class Proxy implements Subject {

    private Subject subject=null;

    public Proxy(Subject subject) {
        this.subject = subject;
    }

    @Override
    public int add(int arg1, int arg2) {
        System.out.println("被加数为:"+arg1);
        System.out.println("加数为:"+arg2);
        return subject.add(arg1, arg2);
    }
}
public class ProxyTest {
    public static void main(String[] args) {
        Subject subject = new Proxy(new ReadSubject());
        int resulr=subject.add(1,4);
        System.out.println(resulr);
    }
}

1.6动态代理

静态代理解决了业务逻辑与日志信息脱耦的一种设计, 但是又带来其他的问题, 也就是
说我们有 100 个目标对象,就需要设计 100 个代理,这样会引起类爆炸(类非常多) 。
代理类在程序运行时创建的代理方式被成为 动态代理。 也就是说,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。

public class DynamicProxy implements InvocationHandler {
    private  Object object=null;
     public Object biding(Object object){
         this.object=object;
         return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
     }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result=null;
        for (Object o:args){
            System.out.println(o);
        }
        result=method.invoke(object,args);
        return result;
    }
}
public class DymicProxyTest {
    public static void main(String[] args) {
        DynamicProxy dynamicProxy = new DynamicProxy();
        Subject biding = (Subject)dynamicProxy.biding(new ReadSubject());
        int resultt=biding.add(1,6);
        System.out.println(resultt);
    }
}

1.7 创建对象的几种方式

上一篇 下一篇

猜你喜欢

热点阅读