Java反射笔记

Java反射 之 初体验

    笔者最近在java编程实践中接触到Java的反射机制,于是粗浅地做了一些了解,在此记录一下。

    java反射的主要作用体现在为JVM动态加载类,获取类的成员,方法,构造器等提供了一种手段。    

   Java反射框架主要提供以下功能:

  •         1.在运行时判断任意一个对象所属的类;
  •         2.在运行时构造任意一个类的对象;
  •         3.在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法);
  •         4.在运行时调用任意一个对象的方法
    重点:是运行时而不是编译时

       反射的主要用途在于开发框架,很多框架(比如Spring)都是配置化的(比如通过XML文件配置JavaBean,Action之类的),为了保证框架的通用性,它们可能需要根据配置文件加载不同的对象或类,调用不同的方法,这个时候就必须用到反射——运行时动态加载需要加载的对象。

1、获得Class对象

方法有三种
(1)使用Class类的forName静态方法:

1
2
3
4
5
public static Class<?> forName(String className)
```
在JDBC开发中常用此方法加载数据库驱动:
```java
Class.forName(driver);

(2)直接获取某一个对象的class,比如:

1
2
Class<?> klass = int.class;
Class<?> classInt = Integer.TYPE;

(3)调用某个对象的getClass()方法,比如:

1
2
StringBuilder str = new StringBuilder("123");
Class<?> klass = str.getClass();

2、判断是否为某个类的实例

一般地,我们用instanceof关键字来判断是否为某个类的实例。同时我们也可以借助反射中Class对象的isInstance()方法来判断是否为某个类的实例,它是一个Native方法:

1
public native boolean isInstance(Object obj);

3、创建实例

通过反射来生成对象主要有两种方式。
(1)使用Class对象的newInstance()方法来创建Class对象对应类的实例。

1
2
Class<?> c = String.class;
Object str = c.newInstance();

(2)先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建实例。这种方法可以用指定的构造器构造类的实例。

1
2
3
4
5
6
7
//获取String所对应的Class对象
Class<?> c = String.class;
//获取String类带一个String参数的构造器
Constructor constructor = c.getConstructor(String.class);
//根据构造器创建实例
Object obj = constructor.newInstance("23333");
System.out.println(obj);

4、获取方法

获取某个Class对象的方法集合,主要有以下几个方法:
getDeclaredMethods()方法返回类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。

1
public Method[] getDeclaredMethods() throws SecurityException

getMethods()方法返回某个类的所有公用(public)方法,包括其继承类的公用方法。

1
public Method[] getMethods() throws SecurityException

getMethod方法返回一个特定的方法,其中第一个参数为方法名称,后面的参数为方法的参数对应Class的对象

1
public Method getMethod(String name, Class<?>... parameterTypes)

5、获取构造器信息

获取类构造器的用法与上述获取方法的用法类似。主要是通过Class类的getConstructor方法得到Constructor类的一个实例,而Constructor类有一个newInstance方法可以创建一个对象实例:

1
public T newInstance(Object ... initargs)

此方法可以根据传入的参数来调用对应的Constructor创建对象实例~

6、获取类的成员变量(字段)信息

主要是这几个方法,在此不再赘述:
getFiled: 访问公有的成员变量
getDeclaredField:所有已声明的成员变量。但不能得到其父类的成员变量
getFileds和getDeclaredFields用法同上(参照Method)

7、调用方法

当我们从类中获取了一个方法后,我们就可以用invoke()方法来调用这个方法。invoke方法的原型为:

1
2
3
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException

下面给一个例子:

public class test1 {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class<?> klass = methodClass.class;
        //创建methodClass的实例
        Object obj = klass.newInstance();
        //获取methodClass类的add方法
        Method method = klass.getMethod("add",int.class,int.class);
        //调用method对应的方法 => add(1,4)
        Object result = method.invoke(obj,1,4);
        System.out.println(result);
    }
}
class methodClass {
    public final int fuck = 3;
    public int add(int a,int b) {
        return a+b;
    }
    public int sub(int a,int b) {
        return a+b;
    }
}

8、利用反射创建数组

数组在Java里是比较特殊的一种类型,它可以赋值给一个Object Reference。下面我们看一看利用反射创建数组的例子:

	/**
	 * 用反射来创建数组
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			Class<?> clazz = Class.forName("java.lang.String");
			Object array = Array.newInstance(clazz, 10);
			Array.set(array, 0, "Nuist");
			Array.set(array, 1, " is");
			Array.set(array, 2, " a");
			Array.set(array, 3, " good");
			Array.set(array, 4, " school.");
			
			for(int i = 0; i < 5; i ++) {
				if(null != Array.get(array, i) || !((String) Array.get(array, i)).equals("")) {
					System.out.print(Array.get(array, i).toString());
				}
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
输出结果:

其中的Array类为java.lang.reflect.Array类。我们通过Array.newInstance()创建数组对象,它的原型是:
1
2
3
4
public static Object newInstance(Class<?> componentType, int length)
throws NegativeArraySizeException {
return newArray(componentType, length);
}

而newArray()方法是一个Native方法,它在Hotspot JVM里的具体实现我们后边再研究,这里先把源码贴出来

1
2
private static native Object newArray(Class<?> componentType, int length)
throws NegativeArraySizeException;
    望每天进步一点,再见

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章