我的Java反射学习笔记

来源:互联网 发布:淘宝如何上架宝贝 编辑:程序博客网 时间:2024/05/29 02:49

Class篇

 

一,得到Class对象的几个方法:

1,对象的getClass()方法。仅限引用类型。

比如:Class c = "这是一个字符串".getClass();

枚举实例使用getClass()方法得到的是枚举的class。

2,类的.class语法。引用类型和基本类型都使用。
比如:
Integer.class.newInstance();

int.class.newInstance();

3,Class.forName(),使用完整类路径得到class。

比如:

Class<?>c = Class.forName("java.lang.String");

Class<?>aClass = Class.forName("dynamic.proxy.ProxyTest");

4,静态属性 TYPE。适用于基本类型和 void 的包装类。

比如:

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;

5,返回class的方法。在已经有一个Class,可以获取相关Class。

比如:

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

0 0
原创粉丝点击