笔记:Java反射机制基础
来源:互联网 发布:postgresql mysql迁移 编辑:程序博客网 时间:2024/05/16 16:42
反射在百度的解释为“一种计算机处理方式,是程序可以访问、检测和修改它本身状态或行为的一种能力”,即在运行的时候可以分析代码的内容,包括注解的内容,得到需要的信息。就像在常用的IDE如Eclipse中利用了反射实现了获取类的信息。
1.Class
java.lang.Class没有公共的构造方法,因此单独声明一个Class对象是不允许的;每个类型都有一个Class对象,这个Class对象记录了改类型的interface,field,method,annotation,generics等。任何类型,包括基础数据类型(int, short, long, float, double, char, btye, boolean)以及void类型都有对应的Class对象。
package com.test.ReflectTest;/** * @author 王狗蛋 * @date : 2017年8月13日 上午11:42:42 */public class Reflect { public static void main(String...args) throws Exception { // The first method to get a class object // This method will throws ClassNotFoundException Class<String> clz = (Class<String>)Class.forName("java.lang.String"); // The second method to get a class object clz = String.class; // Now let check the attributes of clz System.out.println("The name of clz is " + clz.getName()); System.out.println("Is clz a primitive " + clz.isPrimitive()); // Of course we can check whether an object is specific class System.out.println("Is string is a String " + clz.isInstance("string")); // And there is another method to print info System.out.println(clz.toGenericString()); // Of course we can create an instance String instance = clz.newInstance(); System.out.println(instance instanceof String); }}
输出结果
The name of clz is java.lang.String
Is clz a primitive fase
Is string is a String true
public final class java.lang.String
true
从结果可知,clz的类名为java.lang.String,并且clz不是一个基础类型,“string”字符串是clz的类型,Class这个类是一个public final 类,由于被final修饰,Class在创建之后不会被修改,保证了代理时的安全性
2.interface
接口不能实例化并且包含了所有继承类应包含的所有方法,但接口可以被访问,也可以调用里面的方法。调用方法会在介绍invoke方法的笔记中记录 。
我们都知道String类继承Serializable,Comparable;但String类到底都继承了那些接口呢,我们来下面代码:
/** 这段代码接上述代码 */ Class<?>[] inters = clz.getInterfaces(); for (Class<?> inter: inters) { System.out.println(inter.toGenericString()); }
结果如下:
public abstract interface java.io.Serializable
public abstract interface java.lang.Comparable
public abstract interface java.lang.CharSequence
这三个接口就是String类继承的接口,其中Serializable就是可序列化接口,使得该类型的对象可以通过IO输出;Comparable用于实现俩个对象之间的比较,并通过方法compareTo(T object)来制定比较规则 ;CharSequence是String和AbstractStringBuilder的接口,具体内容在String笔记中介绍(我也不知道这个笔记什么时候整理,一般String和StringBuilder就够用了)
3.Field
域就是类的属性,我们可以通过一个Class对象来获取field
首先我们先弄一个类用来演示:
package com.test.ReflectTest;/** * @author 王狗蛋 * @date : 2017年8月13日 下午12:21:06 */public class DemoClass { public int num1 = 1; protected int num2 = 2; int num3 = 3; private int num4 = 4; public static int num5 = 5````}
然后我们继续在main方法中演示:
import java.lang.reflect.Field;import java.lang.reflect.Modifier; Class<?> clzDemo = Class.forName("com.test.ReflectTest.DemoClass"); Object obj = clzDemo.newInstance(); Field field = clzDemo.getField("num1"); System.out.println(field.toGenericString()); System.out.println(Modifier.toString(field.getModifiers())); System.out.println(field.getType().toGenericString()); field.set(obj, 10); System.out.println(field.get(obj));
输出结果:
public int com.test.ReflectTest.DemoClass.num1
public
int
10
首先先用clzDemo.getFIeid(“field name”)获取了name为”num1”的域
然后field.getModifiers()获取field的修饰类型,但获得的是一个int型对象,需要通过Modifier的静态方法toString(int)来输出;field.getType()获取域的数据类型;通过set方法来修改值并通过get方法获取值;
在set(Object obj, Obejct value)方法中修改对象为obj的域,但num5是一个静态属性,即在内存中只存放一个num5对象,即使创建多个对象,每个对象的num5都是引用内存中那唯一的num5域的值。
所以在set()方法时,如果该域是一个静态的域,那么在传入第一个参数时可以传入空指针null,即set(null,20);这时所有对象的num5都被改为20。
可能你会想这样一个一个域取很麻烦,当然有简单的方法:
Field[] fields = cls.getFields(); for (Field field: fields) { System.out.println(field.toString() + "\t" + field.get(obj)); }
输出结果:
public int com.test.ReflectTest.FieldDemo.num1 1
public static int com.test.ReflectTest.FieldDemo.num5 10
诶,等等,明明有5个域,你怎么就把public的域输出出来了呢?这是因为getFields()方法只会返回public域,对于private protected 和默认类型不会输出,这时我们就需要用到另一个方法getDeclaredFields()
fields = cls.getDeclaredFields(); for (Field field: fields) { //field.setAccessible(true); System.out.println(field.toGenericString() + "\t" + field.get(obj)); }
这时候一定会报一个java.lang.IllegalAccessException异常,这个异常就是说没有访问权限造成的异常,这时把注释掉那行代码加上就不会有问题了,哈哈神奇吧。
输出结果:
public int com.test.ReflectTest.FieldDemo.num1 1
0
protected int com.test.ReflectTest.FieldDemo.num2 2
int com.test.ReflectTest.FieldDemo.num3 3
private int com.test.ReflectTest.FieldDemo.num4 4
public static int com.test.ReflectTest.FieldDemo.num5 5
为什么会这样呢,Accessible = true 会忽略访问权限的限制,具体会在invoke方法介绍的笔记中介绍。
4.Method
方法就是定义在类中的所有方法,构造方法需要用构造调用
import java.lang.reflect.Method;import java.lang.reflect.Parameter;import java.lang.reflect.Modifier; Method[] methods = clz.getMethods(); for (Method method: methods) { System.out.println("-----------------------"); System.out.println("name:" + method.getName()); System.out.print("defaultValue:" + method.getDefaultValue()); System.out.print("generic return type:" + method.getGenericReturnType()); System.out.print("return type:" + method.getReturnType()); System.out.print("modifiers:" + Modifier.toString(method.getModifiers())); // Parameters Parameter[] parameters = method.getParameters(); System.out.print(parameters.length + "parameters:"); for (Parameter para: parameters) { System.out.print("name:" + para.getName()); System.out.print("type:" + para.getType().toString()); } Class<?>[] parameterTypes = method.getParameterTypes(); System.out.print(parameterTypes.length + "parameters:"); for (Class<?> paraType: parameterTypes){ print("parameter smiple name: " + paraType.getSimpleName()); System.out.print("parameter type name: " + paraType.getName()); System.out.print("parameter modifier:" + Modifier.toString(paraType.getModifiers())); System.out.print(paraType.toGenericString()); } Class<?>[] exceptionTypes = method.getExceptionTypes(); System.out.print(exceptionTypes.length + "exception types:"); for (Class<?> exceptionType: exceptionTypes) { System.out.print("exception name: " + exceptionType.getName()); System.out.print("exception simple name: " + exceptionType.getSimpleName()); System.out.print(exceptionType.toGenericString()); } System.out.print("is accessible: " + method.isAccessible()); System.out.print("is varArgs: " + method.isVarArgs()); }
输出结果太多了,就是String类的所有可见方法,只弄一部分结果:
name:equals
defaultValue:null
generic return type:boolean
return type:boolean
modifiers:public
1parameters:
name:arg0
type:class java.lang.Object
1parameters:
parameter smiple name: Object
parameter type name: java.lang.Object
parameter modifier:public
public class java.lang.Object
0exception types:
is accessible: false
is varArgs: false
当然如果你想看不可见的方法,可以调用getDeclaredMethods()方法,
当然在获取一个方法对象后可以通过invoke(Object rescourse, Object…argument)方法调用,具体在invoke笔记中介绍。
6.构造器
我们可以通过类对象来获取该类的构造器
import java.lang.reflect.Constructor; Constructor<?>[] constructors = clz.getConstructors(); for (Constructor<?> constructor: constructors) { System.out.println("constructor " + constructor.getName()); System.out.println("number of parameters: " + constructor.getParameterCount()); System.out.println("modifiers: " + Modifier.toString(constructor.getModifiers())); System.out.println(constructor.toGenericString()); Annotation[] annotaitons = constructor.getAnnotations(); for (Annotation annotation: annotaitons) { System.out.println(annotation.toString()); } System.out.println(); }
输出结果:
constructor java.lang.String
number of parameters: 3
modifiers: public
public java.lang.String(byte[],int,int)
constructor java.lang.String
number of parameters: 2
modifiers: public
public java.lang.String(byte[],java.nio.charset.Charset)
constructor java.lang.String
number of parameters: 2
modifiers: public
public java.lang.String(byte[],java.lang.String) throws java.io.UnsupportedEncodingException
constructor java.lang.String
number of parameters: 4
modifiers: public
public java.lang.String(byte[],int,int,java.nio.charset.Charset)
constructor java.lang.String
number of parameters: 4
modifiers: public
public java.lang.String(byte[],int,int,java.lang.String) throws java.io.UnsupportedEncodingException
constructor java.lang.String
number of parameters: 1
modifiers: public
public java.lang.String(java.lang.StringBuilder)
constructor java.lang.String
number of parameters: 2
modifiers: public
public java.lang.String(byte[],int)
@java.lang.Deprecated()
constructor java.lang.String
number of parameters: 4
modifiers: public
public java.lang.String(byte[],int,int,int)
@java.lang.Deprecated()
我仅仅保留了一部分结果,在代码中我要求输出可见的构造器的名字,参数,修饰类型,构造器的toGenericString(),以及构造器的注解,对于注解的含义在注解介绍笔记详细介绍,从结果看有@Deprecated注解,表示该方法被遗弃,不建议使用。
java反射机制的基础就像介绍在这里,后续将继续通过笔记介绍java反射的invoke,proxy代理等。
第一篇博客如有不足还请见谅,如有原理问题欢迎提出,共同学习。
- java反射机制基础笔记
- 笔记:Java反射机制基础
- Java笔记-反射机制Reflection API(java动态机制)基础
- java反射机制基础
- java基础:反射机制
- JAVA基础--反射机制
- 【JAVA基础】反射机制
- Java反射机制 笔记
- java反射机制笔记
- Java笔记---反射机制
- Java反射机制笔记
- Java反射机制笔记
- Java反射机制笔记
- Java反射机制笔记-反射机制
- 【java基础】Java反射机制
- 【java基础】java反射机制
- java基础学习笔记——反射机制
- 黑马程序员——java基础笔记:反射机制
- MySQL高速缓存---query_cache_size
- 数据库知识(面)
- 读取图片并打印图片
- 二级指针三种内存模型
- 初来乍到
- 笔记:Java反射机制基础
- 深入了解java虚拟机-读书笔记
- Vases and Flowers
- ngrok安装使用
- Codeforces Round #428 (Div. 2) ABCD
- 浅谈算法和数据结构: 八 平衡查找树之2-3树
- 数据结构-二叉排序树
- HDU -- 6113 度度熊的01世界 【搜联通块 + 思维】
- Redis命令