我的Java反射学习笔记

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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值