我的Java反射学习笔记
来源:互联网 发布:淘宝如何上架宝贝 编辑:程序博客网 时间:2024/05/29 02:49
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
- 我的Java反射学习笔记
- 我的java学习笔记(12)关于反射(part 1)
- 我的java学习笔记(13)关于反射(part 2)
- 我的java学习笔记(14)关于反射(part 3)
- 【我的Java笔记】Java反射
- Java 反射学习笔记
- Java反射学习笔记
- java反射学习笔记
- Java反射学习笔记
- Java 反射学习笔记
- Java反射学习笔记
- Java学习笔记----反射
- Java反射学习笔记
- Java反射学习笔记
- Java反射学习笔记
- JAVA反射学习笔记
- 反射java学习笔记
- JAVA 反射学习笔记
- 欧几里德与扩展欧几里德算法
- 勾股定理问题
- opencv图像增强demo
- 关于月亮双鱼,早已超越弱与强。
- 学习记录 用C#.net 加 asp.net发送带附件邮件
- 我的Java反射学习笔记
- mybatis There is no getter for property named 'xx' in 'class
- sdnuoj 1330
- 基于linux的shell命令行
- 有关程序员的段子③
- 到底什么才是用户体验度
- 而立之年——三线城市程序员的年终告白 转载自铭毅天下
- Java读取UTF-8格式txt文件第一行出现乱码——问号“?”及解决;Java读带有BOM的UTF-8文件乱码原因及解决方法
- EditText在光标处插入