JAVA 反射总结

来源:互联网 发布:北京人民大学网络教育 编辑:程序博客网 时间:2024/05/22 01:59
反射提供了程序分析类的能力,利用JAVA的反射机制可以方便完成很多工作,常用到的3个类:

java.lang.reflect.Field

java.lang.reflect.Method

java.lang.Class<T>


一.java.lang.Class<T>:

在运行的JAVA程序中维护所有对象的信息的一个类.Class类没有公共的构造方法,一个类加载时它的Class对象由虚拟机自动创建。

通过三种方法可以得到Class对象。

1.getClass方法

2.静态方法forName获得类名对应的Class对象

3..class

package test.reflect;public class ReflectionTest {public static void main(String[] args) {//getClass方法DemoClass demo = new DemoClass();Class<?> c1 = demo.getClass();try {//forNameClass<?> c2 = Class.forName("test.reflect.DemoClass");//.classClass<?> c3 = DemoClass.class;System.out.println(c1.getName());System.out.println(c2.getName());System.out.println(c3.getName());} catch (ClassNotFoundException e1) {e1.printStackTrace();}}}class DemoClass {}

结果:

注:一个Class对象实际上表示的是一个类型,而这个类型未必一定是一个类。比如,int是基本数据类型不是类,但是int.class是一个Class类型的对象。虚拟机为所有的类型维护一个Class类。


Class类一些常用的方法:

getClasses:返回指定类及其父类的所有公共的内部类,接口

getDeclaredClasses:返回指定类的所有内部类,接口

public class ReflectionTest {public static void main(String[] args) {Class<?>[] classes = DemoClass.class.getClasses();for (Class<?> a: classes) {System.out.println(a.getName());}Class<?>[] classes2 = DemoClass.class.getDeclaredClasses();for (Class<?> b: classes2) {System.out.println("Declared:"+b.getName());}}}class DemoClass  extends TestClass{public class a {}public interface b {}private class c {}}class TestClass {private class e {}public class d {}}

结果

test.reflect.DemoClass$a
test.reflect.DemoClass$b
test.reflect.TestClass$d
Declared:test.reflect.DemoClass$a
Declared:test.reflect.DemoClass$b
Declared:test.reflect.DemoClass$c


getConstructors() :取得所有的公共构造方法
getDeclaredConstructors() :取得所有的构造方法

getDeclaredConstructor(Class<?>... parameterTypes) :根据指定的参数类型取得所有的公共构造方法
getConstructor(Class<?>... parameterTypes) :根据指定的参数类型取得所有的构造方法

public class ReflectionTest {public static void main(String[] args) {Constructor<?>[] cons = DemoClass.class.getConstructors();for (Constructor<?> a: cons) {System.out.println(a);}Constructor<?>[] cons2 = DemoClass.class.getDeclaredConstructors();for (Constructor<?> a: cons2) {System.out.println("DeclaredConstructors:"+a);}try {Constructor<?>cons3 = DemoClass.class.getConstructor(int.class);Constructor<?>cons4 = DemoClass.class.getDeclaredConstructor(String.class);System.out.println("Constructor:"+cons3);System.out.println("DeclaredConstructor:"+cons4);//可以用Constructor对象的newInstance方法来调用类的构造方法System.out.println("class instance:"+cons4.newInstance("Jim"));} catch (Exception e) {e.printStackTrace();} }}class DemoClass  extends TestClass{public DemoClass() {}public DemoClass(int a) {age = a;}DemoClass(String b) {name = b;}@Overridepublic String toString() {return "name="+name+";age="+age;}private String name;private int age;}

结果:

public test.reflect.DemoClass(int)
public test.reflect.DemoClass()
DeclaredConstructors:test.reflect.DemoClass(java.lang.String)
DeclaredConstructors:public test.reflect.DemoClass(int)
DeclaredConstructors:public test.reflect.DemoClass()
Constructor:public test.reflect.DemoClass(int)
DeclaredConstructor:test.reflect.DemoClass(java.lang.String)
class instance:name=Jim;age=0


getModifiers() :取得类的修饰符,以int表示

public class ReflectionTest {public static void main(String[] args) {int modifier = ReflectionTest.class.getModifiers();String m = Modifier.toString(modifier);System.out.println(m);}}

结果:

public


public Class<?>[] getInterfaces():获取实现的接口的Class对象。

public class ReflectionTest {public static void main(String[] args) {Class<?>[] interfaces = ImplementsTest.class.getInterfaces();for (Class i : interfaces) {System.out.println(i);}}}class ImplementsTest implements Serializable, Cloneable {}
输出:

interface java.io.Serializable
interface java.lang.Cloneable

如果是一个接口的Class对象,则返回它的父类接口

public class ReflectionTest {public static void main(String[] args) {Class<?>[] interfaces = A.class.getInterfaces();for (Class i : interfaces) {System.out.println(i);}}}interface A extends B{}interface B{}
输出:
interface com.reflect.test.B


public String getName():得到对象的全路径名
public String getSimpleName():得到对象的简单类名

System.out.println(ArrayList.class.getName());System.out.println(ArrayList.class.getSimpleName());
输出:
java.util.ArrayList
ArrayList

public Class<? super T> getSuperclass():返回父Class对象

public class ReflectionTest {public static void main(String[] args) {Class<? super A> superClass = A.class.getSuperclass();System.out.println(superClass);}}class A extends B{}class B{}
输出:
class com.reflect.test.B


isPrimitive():判断是否是基本类型

System.out.println(Integer.class.isPrimitive());System.out.println(int.class.isPrimitive());
输出:

false
true

public boolean isAssignableFrom(Class<?> cls):判断Class对象是否是给定的Class对象的父类/父接口或者和它类型一致。

当前Class对象是给定的Class对象的父类:

public class ReflectionTest {public static void main(String[] args) {System.out.println(SuperClass.class.isAssignableFrom(SubClass.class));}}class SubClass extends SuperClass{}class SuperClass {}
结果:true


当前Class对象是给定的Class对象的父接口:

System.out.println(List.class.isAssignableFrom(ArrayList.class));
结果:true
当前Class对象和给定的Class对象类型一致:

System.out.println(ArrayList.class.isAssignableFrom(ArrayList.class));
结果:true


getDeclaredField(String name) :返回指定的field对象
getDeclaredFields() :返回所有field对象

getField(String name) :返回指定的公共field对象

getFields() :返回公共的field对象

这几个方法往往和Field类的方法配合使用,在下面Filed类使用中介绍

getMethod(String name, Class<?>... parameterTypes) :根据指定的方法名称和参数类型返回公共方法的Method对象

getMethods() :返回类的所有公共方法的Method对象

getDeclaredMethod(String name, Class<?>... parameterTypes) :根据指定的方法名称和参数类型返回所有方法的Method对象
getDeclaredMethods() :返回类的所有方法的Method对象

这几个方法往往和Method类的方法配合使用,在下面Method类使用中介绍


二.java.lang.reflect.Field:

Field对象封装了Java类中的属性的信息,Class类中获得Field对象的方法有以下几种:

getDeclaredField(String name) :返回指定的field对象
getDeclaredFields() :返回所有field对象
getField(String name) :返回指定的公共field对象
getFields() :返回公共的field对象

测试JavaBean:

public class TestBean {private String name;private String code;private long id;private int num;public int pubSum;public List<String> list;public Map<String, Integer> map;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public long getId() {return id;}public void setId(long id) {this.id = id;}public int getNum() {return num;}public void setNum(int num) {this.num = num;}public int getPubSum() {return pubSum;}public void setPubSum(int pubSum) {this.pubSum = pubSum;}public List<String> getList() {return list;}public void setList(List<String> list) {this.list = list;}public Map<String, Integer> getMap() {return map;}public void setMap(Map<String, Integer> map) {this.map = map;}}
反射代码:

System.out.println("======返回公共的field对象=========");Field[] fields = TestBean.class.getFields();for (Field f : fields) {System.out.println(f);}System.out.println("======返回指定的公共field对象=========");try {Field field = TestBean.class.getField("pubSum");System.out.println(field);} catch (SecurityException e) {e.printStackTrace();} catch (NoSuchFieldException e) {e.printStackTrace();}System.out.println("======返回所有field对象=========");Field[] declaredFields = TestBean.class.getDeclaredFields();for (Field f : declaredFields) {System.out.println(f);}System.out.println("======返回指定的field对象=========");try {Field declaredField = TestBean.class.getDeclaredField("num");System.out.println(declaredField);} catch (SecurityException e) {e.printStackTrace();} catch (NoSuchFieldException e) {e.printStackTrace();}
输出:

======返回公共的field对象=========
public int com.test.reflect.TestBean.pubSum
public java.util.List com.test.reflect.TestBean.list
public java.util.Map com.test.reflect.TestBean.map
======返回指定的公共field对象=========
public int com.test.reflect.TestBean.pubSum
======返回所有field对象=========
private java.lang.String com.test.reflect.TestBean.name
private java.lang.String com.test.reflect.TestBean.code
private long com.test.reflect.TestBean.id
private int com.test.reflect.TestBean.num
public int com.test.reflect.TestBean.pubSum
public java.util.List com.test.reflect.TestBean.list
public java.util.Map com.test.reflect.TestBean.map
======返回指定的field对象=========

private int com.test.reflect.TestBean.num

public Object get(Object obj) throws IllegalArgumentException,IllegalAccessException:返回指定field的值。

TestBean t = new TestBean();t.setCode("code1");t.setName("name1");t.setId(12000000000L);t.setNum(29);try {Field nameField = TestBean.class.getDeclaredField("name");//不设置setAccessible会抛出java.lang.IllegalAccessExceptionnameField.setAccessible(true);System.out.println(nameField.get(t));} catch (Exception e) {e.printStackTrace();}
输出:name1

也可以在已知属性类型的情况下采用更具体的get方法获取值:

TestBean t = new TestBean();t.setCode("code1");t.setName("name1");t.setId(12000000000L);t.setNum(29);try {Field idField = TestBean.class.getDeclaredField("id");idField.setAccessible(true);System.out.println(idField.getLong(t));System.out.println((idField.getLong(t) + 1));} catch (Exception e) {e.printStackTrace();}
输出:
12000000000
12000000001
类似的方法还有:getBoolean,getByte,getChar,getDouble,getFloat,getInt,getLong

public Class<?> getType():返回代表Field类型的Class 对象。

Field idField = TestBean.class.getDeclaredField("id");Class<?> cls = idField.getType();System.out.println(cls.isPrimitive());
输出:true。

public Type getGenericType():获取属性的泛型参数

Field idField = TestBean.class.getDeclaredField("list");ParameterizedType type = (ParameterizedType) idField.getGenericType();System.out.println(type.getActualTypeArguments()[0]);
输出:
class java.lang.String

Field idField = TestBean.class.getDeclaredField("map");ParameterizedType type = (ParameterizedType) idField.getGenericType();System.out.println(type.getActualTypeArguments()[0]);System.out.println(type.getActualTypeArguments()[1]);
输出:

class java.lang.String
class java.lang.Integer

public void set(Object obj,Object value)throws IllegalArgumentException, IllegalAccessException:给属性赋值:

TestBean t = new TestBean();Field idField = TestBean.class.getDeclaredField("num");try {idField.setAccessible(true);idField.set(t, 99);System.out.println(t.getNum());} catch (IllegalArgumentException | IllegalAccessException e) {e.printStackTrace();}
输出:99


三.java.lang.reflect.Method

Method类封装一个类或者接口中的方法的信息。

Class类中获得Method对象的几种方法。

getMethod(String name, Class<?>... parameterTypes) :根据指定的方法名称和参数类型返回公共方法的Method对象
getMethods() :返回类的所有公共方法(包括父类)的Method对象
getDeclaredMethod(String name, Class<?>... parameterTypes) :根据指定的方法名称和参数类型返回所有方法的Method对象
getDeclaredMethods() :返回类的所有方法的Method对象

public class TestReflection {public static void main(String[] args) throws Exception {System.out.println("======返回类的所有公共方法(包括父类的方法)的Method对象=========");Method[] methods = TestMethodClass.class.getMethods();for (Method m : methods) {System.out.println(m);}System.out.println("======返回类的所有方法的(不包括父类的方法)的Method对象=========");Method[] declaredMethods = TestMethodClass.class.getDeclaredMethods();for (Method m : declaredMethods) {System.out.println(m);}System.out.println("======根据指定的方法名称和参数类型返回公共方法的Method对象=========");Method m = TestMethodClass.class.getMethod("setName", String.class);System.out.println(m);System.out.println("======根据指定的方法名称和参数类型返回所有方法的Method对象=========");Method dm = TestMethodClass.class.getMethod("setName", String.class);System.out.println(dm);}}class TestMethodClass {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}}
输出:

======返回类的所有公共方法(包括父类的方法)的Method对象=========
public java.lang.String com.test.reflect.TestMethodClass.getName()
public void com.test.reflect.TestMethodClass.setName(java.lang.String)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
======返回类的所有方法的(不包括父类的方法)的Method对象=========
public java.lang.String com.test.reflect.TestMethodClass.getName()
public void com.test.reflect.TestMethodClass.setName(java.lang.String)
======根据指定的方法名称和参数类型返回公共方法的Method对象=========
public void com.test.reflect.TestMethodClass.setName(java.lang.String)
======根据指定的方法名称和参数类型返回所有方法的Method对象=========
public void com.test.reflect.TestMethodClass.setName(java.lang.String)


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

Method类最重要的一个方法:执行Method对象代表的方法。

参数1:需要执行此方法的对象实例。如果这个方法是静态的,这个参数传null

参数2:调用这个方法需要传入的参数

public class TestReflection {public static void main(String[] args) throws Exception {TestMethodClass cls = new TestMethodClass();System.out.println("调用非静态方法:");Method method = TestMethodClass.class.getMethod("setName", String.class);method.invoke(cls, "xiaoming");System.out.println(cls.getName());System.out.println("调用静态方法:");Method method2 = TestMethodClass.class.getMethod("print", String.class);method2.invoke(null, "xiaoming");}}class TestMethodClass {private String name;public static void print(String args) {System.out.println("static method input:"+ args);}public String getName() {return name;}public void setName(String name) {this.name = name;}}
输出:

调用非静态方法:
xiaoming
调用静态方法:
static method input:xiaoming

原创粉丝点击