Java反射机制简单介绍

概述

Java的反射机制允许我们在运行时发现和使用类的信息。是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

Class对象

一个Class对象表示了运行时的类型信息,包含了类的相关信息。Class对象用于表示一个.class文件,即类的字节码文件。

类的加载

当一个类在第一次被使用时,JVM才会将其动态地加载。当这个类的Class对象被载入内存后,就能通过它来创建这个类的所有对象。

获取Class对象的方法

1.使用Class类的forName()静态方法:

Class c=Class.forName(目标类的文本名);

2.使用类字面常量,假设有Test类,则可通过以下方法获取Class对象:

Class c=Test.class;

3.使用从Object类集成的getClass()方法。

Test test=new Test();
Class c=test.getClass();
演示

测试类Reflection

package com.learn.domain;
public class Reflection {
    public String publicField;

    private String privateField;

    public String getPublicField() {
        return publicField;
    }

    public void setPublicField(String publicField) {
        this.publicField = publicField;
    }

    public String getPrivateField() {
        return privateField;
    }

    public void setPrivateField(String privateField) {
        this.privateField = privateField;
    }
    
	private void privateMethod(String param){
	       System.out.println("我是私有方法,参数:"+param);
	}
    
    @Override
    public String toString() {
        return "publicField:" + publicField + " privateField:" + privateField;
    }
}

主程序

public class Main {
    public static void main(String[] args) {
        try {
            System.out.println(Class.forName("com.learn.domain.Reflection"));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println(Reflection.class);
        System.out.println(new Reflection().getClass());
    }
}

输出

class com.learn.domain.Reflection
class com.learn.domain.Reflection
class com.learn.domain.Reflection

Class

在Java SE5之后,允许通过泛型语法对Class引用所指向的类型进行限定,从而提供了编译期的类型检查。比如使用Class表示Test类及其子类的Class对象,引用错误时在编译时便可发现。而如果使用普通的Class引用,则会到运行时才发现错误。

通过反射创建对象简单介绍

使用Class的newInstance方法可以创建实例对象。

演示

主程序

public class Main {
    public static void main(String[] args) {
        try {
            Class clazz = Class.forName("com.learn.domain.Reflection");
            System.out.println(clazz.newInstance());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

输出

publicField:null privateField:null
  • 注意,使用class的newInstance方法时,必须保证这个类存在有无参构造方法

通过反射操作变量简单介绍

通过Class可以获取类的字段Field,在通过Field可以对字段进行相关的操作。

演示

主程序

public class Main {
    public static void main(String[] args) {
        try{
            Class clazz = Class.forName("com.learn.domain.Reflection");
            //获取Reflection的所有字段
            Field[] fields = clazz.getDeclaredFields();  // ---- (1)
            for(Field tmp:fields){
                String modifier = Modifier.isPrivate(tmp.getModifiers())?  // ---- (2)
                        "private":(Modifier.isPublic(tmp.getModifiers())?"public":"");
                System.out.println("字段("+modifier+"):"+tmp.getName());
            }
            Reflection reflection = new Reflection();
            System.out.println(reflection);
            Field privateField = clazz.getDeclaredField("privateField");  // ---- (3)
            privateField.setAccessible(true);  // ---- (4)
            privateField.set(reflection, "我是私有字段");  // ---- (5)
            System.out.println(reflection); 
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

输出

字段(public):publicField
字段(private):privateField
publicField:null privateField:null
publicField:null privateField:我是私有字段
  1. 通过Class的getDeclaredFields方法可以获取类的所有字段(public、private等所有字段)。如果使用getFields方法,则只能得到public字段。注意,使用这两个方法获取的字段只是在本类中定义的字段,不能获取到父类的定义的字段
  2. 使用Field类的getModifiers方法可以获取字段的修饰符信息,并借助Modifier类的静态方法进行判断。
  3. 可以根据提供的字段名获取指定的字段。
  4. 操作使用字段时,必须使用Field类的setAccessible方法
  5. 使用Field类的set方法可以对对象字段赋值。

通过反射操作方法简单介绍

通过Class可以获取类的方法Method,在通过Method可以对方法进行相关的操作,其操作与对Field的操作类似。

演示

主程序

public class Main {
    public static void main(String[] args) {
        try{
            Class clazz = Class.forName("com.learn.domain.Reflection");
            //获取Reflection的所有字段
            Method[] methods = clazz.getDeclaredMethods();
            for(Method tmp:methods){
                String modifier = Modifier.isPrivate(tmp.getModifiers())?
                        "private":(Modifier.isPublic(tmp.getModifiers())?"public":"");
                System.out.println("方法("+modifier+"):"+tmp.getName());
            }
            Reflection reflection = new Reflection();
            Method privateMethod = clazz.getDeclaredMethod("privateMethod",String.class);
            privateMethod.setAccessible(true);
            privateMethod.invoke(reflection, "csdn");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

输出

方法(public):toString
方法(public):getPrivateField
方法(private):privateMethod
方法(public):setPublicField
方法(public):setPrivateField
方法(public):getPublicField
我是私有方法,参数:csdn

你可能感兴趣的:(Java)