Class篇
一,得到Class对象的几个方法:
1,对象的getClass()方法。仅限引用类型。2,类的.class语法。引用类型和基本类型都使用。比如:Class c = "这是一个字符串".getClass();
枚举实例使用getClass()方法得到的是枚举的class。
比如:3,Class.forName(),使用完整类路径得到class。
Integer.class.newInstance();int.class.newInstance();
4,静态属性 TYPE。适用于基本类型和 void 的包装类。比如:
Class<?>c = Class.forName("java.lang.String");
Class<?>aClass = Class.forName("dynamic.proxy.ProxyTest");
5,返回class的方法。在已经有一个Class,可以获取相关Class。比如:
public static final Class<Double> TYPE = (Class<Double>) double[].class.getComponentType();
Class<Integer>integerWrapper = Integer.TYPE;
Class<Double>doubleWrapper = Double.TYPE;
Class<Void>voidWrapper = Void.TYPE;
比如:
Class.getSuperclass() 返回调用类的父类
Class.getClasses() 返回调用类的所有公共类、接口、枚举组成的Class 数组,包括继承的
Class.getDeclaredClasses() 返回调用类显式声明的所有类、接口、枚举组成的Class 数组
Class.getDeclaringClass()
java.lang.reflect.Field.getDeclaringClass()
java.lang.reflect.Method.getDeclaringClass()
java.lang.reflect.Constructor.getDeclaringClass() 返回类/属性/方法/构造器所在的类
二,Modifier,修饰符。java.lang.reflect.Modifier
可以修饰Class,Field,Method等的修饰符有:
访问权限控制符:public, protected, private
抽象的、需要实现的:abstract
限制只能有一个实例的:static
不允许修改的:final
线程同步锁:synchronized
原生函数:native
采用严格的浮点精度:strictfp
接口
注解
使用方式,以class为例:
intm=Class.getModifiers();//这是类的修饰符二进制值
String mStr= Modifier.toString(m);//这是人能看懂的修饰符
如果一个Class是这样定义的:public static ClassTest{}
那么修饰符就是public static
三,Member,Class的成员
Member是一个接口,java.lang.reflect.Member ,代表Class的成员,有三个实现,分别代表 构造函数,成员变量和成员方法:
java.lang.reflect.Constructor:表示该 Class 的构造函数
java.lang.reflect.Field:表示该 Class 的成员变量
java.lang.reflect.Method:表示该 Class 的成员方法
由Class得到构造函数的方法有:
getConstructor()
getConstructors()
getDeclaredConstructor()
getDeclaredConstructors()
他们的区别大概是这样的:
API | 得到构造数 | 得到全部构造 | 得到父类构造 | 返回值 |
getConstructor() | 1个,需要参数,得到指定构造 | 仅public | 不能 | Constructor<T> |
getConstructors() | 多个 | 仅public | 不能 | Constructor<?>[] |
getDeclaredConstructor() | 1个,需要参数,得到指定构造 | 全部 | 不能 | Constructor<T> |
getDeclaredConstructors() | 多个 | 全部 | 不能 | Constructor<?>[] |
由Class得到成员变量的方法有:
getField()
getFields()
getDeclaredField()
getDeclaredFields()
他们的区别大概是这样的:
API | 得到变量数 | 得到全部变量 | 得到基类变量 | 得到父类变量 | 返回值 |
getField() | 1个,需要参数,得到指定变量 | 仅public | 可以 | 可以得到父类public变量 | Field |
getFields() | 多个 | 仅public | 可以 | 可以得到父类public变量 | Field[] |
getDeclaredField() | 1个,需要参数,得到指定变量 | 全部 | 不能 | 不能 | Field |
getDeclaredFields() | 多个 | 全部 | 不能 | 不能 | Field[] |
由Class得到成员方法的方法有:
getMethod()
getMethods()
getDeclaredMethod()
getDeclaredMethods()
他们的区别大概是这样的:
API | 得到方法数 | 得到全部方法 | 得到父类方法 | 返回值 |
getMethod() | 1个,需要参数,得到指定方法 | 仅public | 可以得到父类public方法 | Method |
getMethods() | 多个 | 仅public | 可以得到父类public方法 | Method[] |
getDeclaredMethod() | 1个,需要参数,得到指定方法 | 全部 | 不能 | Method |
getDeclaredMethods() | 多个 | 全部 | 不能 | Method[] |
上面几组方法区别的方式基本一样,除了得到的构造都不能得到父类构造之外。
一般不建议访问类中的私有成员,成员设置为私有就是不打算让别人访问的,强行访问私有成员可能会导致问题。
Field篇
一,获取变量类型
获取变量类型的方法:
Field.getType()
Field.getGenericType()
getType().getCanonicalName()
他们三个的区别:
1,返回的类型不一样
getType()返回属性声明类型的Class对象。
getType().getCanonicalName()返回String,是声明类型的底层类规范化名称。
getGenericType()返回Type接口。
2,如果属性是一个泛型
从getType()只能得到这个属性的接口类型。
getType().getCanonicalName()得到类型的规范化名称但不包含泛型的内容。
从getGenericType()还能得到这个泛型的参数类型。
二,相关的一些方法
1,得到变量名
field.getName()
2,得到变量类型
Field.getType()
3,得到变量标识符
Modifier.toString(field.getModifiers())
4,设置变量值
field.setLong(shixin, 123456)
第一个参数是成员变量所属的对象,第二个参数是要设置的值。
这里的setLong或者setInt与变量本身的类型有关,写错了会报异常。
三,测试用一些方法用的代码:
package field;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
public class People {
public long idCarNumber = 1000000000;
public String[] name = {"shi", "xin"};
public List<String> list;
public static ArrayList<String> list2;
public static void main(String[] args) {
People shixin = new People();
Class<? extends People> cls = shixin.getClass();
try {
Field idCarNumber = cls.getDeclaredField("idCarNumber");
Field name = cls.getDeclaredField("name");
Field list = cls.getDeclaredField("list");
Field list2 = cls.getDeclaredField("list2");
System.out.println(idCarNumber.getType());
System.out.println(idCarNumber.getGenericType());
System.out.println(idCarNumber.getName());
System.out.println(idCarNumber.getLong(shixin));
idCarNumber.setLong(shixin, 123456);
System.out.println("-----------------------------");
System.out.println(name.getType());
System.out.println(name.getType().getCanonicalName());
System.out.println(name.getGenericType());
System.out.println("-----------------------------");
System.out.println(list.getType());
System.out.println(list.getType().getCanonicalName());
System.out.println(list.getGenericType());
System.out.println("-----------------------------");
System.out.println(list2.getType());
System.out.println(list2.getType().getCanonicalName());
System.out.println(list2.getGenericType());
System.out.println("-----------------------------");
System.out.println(list2.getModifiers());
System.out.println(Modifier.toString(list2.getModifiers()));
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出的结果是:
long
long
idCarNumber
1000000000
-----------------------------
class [Ljava.lang.String;
java.lang.String[]
class [Ljava.lang.String;
-----------------------------
interface java.util.List
java.util.List
java.util.List<java.lang.String>
-----------------------------
class java.util.ArrayList
java.util.ArrayList
java.util.ArrayList<java.lang.String>
-----------------------------
9
public static
四,测试getFields()和getDeclaredFields()区别的代码:
package field;
import java.lang.reflect.Field;
public class FieldTest {
public static void main(String[] args) {
testFields();
}
public static void testFields() {
try {
System.out.println("Declared fields: ");
Field[] fields = Dog.class.getDeclaredFields();
for(int i = 0; i < fields.length; i++) {
System.out.println(fields[i].getName()); // 此处结果是color, name, type, fur
}
System.out.println("----------------------------");
System.out.println("Public fields: ");
fields = Dog.class.getFields();
for(int i = 0; i < fields.length; i++) {
System.out.println(fields[i].getName()); // 此处结果是color, location
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Dog extends Animal {
public int color;
protected int name;
private int type;
int fur;
}
class Animal {
public int location;
protected int age;
private int height;
int length;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
输出的结果是:
Declared fields:
color
name
type
fur
----------------------------
Public fields:
color
location
Method篇
一,相关的一些方法:
1,获得方法名,只有名字
method.getName()
2,获得方法全部信息,包括修饰符、返回值、路径、名称、参数、抛出值等
method.toGenericString()
3,获得修饰符
Modifier.toString(method.getModifiers())
4,获得返回值,不包括泛型
method.getReturnType()
如果方法定义是public List<String> testMethod()
那么getReturnType()就是interface java.util.List
该方法返回值是Class类型
5,获得返回值的完整信息,包括泛型
method.getGenericReturnType()
如果方法定义是ArrayList<String> testMethod2()
那么getGenericReturnType()就是java.util.ArrayList<java.lang.String>
该方法返回值是Type类型
5,获得参数类型,不包括泛型
getParameterTypes()
该方法返回值是Class[]类型。
6,获得参数完整类型,包括泛型
method.getGenericParameterTypes()
该方法返回值是Type[]类型
7,获得异常类型
method.getExceptionTypes()
8,获得异常完整类型
method.getGenericExceptionTypes()
9,获得注解
method.getAnnotations()
得到的结果是这样的:@java.lang.Deprecated()
10,获得注解类型
Annotation[]annotations = method.getAnnotations();
annotations[0].annotationType();
得到的结果是这样的:interface java.lang.Deprecated
11,判断是否是合成方法
method.isSynthetic()
合成方法是由编译器引入的方法,在源代码中不出现,在class文件中能看到,当内部类与外部类之前有互相访问 private 属性、方法时,编译器会在运行时为调用方创建一个 synthetic 方法
12,判断方法是否有可变参数
isVarArgs()
可变参数是这样的:public void testVarargs(String...strings)
一个方法的可变参数必须放在参数列表的最后面,所以一个方法最多只能有一个可变参数
调用方法时,可变参数可以传入一个数组或者分成多个参数
13,判断方法是否是桥接方法
method.isBridge()
桥接方法由编译器自动生成,参数、返回值都是 Object,然后调用实际泛型方法。
为了与jdk1.5之前没有泛型的代码兼容,java代码在编译时会把泛型去除,这个称之为“泛型擦除”
桥接方法实现了将泛型生成的字节码与 1.5 以前的字节码进行兼容。
14,调用反射出来的method方法
method.invoke()
使用方法:
public native Object invoke(Objectreceiver, Object... args)
throws IllegalAccessException,IllegalArgumentException, InvocationTargetException;
第一个参数是方法属于的对象(如果是静态方法,则可以直接传 null)
第二个可变参数是该方法的参数
如果调用的方法有抛出异常,异常会被 java.lang.reflect.InvocationTargetException 包一层
二,测试一些方法用的代码:
package method;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
public class MethodInvoke {
private boolean checkString(String s) {
System.out.format("checkString: %s\n", s);
return false;
}
private static void saySomething(String something) {
System.out.println(something);
}
private String onEvent(TestEvent event) {
System.out.format("Event name: ", event.getEventName());
return event.getResult();
}
static class TestEvent {
private String eventName;
private String result;
public TestEvent(String eventName, String result) {
this.eventName = eventName;
this.result = result;
}
public String getResult() {
return result;
}
public String getEventName() {
return eventName;
}
}
public static void main(String[] args) {
try {
Class<?> cls = Class.forName("method.MethodInvoke");
MethodInvoke object = (MethodInvoke) cls.newInstance();
Method[] declaredMethods = cls.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
String methodName = declaredMethod.getName(); //获取方法名
Type returnType = declaredMethod.getGenericReturnType(); //获取带泛型的返回值类型
int modifiers = declaredMethod.getModifiers(); //获取方法修饰符
System.out.println("methodName:"+methodName);
if (methodName.equals("onEvent")) {
TestEvent testEvent = new TestEvent("shixin's Event", "cuteType");
try {
Object invokeResult = declaredMethod.invoke(object, testEvent);
System.out.format("Invoke of %s, return %s \n", methodName, invokeResult.toString());
} catch (InvocationTargetException e) { //处理被调用方法可能抛出的异常
Throwable cause = e.getCause();
System.out.format("Invocation of %s failed: %s\n", methodName, cause.getMessage());
}
} else if (returnType == boolean.class) {
try {
declaredMethod.invoke(object, "shixin's parameter");
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
System.out.format("Invocation of %s failed: %s\n", methodName, cause.getMessage());
}
}else if (Modifier.isStatic(modifiers) && !methodName.equals("main")){ //静态方法,调用时 object 直接传入 null
try {
declaredMethod.invoke(null, "static method");
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
System.out.format("Invocation of %s failed: %s\n", methodName, cause.getMessage());
}
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
输出是这样的:
methodName:main
methodName:checkString
checkString: shixin's parameter
methodName:saySomething
static method
methodName:onEvent
Event name: Invoke of onEvent, return cuteType
三,写着玩的,按类的名字获取方法然后调用这些方法
package method;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MtehodTest {
public static class Test{
private int id;
private String code;
private Date time;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
}
/**
* 调用set方法,给对象赋值
*/
public static void main(String[] args) {
String[] input={"123","abc","2017-01-23 01:02:34"};//用来赋值的列表
String[] fields={"id","code","time"};//对象属性列表,和用来赋值的列表对应
try{
Test atest=Test.class.newInstance();
Method[] methods=atest.getClass().getDeclaredMethods();
for(int i=0;i<methods.length;i++){
Method method=methods[i];
System.out.println(Modifier.toString(method.getModifiers()));
System.out.println(method.getGenericReturnType());
String methodName=method.getName();
System.out.println(methodName);
if(method.getName().startsWith("set")){ //如果扫到的是set方法,就调用这个方法,给对象赋值
for(int fieldsIndex=0;fieldsIndex<fields.length;fieldsIndex++){
if(methodName.toLowerCase().endsWith(fields[fieldsIndex])){
System.out.println(method.getParameterTypes()[0]);
if(method.getParameterTypes()[0].equals(Date.class)){ //参数不同,赋值的方式也不同
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
method.invoke(atest, sdf.parse(input[fieldsIndex]));
}else if (method.getParameterTypes()[0].equals(int.class)){
method.invoke(atest, Integer.parseInt(input[fieldsIndex]));
}else{
method.invoke(atest, input[fieldsIndex]);
}
}
}
}
System.out.println("-----------------");
}
System.out.println("========================");
System.out.println(atest.getId());//查看赋值的结果
System.out.println(atest.getCode());
System.out.println(atest.getTime());
}catch(Exception e){
e.printStackTrace();
}
}
}
输出的结果是这样的:
public
int
getId
-----------------
public
class java.lang.String
getCode
-----------------
public
class java.util.Date
getTime
-----------------
public
void
setId
int
-----------------
public
void
setTime
class java.util.Date
-----------------
public
void
setCode
class java.lang.String
-----------------
========================
123
abc
Mon Jan 23 01:02:34 CST 2017