Java反射机制小结
2015-06-21 14:49
405 查看
要了解Java反射机制,前提是搞清楚Class类(Class类型)怎么理解?翻阅了一些资料,Class类(Class类型)是定义Java程序中一个特定类的实现,Class类(Class类型)的对象(实例)用于表示当前运行的Java应用程序中的类和接口。
举个栗子,张三、李四等,可以用Person来描述
Person就是张三、李四(是Person的对象)的类型,引申出Date、String类又是什么类型呢?Class类型。二者作为对比:
Person类代表人,它的实例对象就是张三、李四这样一个个具体的人
Class类代表Java类,它的实例对象对应各个类在内存中(JVM中)的字节码。例如,Person类的字节码,ArrayList类的字节码,等等。一个类被类加载器加载到内存中,占用一片存储空间。这个空间里面的内容就是类的字节码。不同的类的字节码是不同的,所以它们在内存中的内容是不同的。一个类在虚拟机中只有一份字节码。
问题1:Class类的实例到底表示的是哪一份字节码,为了明确区分出Class类的实例表示的是谁的字节码,Class类提供了泛型
Class<Date> clz1 = Date.class; //clz1表示Date的字节码
Class<String> clz2 = String.class; //clz2表示String的字节码
问题2:如何得到Class类的实例,有三种方式,其中2、3用的较多
1.类名.class(就是一份字节码);
2.Class.forName(String className);//根据一个类的全限定名来构建Class对象,那么就能得到这个类的父类、属性、方法等
3.每一个对象都有getClass()方法: obj.getClass(); 返回对象的真实类型,即编译类型,突然间想起某人和我说的一句话,“编译时决定类型,运行时绑定对象”,哈哈^^
打印结果:
class test.cd.User
class test.cd.User
class test.cd.User
clz1 == clz2 : true
clz1 == clz3 : true
clz2 == clz3 : true
true
sun.misc.Launcher$AppClassLoader@53004901
sun.misc.Launcher$AppClassLoader@53004901
从打印结果可知,一个类在JVM中只有一份字节码(User.class)。
问题3:如果我想获取某一个类中所有的构造器(当然也可以是类中所有的属性或方法等)呢?应该怎么做?
1.明确知道操作的是哪一份字节码对象,即哪个Class类的实例
2.获取构造器
在实践过程中发现会涉及Constructor类:表示类中构造器的类型,Constructor的实例就是某一个类中的某一个构造器,此外还有Method类,Field类,分别表示类中方法的类型和字段的类型,Method的实例就是某一个类中的某一个方法,Field的实例就是某一个类中的某一个字段。
问题4:请用图形象画出Class类的实例在内存中的情况
我们可以把每个Class类的对象当做众多类的代理。而且在每个Class类对象中都会有字段记录他引用的这个类的类加载器。java中有多个加载器,每个加载器能载入多个类,所以只要取得Class类对象,就可利用其getClassLoader()方法取得该类加载器的引用。JVM为每种类管理着独一的Class对象。因此我们可以用双等号操作符来比较对象:a1.getClass()==A.class;应该返回的是true。
![](http://img.blog.csdn.net/20150622105748396?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYmVpYmVpMDkyMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://img.blog.csdn.net/20150622105730455?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYmVpYmVpMDkyMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
问题5:Class类中都有一些什么方法?
举个栗子,张三、李四等,可以用Person来描述
class Person{ //张三和李四共同具备的行为和状态 }
Person就是张三、李四(是Person的对象)的类型,引申出Date、String类又是什么类型呢?Class类型。二者作为对比:
Person类代表人,它的实例对象就是张三、李四这样一个个具体的人
Class类代表Java类,它的实例对象对应各个类在内存中(JVM中)的字节码。例如,Person类的字节码,ArrayList类的字节码,等等。一个类被类加载器加载到内存中,占用一片存储空间。这个空间里面的内容就是类的字节码。不同的类的字节码是不同的,所以它们在内存中的内容是不同的。一个类在虚拟机中只有一份字节码。
问题1:Class类的实例到底表示的是哪一份字节码,为了明确区分出Class类的实例表示的是谁的字节码,Class类提供了泛型
Class<Date> clz1 = Date.class; //clz1表示Date的字节码
Class<String> clz2 = String.class; //clz2表示String的字节码
问题2:如何得到Class类的实例,有三种方式,其中2、3用的较多
1.类名.class(就是一份字节码);
2.Class.forName(String className);//根据一个类的全限定名来构建Class对象,那么就能得到这个类的父类、属性、方法等
3.每一个对象都有getClass()方法: obj.getClass(); 返回对象的真实类型,即编译类型,突然间想起某人和我说的一句话,“编译时决定类型,运行时绑定对象”,哈哈^^
package test.cd; /** * @author quyang.ybb * */ public class User { }
package test.cd.clazz; import test.cd.User; /** * @author quyang.ybb * */ public class ClassInstanceDemo { public static void main(String[] args) throws Exception { // 第一种方式:类名.class; Class<User> clz1 = User.class; System.out.println(clz1); // 第二种方式:Class.forName(String className); // 用?表示是因为后面是字符串,clz2并不知道自己表示的是谁 Class<?> clz2 = Class.forName("test.cd.User"); System.out.println(clz2); // 第三种方式:对象.getClass(); User user = new User(); Class clz3 = (Class) user.getClass(); System.out.println(clz3); System.out.println("clz1 == clz2 : " + (clz1 == clz2)); System.out.println("clz1 == clz3 : " + (clz1 == clz3)); System.out.println("clz2 == clz3 : " + (clz2 == clz3)); User user11 = new User(); Class clz11 = user11.getClass(); User user22 = new User(); Class clz22 = user22.getClass(); System.out.println(clz11==clz22); System.out.println(clz11.getClassLoader()); System.out.println(clz22.getClassLoader()); } }
打印结果:
class test.cd.User
class test.cd.User
class test.cd.User
clz1 == clz2 : true
clz1 == clz3 : true
clz2 == clz3 : true
true
sun.misc.Launcher$AppClassLoader@53004901
sun.misc.Launcher$AppClassLoader@53004901
从打印结果可知,一个类在JVM中只有一份字节码(User.class)。
问题3:如果我想获取某一个类中所有的构造器(当然也可以是类中所有的属性或方法等)呢?应该怎么做?
1.明确知道操作的是哪一份字节码对象,即哪个Class类的实例
2.获取构造器
在实践过程中发现会涉及Constructor类:表示类中构造器的类型,Constructor的实例就是某一个类中的某一个构造器,此外还有Method类,Field类,分别表示类中方法的类型和字段的类型,Method的实例就是某一个类中的某一个方法,Field的实例就是某一个类中的某一个字段。
问题4:请用图形象画出Class类的实例在内存中的情况
我们可以把每个Class类的对象当做众多类的代理。而且在每个Class类对象中都会有字段记录他引用的这个类的类加载器。java中有多个加载器,每个加载器能载入多个类,所以只要取得Class类对象,就可利用其getClassLoader()方法取得该类加载器的引用。JVM为每种类管理着独一的Class对象。因此我们可以用双等号操作符来比较对象:a1.getClass()==A.class;应该返回的是true。
问题5:Class类中都有一些什么方法?
getClassLoader() //获取该类的类装载器。 getComponentType() //如果当前类表示一个数组,则返回表示该数组组件的 Class 对象,否则返回 null。 getConstructor(Class[]) //返回当前 Class 对象表示的类的指定的公有构造子对象。 getConstructors() //返回当前 Class 对象表示的类的所有公有构造子对象数组。 getDeclaredConstructor(Class[]) //返回当前 Class 对象表示的类的指定已说明的一个构造子对象。 getDeclaredConstructors() //返回当前 Class 对象表示的类的所有已说明的构造子对象数组。 getDeclaredField(String) //返回当前 Class 对象表示的类或接口的指定已说明的一个域对象。 getDeclaredFields() //返回当前 Class 对象表示的类或接口的所有已说明的域对象数组。 getDeclaredMethod(String, Class[]) //返回当前 Class 对象表示的类或接口的指定已说明的一个方法对象。 getDeclaredMethods() //返回 Class 对象表示的类或接口的所有已说明的方法数组。 getField(String) //返回当前 Class 对象表示的类或接口的指定的公有成员域对象。 getFields() //返回当前 Class 对象表示的类或接口的所有可访问的公有域对象数组。 getInterfaces() //返回当前对象表示的类或接口实现的接口。 getMethod(String, Class[]) //返回当前 Class 对象表示的类或接口的指定的公有成员方法对象。 getMethods() //返回当前 Class 对象表示的类或接口的所有公有成员方法对象数组,包括已声明的和从父类继承的方法。 getModifiers() //返回该类或接口的 Java 语言修改器代码。 getName() //返回 Class 对象表示的类型(类、接口、数组或基类型)的完整路径名字符串。 getResource(String) //按指定名查找资源。 getResourceAsStream(String) //用给定名查找资源。 getSigners() //获取类标记。 getSuperclass() //如果此对象表示除 Object 外的任一类, 那么返回此对象的父类对象。 isArray() //如果 Class 对象表示一个数组则返回 true, 否则返回 false。 isAssignableFrom(Class) //判定 Class 对象表示的类或接口是否同参数指定的 Class 表示的类或接口相同,或是其父类。 isInstance(Object) //此方法是 Java 语言 instanceof 操作的动态等价方法。 isInterface() //判定指定的 Class 对象是否表示一个接口类型。 isPrimitive() //判定指定的 Class 对象是否表示一个 Java 的基类型。 newInstance() //创建类的新实例。 toString() //将对象转换为字符串。
相关文章推荐
- 疯狂Java学习笔记(84)----------大约 Java 对象序列化,你不知道 5 事
- Java学习之继承
- JavaBean概念与理解
- Java IO 之 System类
- Java 内部类种类及使用解析
- “找女神要QQ号码”——跟风篇java新手版(求指点)
- Frame与JFrame的区别
- Java.lang.Process需要注意的问题
- Java 初始化顺序
- Java开发之设计模式--单例模式(Singleton Pattern)
- java基础-集合遍历输出的四种方式
- myeclipse中,项目上有个红叉报错,但是文件中一个红叉叉都没有
- JAVA 反射
- Java中如何处理空指针异常
- Java基本数据类型
- windows下eclipse android开发环境的搭建
- java枚举使用详解
- java异常捕获的一点感悟
- Java 什么时候该用static
- 【java设计模式】java 桥接模式