java.lang.Class对象

每一个java类都会被加载到jvm内存,生成一个对应的java.lang.Class对象才能使用。取得这个对象可以通过如下方式:

1、如:A.class

2、对象的getClass()方法。

3、如:Class.forName("com.test.javatest.A")

java反射设置final java反射设置static_java反射设置final

 

 

类载入分三个阶段

1、加载:加载class文件

2、链接:为静态成员变量分配内存,设置初始值,如int、long设置为0,Object设置为null,boolean设置为false

3、初始化:为静态成员变量设置用户指定的值,执行static块。

 

如果使用A.class这种方式访问到类时,只会执行第1、2阶段,不会执行static块(当调用它的方法时也会执行,如A.class.newInstance())。

使用Class.forName默认会执行全部3个阶段。也可以设定只做第一步(forName第二个参数设置为false,ClassLoader.loadClass(className,false);)。

java反射设置final java反射设置static_成员变量_02

 

 

反射的概念

通常使用类都是提前定义好java文件,然后创建对象,调用属性、方法。而有一些情况则不能提前定义类,如类的定义是运行期才知道的,比如spring框架中创建bean对象,框架无法预知用户会定义哪些bean类,但它要为这些用户定义的bean类创建bean对象,它只能在运行期动态获取类定义创建bean对象,而不能提前用new的方式写在代码中创建。

 

这种情况可以采用反射机制,首先通过类的全路径生成对应的java.lang.Class对象。java.lang.Class对象提供了通过Class创建实际对象的能力,但这时由于没有提前定义类的class文件,因此不能在代码里面直接通过"对象."的形式访问属性或者调用方法,而且反射出来的对象是个Object类型,由于没有类的class定义,也无法使用强转。

 

java.lang.Class提供了一系列的方法,可以实现创建对象、获取对象的属性、通过方法名调用对象的方法等操作。

 

常用的反射功能

isInstance判断是否为某个类的实例

如:

 

a = 2;

out.println(Number.class.isInstance(a)); // true

 

 

创建对象

1、通过Class的newInstance方法创建,只能调用无参构造函数,如果定义了有参构造函数,又没有写无参构造函数,则会报错。

使用,如:

classB = Class.forName("com.test.javatest.B");

bclassB.newInstance();

 

2、通过Constructor对象创建。

首先取得Constructor,可取得数组,或者根据参数类型取得单个。

java反射设置final java反射设置static_java反射设置final_03

 

然后调用它的newInstance方法即可

 

constructorclassB.getConstructor(String.class, Integer.class);

constructor.newInstance("kkk", 3);

java反射设置final java反射设置static_成员变量_04

 

ps:如果参数是int类型而不是Integer,则要用Integer.TYPE代替Integer.Class,或者用int.class,如:

java反射设置final java反射设置static_数组_05

java反射设置final java反射设置static_java_06

 

获取方法

getMethods(),返回所有public方法,包括继承的。

getDeclaredMethods(),返回本类(接口)中声明的所有方法,不包括继承的。

getMethod(String name, Class<?>... parameterTypes),根据方法名、参数获取单个方法。

如:

获取方法数组:

java反射设置final java反射设置static_成员变量_07

由于所有类都继承了Object类,所以getMethods打印了很多从Object继承下来的public方法,但没有打印本类中的protected和private。getDeclaredMethods打印了本类中定义的三个方法。

 

 

 

获取单个方法:

java反射设置final java反射设置static_java_08

 

ps:通过名称获取的方法必须是public的,否则报错,如:

java反射设置final java反射设置static_java反射设置final_09

 

 

获取成员变量

与获取方法类似:

getFields():获取所有的public成员变量,包括继承的

getDeclaredFields():获取本类(接口)中定义的成员变量,不包括继承的

如:

获取成员变量数组:

java反射设置final java反射设置static_java反射设置final_10

 

 

获取单个成员变量:

java反射设置final java反射设置static_java反射设置final_11

ps:通过名称获取的成员变量必须是public的,否则报错。

 

 

调用方法

使用getField得到的方法是类里面的定义,调用方法前必须有一个对象,然后将该对象作为参数传递个field的invoke方法,它会自动回调对象中的对应方法:

如:

java反射设置final java反射设置static_java_12

 

使用数组

由于通常定义对象数组的时候需要指定对象类型,如:String[] s;而在运行期才知道对象类型的情况下,就不能使用这种方式直接创建数组了。

可以使用反射的方式创建,如:

import java.lang.reflect.Array;

 

publicclass A {

 

publicstaticvoidargs) throws Exception {

classB = Class.forName("com.test.javatest.B");

// 创建数组

bArray = Array.newInstance(classB, 5);

        

// 设置数组元素

        Array.set(bArray, 0, classB.newInstance());

        Array.set(bArray, 1, classB.newInstance());

        

// 获取数组元素

        Array.get(bArray, 0);

        

        

    }

}

 

class B {

}

 

反射调用private方法

java反射设置final java反射设置static_成员变量_13

 

反射越过泛型检查

java反射设置final java反射设置static_java_14