java反射初探

反射(Reflection)?

它是java语言特有的,其他语言并无此特性,其能力是在程序运行期间中,检查,操作,程序的内部属性。

Class对象?

它是jvm生成用来保存对应类的信息的,当我们定义好一个类文件并编译成.class字节码后,编译器同时为我们创建了一个Class对象并将它保存.class文件中。所以说只要拿到class对象即可操作对应类了。

注解?

是java语言5.0版本加入的特殊语法元数组,java语言中的类,方法,变量,参数,包都可以被标注。

1.代码的注解

@Override - 检查该方法是否是重载方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
@Deprecated - 标记过时方法。如果使用该方法,会报编译警告。
@SuppressWarnings - 指示编译器去忽略注解中声明的警告。

2.作用在其他注解上的注解()

@Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
@Documented - 标记这些注解是否包含在用户文档中。
@Target - 标记这个注解应该是哪种 Java 成员。
@Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)

3.从 Java 7 开始,额外添加了 3 个注解:

@SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
@FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。
@Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。


反射例子

首先我们写一个反射的测试类小栗子,在此基础上通过反射获取对应的信息,代码如下

@MyAnnitation(name="someName",  value = "Hello World")
public  class Person{
    private String name="xm";
    public int age=18;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    private void eat(){
        System.out.println("吃水果");
    }

    public void play(String playType){
        System.out.println(this.name+"玩"+playType);
    }
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)

public @interface MyAnnitation {
    public String name();
    public String value();
}

1.获取class对象

类名.class
Class.forName(类名)

public static void ObtainClass() {
        //方式一
        Class personCls1 = Person.class;

        //方式二
        Class personCls2 = null;
        String clsName = "com.bridge.view.javademo.Person";//类全名=类所在包名+类名
        try {
            personCls2 = Class.forName(clsName);
        } catch (ClassNotFoundException e) {//如果forName未找类,则抛出次异常
            e.printStackTrace();
        }
        System.out.println("**获取class对象**");
        System.out.println("方式一:" + personCls1);
        System.out.println("方式二:" + personCls2);
        System.out.println("                         ");
        System.out.println("                         ");
}

输出结果:
**获取class对象**
方式一:class com.bridge.view.javademo.Person
方式二:class com.bridge.view.javademo.Person

2.获取类名

Class.getName()
Class.getSimpleName

    public static void ObtainClassName() {
        Class personCls = Person.class;
        System.out.println("**获取类名**");
        System.out.println("方式一:" + personCls.getName());//获取全名
        System.out.println("方式二:" + personCls.getSimpleName());//获取类名,不包含所在包名
        System.out.println("                         ");
        System.out.println("                         ");
    }

输出结果:
**获取类名**
方式一:com.bridge.view.javademo.Person
方式二:Person

3.获取字段

Class.getFields()
Class.getField()
Class.getDeclaredFields()
Class.getDeclaredField()

    public static void ObtainField() {
        Class personCls = Person.class;
        Field[] Fields;
        System.out.println("**获取字段**");
        //通过getFields 获取所有公开字段
        System.out.println("获取所有公开字段");
        Fields = personCls.getFields();//获取public公开字段
        for (int i = 0; i < Fields.length; i++) {
            System.out.println(Fields[i]);
        }

        //通过getField获取指定公开字段
        System.out.println("获取指定公开字段");
        try {
            Field field;
            field = personCls.getField("age");
            System.out.println(field);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
       //通过getDeclaredFields,获取所有字段
        System.out.println("获取所有字段");
        Fields = personCls.getDeclaredFields();//获取所有申明字段,包括public private proteced
        for (int i = 0; i < Fields.length; i++) {
            Fields[i].setAccessible(true);//打开访问限制,在这里不调用也可以访问,确保访问还是加上这行代码
            System.out.println(Fields[i]);
        }

        //通过getDeclaredField,获取所有字段
        System.out.println("获取指定所有字段");
        try {
            Field field;
            field = personCls.getDeclaredField("age");
            field.setAccessible(true);//打开访问限制,在这里不调用也可以访问,确保访问还是加上这行代码
            System.out.println( field);
            field = personCls.getDeclaredField("name");
            field.setAccessible(true);//打开访问限制,在这里不调用也可以访问,确保访问还是加上这行代码
            System.out.println( field);

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        System.out.println("                         ");
        System.out.println("                         ");
    }

输出结果:
**获取字段**
获取所有公开字段
public int com.bridge.view.javademo.Person.age
获取指定公开字段
public int com.bridge.view.javademo.Person.age
获取所有字段
private java.lang.String com.bridge.view.javademo.Person.name
public int com.bridge.view.javademo.Person.age
获取指定所有字段
public int com.bridge.view.javademo.Person.age
private java.lang.String com.bridge.view.javademo.Person.name

4.获取方法

Class.getMethods()
Class.getMethod()
Class.getDeclaredMethods()
Class.getDeclaredMethod

 public static void ObtainMethod() {
        Class personCls = Person.class;
        System.out.println("**获取方法**");
        //通过getMethods获取所有公开方法
        System.out.println("获取所有公开字段的方法");
        Method[] methods =  personCls.getMethods();
        for(int i=0;i

5.获取构造函数

    public static void ObtainConstructor() {
        Class personCls = Person.class;
        System.out.println("**获取构造函数**");
        Constructor[] constructors = personCls.getConstructors();
        System.out.println("获取所有的构造函数");
        for(int i=0;i

6.获取注解

Class.getAnnotations()
Class.getAnnotation();
Class.getDeclaredAnnotations();

    public static void ObtainAnnotation() {
        Class personCls = Person.class;
        Annotation[] annotations = personCls.getAnnotations();
        for(int i=0;i

参考

Java 反射机制教程

你可能感兴趣的:(java反射初探)