深入理解 Java 反射:Class (反射的入口)
2017-01-22 14:52
246 查看
转载自:http://blog.csdn.net/u011240877/article/details/54604146
深入理解 Java 反射系列:
深入理解 Java 反射:Class (反射的入口)
深入理解 Java 反射:Field (成员变量)
深入理解 Java 反射:Method (成员方法)
读完本文你将了解到:
什么是 Reflection 反射为什么要用它
Java 中 Reflection 和 Introspection 区别
反射的入口javalangClass
得到一个 Class 对象
Class 的修饰符Modifier
Class 的成员Member
获取构造函数
获取成员变量
获取成员方法
Thanks
Java 强类型语言,但是我们在运行时有了解、修改信息的需求,包括类信息、成员信息以及数组信息。
说起反射,还有一个相似的概念 ‘Introspection’,字面意思是“自省、内省”,它们之间的区别如下:
内省
在运行时检查一个对象的类型或者属性
最常见的例子就是运行时通过 a instanceof A 来判断 a 对象的类型
反射
用来在运行时检查或者修改一个对象信息
可以用来实现看似不可能的操作,比如访问私有方法,动态创建对象
可以看到,反射是在内省的基础上,增加了修改的能力。
日常开发中的对象,分为两种,基本类型和引用类型:
基本类型,(固定的 8 种)
整数:byte, short, int, long
小数:float, double
字符:char
布尔值:boolean
引用类型
所有的引用类型都继承自 java.lang.Object
类,枚举,数组,接口都是引用类型
java.io.Serializable 接口,基本类型的包装类(比如 java.lang.Double)也是引用类型
对每一种对象,JVM 都会实例化一个 java.lang.Class 的实例,java.lang.Class 为我们提供了在运行时访问对象的属性和类型信息的能力。Class 还提供了创建新的类和对象的能力。最重要的是,Class 是调用其他反射 API 的入口,我们必须先获得一个 Class 实例才可以进行接下来的操作。
除了 java.lang.reflect.ReflectPermission 以外,java.lang.reflect 中的其他类都没有 public 的构造函数,也就是说要得到这些类,我们必须通过 Class 。
下面是几种得到 Class 对象的不同方法:
1.Object.getClass 方法
如果我们已经拿到了一个对象,可以很方便地使用它的 getClass 方法获得一个 Class 对象(当然这仅限于引用类型的对象):
1
返回的对象 c 是 String 类型。
2
3
4
5
6
1
2
3
4
5
6
上述例子中 FEMALE 是 枚举 Sex 的实例,因此 FEMALE.getClass() 返回的就是 枚举类型 Sex 的 Class。
2
1
2
由于数组也是 Object 的一种,因此我们可以调用 getClass() 方法获得 byte 数组类型的 Class。
2. .class 语法
如果我们当前没有某个类的对象,无法使用 getClass() 方法,那还可以使用另外一种方法获取 Class:在要获得的类名后加上 .class ,比如这样:
2
1
2
可以看到,这种方式不仅能用于引用类型,基本类型也可以。
当然数组也可以喽:
1
3.Class.forName()
如果我们有一个类的完整路径,就可以使用 Class.forName(“类完整的路径”) 来得到相应的 Class,这个方法只能用于引用类型,比如:
2
1
2
4.静态属性 TYPE
上面介绍,使用 .class 后缀可以很方便地获得基本类型的 Class。
对于基本类型和 void 的包装类,还有另外一种方式获得 Class,那就是静态属性 TYPE 。
每个包装类都有 TYPE 属性,以 Double 为例:
2
1
2
可以看到这个属性就是使用 .class 的方式获得 Class 并保存。
因此我们可以直接调用包装类的 TYPE:
2
3
1
2
3
5.返回 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()
返回类/属性/方法/构造器所在的类
一个 Class 可以被以下修饰符的一种或者多种修饰:
访问权限控制符:
抽象的、需要实现的:
限制只能有一个实例的:
不允许修改的:
线程同步锁:
原生函数:
采用严格的浮点精度:
接口
注解
当然上面的修饰符不是所有 Class 都可以修饰,比如:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
注意:
Interface 添加这个修饰符。
只有被
Java 中预定义的注解
和
Member 有三个实现类:
注意:构造函数无法从父类继承
http://docs.oracle.com/javase/tutorial/reflect/TOC.html
http://stackoverflow.com/questions/2044446/java-introspection-and-reflection
http://stormzhang.com/java/2013/07/29/java-reflection/
http://www.infoq.com/cn/articles/cf-java-reflection-dynamic-proxy
https://github.com/JustinSDK/JavaSE6Tutorial/blob/master/docs/CH16.md
深入理解 Java 反射系列:
深入理解 Java 反射:Class (反射的入口)
深入理解 Java 反射:Field (成员变量)
深入理解 Java 反射:Method (成员方法)
读完本文你将了解到:
什么是 Reflection 反射为什么要用它
Java 中 Reflection 和 Introspection 区别
反射的入口javalangClass
得到一个 Class 对象
Class 的修饰符Modifier
Class 的成员Member
获取构造函数
获取成员变量
获取成员方法
Thanks
什么是 Reflection 反射,为什么要用它
Java 强类型语言,但是我们在运行时有了解、修改信息的需求,包括类信息、成员信息以及数组信息。
Java 中 Reflection 和 Introspection 区别?
说起反射,还有一个相似的概念 ‘Introspection’,字面意思是“自省、内省”,它们之间的区别如下:内省
在运行时检查一个对象的类型或者属性
最常见的例子就是运行时通过 a instanceof A 来判断 a 对象的类型
反射
用来在运行时检查或者修改一个对象信息
可以用来实现看似不可能的操作,比如访问私有方法,动态创建对象
可以看到,反射是在内省的基础上,增加了修改的能力。
反射的入口:java.lang.Class
日常开发中的对象,分为两种,基本类型和引用类型:基本类型,(固定的 8 种)
整数:byte, short, int, long
小数:float, double
字符:char
布尔值:boolean
引用类型
所有的引用类型都继承自 java.lang.Object
类,枚举,数组,接口都是引用类型
java.io.Serializable 接口,基本类型的包装类(比如 java.lang.Double)也是引用类型
对每一种对象,JVM 都会实例化一个 java.lang.Class 的实例,java.lang.Class 为我们提供了在运行时访问对象的属性和类型信息的能力。Class 还提供了创建新的类和对象的能力。最重要的是,Class 是调用其他反射 API 的入口,我们必须先获得一个 Class 实例才可以进行接下来的操作。
得到一个 Class 对象
除了 java.lang.reflect.ReflectPermission 以外,java.lang.reflect 中的其他类都没有 public 的构造函数,也就是说要得到这些类,我们必须通过 Class 。下面是几种得到 Class 对象的不同方法:
1.Object.getClass 方法
如果我们已经拿到了一个对象,可以很方便地使用它的 getClass 方法获得一个 Class 对象(当然这仅限于引用类型的对象):
Class c = "shixinzhang.top".getClass();1
1
返回的对象 c 是 String 类型。
enum Sex{ FEMALE, MALE } Class c = FEMALE.getClass();1
2
3
4
5
6
1
2
3
4
5
6
上述例子中 FEMALE 是 枚举 Sex 的实例,因此 FEMALE.getClass() 返回的就是 枚举类型 Sex 的 Class。
byte[] bytes = new byte[1024]; Class<? extends byte[]>c = bytes.getClass();1
2
1
2
由于数组也是 Object 的一种,因此我们可以调用 getClass() 方法获得 byte 数组类型的 Class。
2. .class 语法
如果我们当前没有某个类的对象,无法使用 getClass() 方法,那还可以使用另外一种方法获取 Class:在要获得的类名后加上 .class ,比如这样:
Integer.class.newInstance(); int.class.newInstance()1
2
1
2
可以看到,这种方式不仅能用于引用类型,基本类型也可以。
当然数组也可以喽:
Class b = int[][].class;1
1
3.Class.forName()
如果我们有一个类的完整路径,就可以使用 Class.forName(“类完整的路径”) 来得到相应的 Class,这个方法只能用于引用类型,比如:
Class<?> c = Class.forName("java.lang.String"); Class<?> aClass = Class.forName("top.shixinzhang.androiddemo2.beans.BookBean");1
2
1
2
4.静态属性 TYPE
上面介绍,使用 .class 后缀可以很方便地获得基本类型的 Class。
对于基本类型和 void 的包装类,还有另外一种方式获得 Class,那就是静态属性 TYPE 。
每个包装类都有 TYPE 属性,以 Double 为例:
public static final Class<Double> TYPE = (Class<Double>) double[].class.getComponentType();1
2
1
2
可以看到这个属性就是使用 .class 的方式获得 Class 并保存。
因此我们可以直接调用包装类的 TYPE:
Class<Integer> integerWrapper = Integer.TYPE; Class<Double> doubleWrapper = Double.TYPE; Class<Void> voidWrapper = Void.TYPE;1
2
3
1
2
3
5.返回 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()
返回类/属性/方法/构造器所在的类
Class 的修饰符:Modifier
一个 Class 可以被以下修饰符的一种或者多种修饰:访问权限控制符:
public,
protected,
private
抽象的、需要实现的:
abstract
限制只能有一个实例的:
static
不允许修改的:
final
线程同步锁:
synchronized
原生函数:
native
采用严格的浮点精度:
strictfp
接口
注解
当然上面的修饰符不是所有 Class 都可以修饰,比如:
Interface不能是
final的
enum不能是
abstract的
java.lang.reflect.Modifier提供了对 Class 修饰符的解码,我们可以使用
Class.getModifiers()获得调用类的修饰符的二进制值,然后使用
Modifier.toString(int modifiers)将二进制值转换为字符串,
Modifier.toString()方法实现如下:
public static java.lang.String toString(int modifiers) { StringBuilder buf = new StringBuilder(); if (isPublic(modifiers)) { buf.append("public "); } if (isProtected(modifiers)) { buf.append("protected "); } if (isPrivate(modifiers)) { buf.append("private "); } if (isAbstract(modifiers)) { buf.append("abstract "); } if (isStatic(modifiers)) { buf.append("static "); } if (isFinal(modifiers)) { buf.append("final "); } if (isTransient(modifiers)) { buf.append("transient "); } if (isVolatile(modifiers)) { buf.append("volatile "); } if (isSynchronized(modifiers)) { buf.append("synchronized "); } if (isNative(modifiers)) { buf.append("native "); } if (isStrict(modifiers)) { buf.append("strictfp "); } if (isInterface(modifiers)) { buf.append("interface "); } if (buf.length() == 0) { return ""; } buf.setLength(buf.length() - 1); return buf.toString(); }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
注意:
Interface默认是
abstract的,虽然我们没有添加,编译器会在编译器为每个
Interface 添加这个修饰符。
只有被
@Retention(RetentionPolicy.RUNTIME)修饰的注解才可以在运行时被发射获取
Java 中预定义的注解
@Deprecated,
@Override,
和
@SuppressWarnings中只有
@Deprecated可以在运行时被访问到
Class 的成员:Member
java.lang.reflect.Member是一个接口,代表 Class 的成员,每个成员都有类型,分为是否从父类继承,还有是否可以直接访问。
Member 有三个实现类:
java.lang.reflect.Constructor:表示该 Class 的构造函数
java.lang.reflect.Field:表示该 Class 的成员变量
java.lang.reflect.Method:表示该 Class 的成员方法
获取构造函数
java.lang.Class提供了以下方法用于获取该类的构造函数:
注意:构造函数无法从父类继承
获取成员变量
java.lang.Class提供了以下方法用于获取该类的成员变量:
获取成员方法
java.lang.Class提供了以下方法用于获取该类的成员方法:
Thanks
http://docs.oracle.com/javase/tutorial/reflect/TOC.html http://stackoverflow.com/questions/2044446/java-introspection-and-reflection
http://stormzhang.com/java/2013/07/29/java-reflection/
http://www.infoq.com/cn/articles/cf-java-reflection-dynamic-proxy
https://github.com/JustinSDK/JavaSE6Tutorial/blob/master/docs/CH16.md
相关文章推荐
- 深入理解 Java 反射:Class (反射的入口)
- 深入理解 Java 反射:Class (反射的入口)
- 深入理解 Java 反射:Class (反射的入口)
- 深入理解Java类型信息(Class对象)与反射机制
- 深入理解Java类型信息(Class对象)与反射机制
- 深入理解Java类型信息(Class对象)与反射机制
- 深入理解Java类型信息(Class对象)与反射机制
- 深入理解Java类型信息(Class对象)与反射机制
- 我对Java的java.lang.Class这个类的深入理解
- 深入理解java class文件格式
- 深入理解Java Class文件格式(一)
- [Java]深入理解Java Class文件格式(二)
- 深入理解Java Class文件格式(六)
- 深入理解Java Class文件格式
- 深入理解Java Class文件格式(八)
- [Java]深入理解Java Class文件格式(五)
- 深入理解java反射
- 深入理解Java Class文件格式(五)
- 深入理解Java Class文件格式(二)
- 深入理解Java Class文件格式