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
    }

 

posted @ 2017-10-13 10:46  飞鸿踏雪泥xp  阅读(296)  评论(0编辑  收藏  举报