zoukankan      html  css  js  c++  java
  • java学习-reflection反射机制

    一、认识java Reflection反射机制

    Java Reflecation的定义

    Reflection(反射)被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性和方法。

    Java反射机制提供的功能

    1、在运行时判断任意一个对象所属的类;

    2、在运行时构造任意一个类的对象;

    3、在运行时判断任意一个类所具有的成员变量和方法;

    4、在运行时调用任意一个对象的成员变量和方法;

    5、生成动态代理。

    反射相关的API

    java.lang.Class:代表一个类
    java.lang.reflect.Method:代表类的方法
    java.lang.reflect.Field:代表类的成员变量
    java.lang.reflect.Constructor:代表类的构造方法

    二、公用类

    因为在这里,我们会用到一些类,所以我先贴出来,等着下面举例的时候可以参考:

    1、Person类:

    package com.xiaop.reflection;
    
    @MyAnnotation(value = "piper")
    public class Person extends Creature implements Comparable{
        
        public String name;
        private int age;
        public int i;
        
        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 int getI() {
            return i;
        }
    
        public void setI(int i) {
            this.i = i;
        }
    
        public Person(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
    
        public Person(String name) {
            super();
            this.name = name;
        }
    
        public Person() {
            super();
        }
    
        @Override
        public int compareTo(Object arg0) {
            // TODO Auto-generated method stub
            return 0;
        }
        
        @Override
        public String toString() {
            return "Person [name=" + name + ", age=" + age + "]";
        }
        
        @MyAnnotation(value = "abc123")
        public void show(){
            System.out.println("我是一个人!");
        }
        
        private Integer display(String nation,Integer i) throws Exception{
            System.out.println("我的国籍是:" + nation);
            return i;
        }
        
        public static void info(){
            System.out.println("中国人!");
        }
        
        class Bird{
            
        }
    
    }
    View Code

    2、Person的父类Creature

    package com.xiaop.reflection;
    
    public class Creature<T> {
        private double weight;
        public String colar;
        
        public void health(){
            System.out.println("呼吸");
        }
    }
    View Code

    3、Person类继承的接口MyInterface

    package com.xiaop.reflection;
    
    import java.io.Serializable;
    
    public interface MyInterface extends Serializable {
    
    }
    View Code

    4、Person类用到的注解Annotation

    package com.xiaop.reflection;
    
    import static java.lang.annotation.ElementType.CONSTRUCTOR;
    import static java.lang.annotation.ElementType.FIELD;
    import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
    import static java.lang.annotation.ElementType.METHOD;
    import static java.lang.annotation.ElementType.PARAMETER;
    import static java.lang.annotation.ElementType.TYPE;
    
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation {
        String value();
    }
    View Code

    三、Class类

    1、在Object类中定义了以下的方法,此方法将被所有子类继承:
    ● public final Class getClass()

    以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。

    2、对照镜子后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。
    3、Class本身也是一个类
    4、Class 对象只能由系统建立对象
    5、一个类在 JVM 中只会有一个Class实例
    6、一个Class对象对应的是一个加载到JVM中的一个.class文件
    7、每个类的实例都会记得自己是由哪个 Class 实例所生成
    8、通过Class可以完整地得到一个类中的完整结构

    1.Class常用的方法:

    方法名

    功能说明

    static Class  forName(String name)

    返回指定类名 name 的 Class 对象

    Object newInstance()

    调用缺省构造函数,返回该Class对象的一个实例

    getName()

    返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称

    Class getSuperClass()

    返回当前Class对象的父类的Class对象

    Class [] getInterfaces()

    获取当前Class对象的接口

    ClassLoader getClassLoader()

    返回该类的类加载器

    Class getSuperclass()

    返回表示此Class所表示的实体的超类的Class

    Constructor[] getConstructors()

    返回一个包含某些Constructor对象的数组

    Field[] getDeclaredFields()

    返回Field对象的一个数组

    Method getMethod(String name,Class  …  paramTypes)

    返回一个Method对象,此对象的形参类型为paramType

    例如,有了反射之后,我们可以通过反射创建类的对象,并调用类对象的结构

         /**
         * 有了反射,可以通过反射创建一个类的对象,并调用其中的结构
         * @throws Exception
         */
        @Test
        public void test2() throws Exception {
            Class<Person> clazz = Person.class;
            //1.创建clazz对应的运行时类Person类的对象
            Person p = (Person) clazz.newInstance();
            
            //2.通过反射调用运行时类的指定的属性
            //2.1
            Field field = clazz.getDeclaredField("name");
            field.set(p, "LiuDeHua");
            System.out.println(p);
            //2.2
            Field fieldAge  =clazz.getDeclaredField("age");
            fieldAge.setAccessible(true);
            fieldAge.set(p, 20);
            System.out.println(p);
            
            //3.通过反射调用运行时类的指定的方法
            Method m = clazz.getMethod("show");
            Object objVal = m.invoke(p);
            
            Method m1 = clazz.getMethod("display", String.class,Integer.class);
            Object objVal1 = m1.invoke(p, "zhongguo",30);
            System.out.println(objVal1);
        }

     2.实例化Class类的对象(四种方法)

    第一种:若已知具体的类,通过类的class属性获取,该方法最安全可靠,程序性能最高;

    例如:Class clazz = String.Class;

    第二种,若已知某个类的事例,调用该事例的getClass方法过去Class对象;

    例如:Class clazz = "com.xiaop.Person".getClass();

    第三种:已知一个类的全类名,且该类在类路径下,可以通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException;

    例如:Class clazz = Class.forName("java.lang.String");

    第四种:ClassLoader cl = this.getClass().getClassLoader();

    Class clazz = cl.loadClass("类的全类名");

    代码示例:

    /**
         * 如何获取Class的实例(3种)
         * @throws ClassNotFoundException 
         * @throws IllegalAccessException 
         * @throws InstantiationException 
         */
        @Test
        public void test4() throws Exception{
            //1.调用运行时类本身的.class属性
            Class clazz1 = Person.class;
            System.out.println(clazz1.getName());
            Class clazz2 = String.class;
            System.out.println(clazz2.getName());
            
            //2.通过运行时类的对象获取
            Person p = new Person();
            Class clazz3 = p.getClass();
            System.out.println(clazz3.getName());
            
            //3.通过Class的静态方法获取.通过此方式,体会一下,反射的动态性。
            String className = "com.xiaop.reflection.Person";
            Class clazz4 = Class.forName(className);
            //clazz4.newInstance();
            System.out.println(clazz4.getName());
            
            //4.(了解)通过类的加载器
            ClassLoader classLoder = this.getClass().getClassLoader();
            Class clazz5 = classLoder.loadClass(className);
            System.out.println(clazz5.getName());
            
            System.out.println(clazz1 == clazz3);//true
            System.out.println(clazz1 == clazz4);//true
            System.out.println(clazz1 == clazz5);//true
        }
  • 相关阅读:
    忙碌的一月
    SharePoint Portal Server 2003书籍计划最新进展
    如何判断Assembly是Debug还是Release?
    C#和C++的一个有意思的差别
    Enterprise Development Reference Architecture(ShadowFax)
    一个“轻量级”的SharePoint文档流转WebPart
    11月25日下午14:00,CSDN在线SharePoint TechTalk
    到北京后的第一篇随笔
    SOA & Messaging Patterns
    操作SharePoint Object Model完成两项操作的文档
  • 原文地址:https://www.cnblogs.com/hjwq/p/7659954.html
Copyright © 2011-2022 走看看