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
        }
  • 相关阅读:
    【第40套模拟题】【noip2011_mayan】解题报告【map】【数论】【dfs】
    【模拟题(63550802...)】解题报告【贪心】【拓扑排序】【找规律】【树相关】
    【模拟题(电子科大MaxKU)】解题报告【树形问题】【矩阵乘法】【快速幂】【数论】
    IMemoryBufferReference and IMemoryBufferByteAccess
    SoftwareBitmap and BitmapEncoder in Windows.Graphics.Imaging Namespace
    Windows UPnP APIs
    编译Android技术总结
    Windows函数转发器
    Two Ways in Delphi to Get IP Address on Android
    Delphi Call getifaddrs and freeifaddrs on Android
  • 原文地址:https://www.cnblogs.com/hjwq/p/7659954.html
Copyright © 2011-2022 走看看