Java反射常用API以及实例

Java反射常用API以及实例

概念:JAVA反射机制是在运行状态中,对于任意一个类,都能知道这个类的所有方法和属性,对于任意一个对象,都能够调用它的任意方法和属性。

与Java反射相关的类如下:

类名用途
Class类代表类的实体,在运行的Java应用程序中表示类和接口
Field类代表类的成员变量(成员变量也称为类的属性)
Method类代表类的方法
Constructor类代表类的构造方法

一.类对象的获取

1.通过对象获取

Object obj = new Object();
Class cla= obj.getClass();

2.通过类名获取

Class cla = Object.class;

3.通过类的路劲名获取

Class cla = Class.forName("com.my");

二.类的实例化和构造函数

获取到的class对象可以直接通过cla.newInstance()方法实例化,但是要求目标类有默认无参构造函数,不然会抛出异常。在类没有默认无参构造函数或者需要某个具体的构造函数来实例化的情况,需要根据Constructor的newInstance()来完成。

public T newInstance(Object... initargs)

1.获取公有构造函数,不包括父类

public Constructor<?>[] getConstructor()
public Constructor<T> getConnector(Class<?>.. parameterType)

2.获取当前类的构造函数,忽略修饰符

public Constructor<?>[] getDeclaredConstructors()
public Constructor<T> getDeclaredConstructor(Class<?>.. parameterType)
//忽略修饰符强制调用,即为true是开启可以调用私有构造方法
public void setAccessible(boolean flag)

三.类成员变量的获取

1.获取公有成员变量,包括父类

public Field[] getFields()
public Field getField(String name)

2.获取当前类成员变量,忽略修饰符强制调用

public Field[] getDeclaredFields()
public Field getDeclaredField(String name)
//成员变量赋值    
//Obj为实例对象
public void set(Object obj,Object value)
//忽略修饰符,强制调用,,即为true是开启可以调用私有成员
public void setAccessible(boolean flag)    

四.类方法的获取

1.获取共有方法,包括父类

public Method[] getMethods()
public Method getMethod(String name, Class<?>.. parameterTypes)

2.获取当前类的方法,忽略修饰符

public Method[] getDeclaredMethods()
public Method getDeclaredMethod(String name, Class<?>.. parameterTypes)
//obj为类实例化对象,如果为静态方法obj为null
invoke(Object obj, Object... args)
//忽略修饰符,强制调用,,即为true是开启可以调用私有方法
public void setAccessible(boolean flag)

五.例子

Animal.java

package com.my;
public class Animal {
    private String name= "lucky";
    public void sayHello(String sb) {
        System.out.println(sb+" say hello!");
    }
    private String throwHello(String sb) {
        return "hello!"+sb;
    }
}

Reflect.java

package com.my;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Reflect {
    public static void main(String args[]) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
        //获取这个类对象
        Class cla = Class.forName("com.my.Animal");
        
        //获得对象实例
        Animal animal = (Animal)cla.newInstance();
        
        //获取这个类的名称并打印
        System.out.println("Class name is "+cla.getName());
        
        //要获取私有方法,先定义一个对象
        //可以获得所有方法 但不能获取继承的和所实现的方法
        Method getHello = cla.getDeclaredMethod("throwHello", String.class);
        getHello.setAccessible(true);
        Object str = getHello.invoke(animal, "Tony");
        System.out.println("getHello result is "+ str);
        
        //通过反射可以调用共有方法 包括所实现的接口的方法和继承的方法
        Method sayHello = cla.getMethod("sayHello", String.class);
        sayHello.invoke(animal,"Bob");
    }
}

控制台输出:

Class name is com.my.Animal
getHello result is hello!Tony
Bob say hello!

六.总结:

1、获取类的属性:

Filed类----c.getFiled(String pname) 获得指定属性(公共字段)
Filed类----c.getDeclearedFiled(String pname) 获得指定属性(本类中的所有权限字段,不包括父类中的字段信息)
Filed[]----c.getFileds() 获得所有属性(公共字段)包括本类及其父类中的所有公有字段信息
Filed[]----c.getDeclearedFileds() 获得所有属性(所有权限字段)只包括本类中的字段信息,不包括父类中的字段信息.

2、获取类的方法:

Method类----c.getMethod(String methodName,class[] params) 获得指定方法(公共方法)
Method类----c.getDeclearedMethod(String methodName,class[] params)获得本类中指定方法(所有方法)不包括父类中的方法
Method[]----c.getMethods() 获得所有方法(公共方法),包括父类中的方法
Method[]----c.getDeclearedMethods() 获得本类中所有方法(所有权限方法),不包括父类中的方法.

反射的好处,其实就一句话:高内聚低耦合。把代码动态化,提高了代码的灵活度减少了代码量!

反射的缺点,代码灵活度增大了,自然会带来效率的问题,因此,大量使用反射会带来效率低的问题!

我来吐槽

*

*