什么是反射
- Java反射机制是在运行状态中
- 对于任意一个类,都能知道这个类的所有属性和方法;
- 对于任何一个对象,都能够调用它的任何一个方法和属性;
- 这样动态获取新的类以及动态调用对象方法的功能就叫做反射。
Class类
- Class可以说是反射能够实现的基础。
- class关键字是在声明java类是使用的;而Class是java JDK提供的一个类,完整路径为
java.lang.Class
。 - 对于每一种类,Java虚拟机都会初始化一个Class类型的实例,每当我们编写并且编译一个新创建的类就会产生一个对应Class对象,并且Class对象会被保存在同名.class文件里。
- 每当new一个新对象或者引用静态成员变量时,JVM中的类加载器系统会将对应的Class对象加载到JVM中,然后再根据这个类型信息相关的Class对象创建我们需要的实例对象或者提供静态变量的引用值。
构造器是私有的,只有JVM才可以调用获赠构造函数创建Class的对象 - 每个class(class是小写,代表普通类),无论创建多少个实例对象,在JVM中都对应同一个Class对象。
Class是反射能够实现的基础另一个原因:Java反射包
java.lang.reflect
中的所有类都没有public构造方法,要想获得这些类实例,只能通过Class类获取。另言之如果想使用反射,必须得获得Class对象。private Class(ClassLoader loader) {
classLoader = loader;
}
通过已有的类得到一个Class对象的几种方式:
1.通过对象实例获取对应Class对象Object.getClass(),基本类型无法使用该方法 ```java //Returns the Class for String Class c = “foo”.getClass();
enum E { A, B } //Returns the Class corresponding to the enumeration type E. Class c = A.getClass();
byte[] bytes = new byte[1024]; //Returns the Class corresponding to an array with component type byte. Class c = bytes.getClass();
Set
- 2.通过类的类型获取Class对象,基本类型同样可以使用这种方法
```java
//The `.class` syntax returns the Class corresponding to the type `boolean`.
Class c = boolean.class;
//Returns the Class for String
Class c = String.class;
- 3.通过类的全限定名获取Class对象,基本类型无法使用此方法 ```java Class c = Class.forName(“java.lang.String”);//通过Class.forName()方法加载的类,采用的是系统类加载器 //对于数组比较特殊 Class cDoubleArray = Class.forName(“[D”); //相当于double[].class
Class cStringArray = Class.forName(“[[Ljava.lang.String;”); //相当于String[][].class
- 4.基本类型和void类型的包装类可以使用TYPE字段获取
```java
Class c = Double.TYPE; //等价于 double.class.
Class c = Void.TYPE;//void
- 5.另外还有一些反射方法可以后去Class,但前提是你已经获取了一个Class对象
Class.getSuperclass()
//获得给定类的父类ClassClass.getClasses()
Class.getDeclaredClasses()
Class.getDeclaringClass()
Class.getEnclosingClass()
java.lang.reflect.Field.getDeclaringClass()
java.lang.reflect.Method.getDeclaringClass()
java.lang.reflect.Constructor.getDeclaringClass()
Member
java.lang.reflect.Member
有三个实现类,对应Java中的操作基本中构造函数,变量和方法。java.lang.reflect.Field
:对应类变量java.lang.reflect.Method
:对应类方法java.lang.reflect.Constructor
:对应类构造函数
突破java的权限检测java.lang.reflect.AccessibleObject
AccessibleObject
为我们提供了一个方法 setAccessible(boolean flag),该方法的作用就是可以取消 Java 语言访问权限检查。所以任何继承AccessibleObject
的类的对象都可以使用该方法取消 Java 语言访问权限检查。
所以任何继承AccessibleObject
的类的对象都可以使用该方法取消 Java 语言访问权限检查。(final类型变量也可以通过这种办法访问)
public final class Field extends AccessibleObject implements Member
Field
、Method
和Constructor
都是继承AccessibleObject
反射缺点
- 性能问题。因为反射是在运行时而不是在编译时,所有不会利用到编译优化,同时因为是动态生成,因此,反射操作的效率要比那些非反射操作低得多。
- 安全问题。使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如Applet,那么这就是个问题了。
- 代码问题。由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用--代码有功能上的错误,降低可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化。