文章目录
1、反射概述
反射,英文名叫reflection,是框架的灵魂,被视为动态语言的关键,注意,Java不是动态语言,但Java可以通过反射机制来获得类似动态语言的特性,即Java具有一定的动态性。
1.1 动态语言
指的是变量在明确赋值之后才会确定变量的类型,并且在运行过程中是可以赋值其它类型的值,并且变量的类型会随着值类型的变化而变化。
或者说,动态语言是在运行期间才进行类型检查的。代表语言:JavaScript,PHP。
<?php
$x = 100; //整数
$x = "haha"; // 字符串
echo $x; //结果为haha
?>
1.2 静态语言
指的是在变量声明阶段就确定了值的类型,变量的类型,并且在没有强制转换的情况下,该变量只能赋值该类型的值。比如如下:
int num = 10;
String name = "小明";
name="小爱"; //必须为字符串
以上的变量在声明阶段就已经确定好类型,像name就不能写成int类型的值,否则就会编译报错,也就是说,静态语言在编译期间就已经进行了类型检查。代表语言:Java。
1.3 结合动态语言的特点理解反射的用处(简单案例)
package com.cht.reflect;
//动物类
public abstract class Animal {
}
package com.cht.reflect;
//狗类
public class Dog extends Animal{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Dog{" +
"name='" + this.name + '\'' +
'}';
}
}
package com.cht.reflect;
//猫类
public class Cat extends Animal{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
'}';
}
}
package com.cht.reflect;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (true){
System.out.println("请选择你喜欢的动物:狗(按1),猫(按2),退出(exit)");
String s = sc.nextLine();
if("exit".equals(s)){
System.out.println("退出");
break;
}
Animal animal = getAnimal(s);
System.out.println(animal);
}
}
public static Animal getAnimal(String input){
Animal a = null;
switch (input){
case "1":
a = new Dog();
break;
case "2":
a = new Cat();
break;
default:
break;
}
return a;
}
}
现在程序处于运行状态,如下:
现在如果有一个类做了升级,比如Dog类,要升级为Dog1,那么就要再创建一个Dog1文件,那new Dog()不就得换成Dog1吗?如下:
public static Animal getAnimal(String input){
Animal a = null;
switch (input){
case "1":
a = new Dog1();
break;
case "2":
a = new Cat();
break;
default:
break;
}
return a;
}
但是,当我们想要去获取Dog1的时候,如下:
是不是不为Dog1呀,如果要想结果是Dog1,就必须退出,重新启动程序才能生效,那有没有一种可以不重启程序也能够生效的办法吗?有如下代码:
public static Animal createAni(String className){
Scanner sc = new Scanner(System.in);
System.out.println("请输入类型:");
String s = sc.nextLine();
try {
Class aClass = Class.forName(s);
Animal animal = (Animal) aClass.newInstance();
return animal;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
以上try里的代码是反射的代码,先别管,只要记住它是用另一种方式来创建对象即可,代替了以前的new。
然我们重新启动测试一下,如下:
针对以上,我们是不是还可以优化一下,比如我们可以建一个properties配置文件,在里写着:
className=com.cht.reflect.Dog1
这样的话,我们是不是可以通过读取properties配置文件里的className来动态创建对象呀,如果你Dog1要升级为Dog2的话,是不是只需要把配置文件里的className对应的值改一改就行了?并且还不需要重启。那么我们就优化一下吧,我在E盘下创建一个properties配置文件,完整代码如下:
package com.cht.reflect;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (true){
System.out.println("请选择你喜欢的动物:狗(按1),猫(按2),退出(exit)");
String s = sc.nextLine();
if("exit".equals(s)){
System.out.println("退出");
break;
}
Animal animal = getAnimal(s);
System.out.println(animal);
}
}
public static Animal createAni(String className){
try {
Class aClass = Class.forName(className);
Animal animal = (Animal) aClass.newInstance();
return animal;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
public static Animal getAnimal(String input) {
String className = null;
try {
Properties properties = new Properties();
BufferedReader bufferedReader = new BufferedReader(new FileReader("E:/config.properties"));
properties.load(bufferedReader);
className = properties.getProperty("className");
}catch (IOException e){
e.printStackTrace();
}
Animal a = null;
switch (input){
case "1":
a = createAni(className);
break;
case "2":
a = new Cat();
break;
default:
break;
}
return a;
}
}
注意createAni方法和getAnimal我都做了相应的修改。到此为止,我们知道了,反射可以代替对象的创建,这样做的好处是不用修改源代码,我们要修改的只是配置文件里的,而且只需要修改一处即可,一处修改,处处修改,也就是解耦,防止依赖性太强,因为你new的话在编译期就要加载该类,而反射是当你要用到的时候才会去动态加载(比如我上面的案例,我在运行中只要不输入1,它就不会帮我们加载,当我输入1,就说明我要用它了,它才会去加载),可以理解为延时加载(结合工厂模式去想更好,更能理解反射),也符合设计模式的ocp原则(开闭原则)。但不要滥用反射,毕竟它比new所耗的时间长,也就是性能上不及new。
1.4 类的加载简单概述
一个程序要想运行,就得加载进内存里,那我们写的java文件也是如此,所以,JVM就会启动一个类加载器来帮我们把java代码加载进内存,这个过程就是类的加载,该过程分为三个部分,分别是加载,连接,初始化。
要明白,.java文件计算机是看不懂的,计算机能够看懂的就是一堆的二进制,所以,我们就要把.java文件编译为.class字节码文件,然后类加载器根据名称就会找到在磁盘上的.class字节码文件并加载进内存里,供CPU去执行。
而.class字节码文件(不管是User.class,还是Animal.class等等)我们可以把共同的部分抽取出来形成一个类,这个类就是后面要说的Class类,如果.class文件被加载器加载进内存(方法区),相应的就会创建一个类对象(在堆上。在我们平时new对象的时候都是通过Class对象来创建类的实例的),这个类对象就有我们想要的信息,比如构造器,属性等等,它都封装起来了,用来描述磁盘上的字节码文件的(所以当我们拿到了类对象,就像拿到了字节码文件,是Class类的一个实例)。这就是第一部分加载的过程。剩下两部分就不说了,不是本节的重点,放到JVM再说。
1.5 class与Class
一个是小写的class,一个是大写的Class,这两个东西要怎么理解?首先,小写的class就是我们经常写的关键字,比如public class User
,它是用来描述具体的对象的。而Class只是一个类,这个类是用来描述所有的类的,或者说是描述所有的java字节码文件的,也就是public class Class
,也就是说,Class这个类是用来定义所有类的结构的,说的直白一点,就是它将类的各个组成部分(属性,方法,构造器)封装了起来,比如属性对应的被封装为Field[],构造方法为Constructor[],成员方法为Method[]。
通过Class类所产生的具体的对象(不是我们自己new出来的,而是系统创建的),叫类对象,上面也说了,类对象就是用来描述字节码文件的,或者说是描述方法区里的Class类字节码二进制元数据的,那么我们是不是只要获取到了类对象,就可以操作字节码文件里的内容了呢?答案是对的。
1.6 反射机制原理图
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射,反射,就像照镜子一样,比如.class文件通过照镜子,发现镜子里的自己跟现实中的自己长的有点像,完全是把类的各个成分封装成了一个个java对象(比如嘴是一个对象,眼睛是一个对象等),而这个镜子中的自己就是Class对象,是不是通过这个镜子里的自己就可以看到自己的内部结构呀,比如看自己嘴巴里的构造一样,肯定是拿起镜子看的,不拿起镜子怎么看,那么一样的,通过获取Class对象就可以看到某个类里的具体构造。
注意某个类的Class类对象,在内存中只有一份,因为类只加载一次,也就是说,不是每一次new一次(前提是同一个类,比如Cat和Dog就不是同一个类,那么在内存中就有两份),就来一次类对象,下面有介绍。
2. 获取Class对象的六种方式
准备一下两个类:
package com.cht.reflect;
public class Person {
private int age;
public String name;
private void eat(){
System.out.println("Person eat");
}
public void sleep(){
System.out.println("Person sleep");
}
}
package com.cht.reflect;
public class Student extends Person {
private int sno;
double height;
protected double weight;
public double score;
public String showInfo(){
return "我是一名学生";
}
private void work(){
System.out.println("我去工作了");
}
void happy(){
System.out.println("开心");
}
protected int getSno(){
return sno;
}
public Student(){
System.out.println("空参构造器");
}
private Student(int sno){
this.sno = sno;
}
Student(int sno,double weight){
this.sno = sno;
this.weight = weight;
}
protected Student(int sno,double height,double weight){
this.sno = sno;
this.height = height;
this.weight = weight;
}
}
在准备一个测试类,如下:
package com.cht.reflect;
public class Test {
public static void main(String[] args) throws Exception {
//方式1:通过getClass方法获取
Person p = new Person();
Class c1 = p.getClass();
//方式2:通过内置class属性。注意,接口,注解(比如Override.class)也是可以的,
// 还包括数组,基本数据类型,和void,枚举,Class,外部类,内部类这些。
Class c2 = Person.class;
//方式3(常用):调用Class类提供的静态方法forName
Class c3 = Class.forName("com.cht.reflect.Person");
//方式4(了解): 利用类的加载器
ClassLoader loader = Test.class.getClassLoader();
Class c4 = loader.loadClass("com.cht.reflect.Person");
//补充:
//基本数据类型(int,char,boolean,float,double,byte,long,short)可按以下方式得到Class类对象
Class c5 = int.class;
//基本数据类型对应的包装类,可以通过.TYPE得到Class类对象
Class c6 = Integer.TYPE;
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println(c5);
System.out.println(c6);
System.out.println(c1 == c2);
System.out.println(c2 == c3);
System.out.println(c3 == c4);
}
}
结果如下:
class com.cht.reflect.Person
class com.cht.reflect.Person
class com.cht.reflect.Person
class com.cht.reflect.Person
int
int
true
true
true
为true,说明他们的类对象是同一个,也就是说,一个类在内存中只有一个Class对象。注意,如果是数组,不同的维度,即使是同一个类型int,得到的字节码对象也不一样,如下:
package com.cht.reflect;
public class Test {
public static void main(String[] args) throws Exception {
int[] num1={1,2};
int[][] num2={{1,2},{3,4}};
System.out.println(num1.getClass());
System.out.println(num2.getClass());
}
}
结果如下:
class [I
class [[I
3. 反射成员变量
通过Class对象的如下方法可获取一个对象的成员变量信息:
-
返回所有公共成员变量对象的数组,包括父类
public Field[] getFields()
-
返回所有成员变量对象的数组(包含私有的),不包括父类
public Field[] getDeclaredFields()
-
返回单个公共成员变量对象,包括父类:
public Field getField(String name)
-
返回单个成员变量对象(可以使用私有的),不包括父类
public Field getDeclaredField(String name)
Field对象描述了成员变量的信息,包括:成员变量的名称,类型,权限等,如下:
package com.cht.reflect;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws Exception {
//1. 首先获取Class对象
Class c1 = Class.forName("com.cht.reflect.Student");
//2. 获取全限定类名
String name = c1.getName();
//3. 获取简单类名
String simpleName = c1.getSimpleName();
System.out.println("全限定类名:"+name);
System.out.println("简单类名:"+simpleName);
//4. 返回单个公共成员变量对象(只能获取公共的public,像private,protected都不能获取,否则报NoSuchFieldException),包括父类
Field field1 = c1.getField("score");
Field field2 = c1.getField("name");//父类的public属性
System.out.println(field1);
System.out.println(field2);
//5. 返回单个成员变量对象(可以使用私有的),不包括父类
Field field3 = c1.getDeclaredField("sno");//sno属性是本类私有的属性
System.out.println(field3);
//6. 如果要想获取父类的Class对象,有这么一个方法,如下
Class c2 = c1.getSuperclass();
Field field4 = c2.getDeclaredField("age");
System.out.println(field4);
//7. 获取所有public的成员变量(包括父类)
Field[] fields = c1.getFields();
for(int i=0;i<fields.length;i++){
System.out.println("所有public的属性:"+fields[i]);
}
//8. 获取本类的所有属性用getDeclaredFields
Field[] fields1 = c1.getDeclaredFields();
for(int i=0;i<fields1.length;i++){
System.out.println("所有属性:"+fields1[i]);
}
}
}
注意getField不能获取私有属性。结果如下:
全限定类名:com.cht.reflect.Student
简单类名:Student
public double com.cht.reflect.Student.score
public java.lang.String com.cht.reflect.Person.name
private int com.cht.reflect.Student.sno
private int com.cht.reflect.Person.age
所有public的属性:public double com.cht.reflect.Student.score
所有public的属性:public java.lang.String com.cht.reflect.Person.name
所有属性:private int com.cht.reflect.Student.sno
所有属性:double com.cht.reflect.Student.height
所有属性:protected double com.cht.reflect.Student.weight
所有属性:public double com.cht.reflect.Student.score
获取属性的信息,如下:
package com.cht.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Test {
public static void main(String[] args) throws Exception {
//1. 首先获取Class对象
Class c1 = Class.forName("com.cht.reflect.Student");
//2. 获取属性
Field field1 = c1.getField("score");
//3. 提取(获取)属性的信息
System.out.println("field1的名字:"+field1.getName());
System.out.println("field1的类型:"+field1.getType());
Student student = new Student();
// field1.setAccessible(true); 表示关闭访问安全检查,为false就是不关闭咯,如果field1是私有属性的话并且要访问就要把安全检查给关闭了。
System.out.println("field1的值:"+field1.getDouble(student));//或者直接get()
int modifiers = field1.getModifiers();
System.out.println("为public?:"+Modifier.isPublic(modifiers));
System.out.println("为private?:"+Modifier.isPrivate(modifiers));
System.out.println("是static吗?:"+ Modifier.isStatic(modifiers));
}
}
结果如下:
field1的名字:score
field1的类型:double
空参构造器
field1的值:0.0
为public?:true
为private?:false
是static吗?:false
说一下getModifiers,它不是返回int类型吗,如下:
修饰符 | 数字 |
---|---|
默认修饰符 | 0 |
public | 1 |
private | 2 |
protected | 4 |
static | 8 |
final | 16 |
如果说是public+static,那它返回的就是两者的相加之和9。
还有很多,都是见名之意的,如下:
设置成员变量的值,如下:
package com.cht.reflect;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws Exception {
//1. 首先获取Class对象
Class c1 = Class.forName("com.cht.reflect.Student");
//2. 获取属性
Field field1 = c1.getField("score");
Student student = new Student();
field1.set(student,65);
System.out.println("field1的值:"+field1.get(student));
}
}
结果如下:
空参构造器
field1的值:65.0
到这为止,我们明白了,new跟反射的不同之处在于,new出来的对象是不能访问私有属性的,而反射不仅可以访问私有属性,还可以为私有属性设值。
4. 反射静态变量
在Student类里的score加上static,如下:
public static double score;
让我们获取和设置score吧,如下代码:
package com.cht.reflect;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws Exception {
Class c1 = Class.forName("com.cht.reflect.Student");
Field score = c1.getField("score");
Object o = score.get(null);
System.out.println("设置前:"+o);
score.set(null,70);
Object o1 = score.get(null);
System.out.println("设置前:"+o1);
}
}
结果如下:
设置前:0.0
设置前:70.0
也就是说,static修饰的变量是不需要对象调用的,类就可以调了,所以我们在获取和设置值的时候用null来代替对象即可。
5. 反射成员方法
通过Class对象的如下方法可获取一个对象的成员方法信息:
- 返回所有公共成员方法对象的数组(包括父类)
public Method[] getMethods()
- 返回所有成员方法对象的数组(包含私有的,不包含父类)
public Method[] getDeclaredMethods()
- 返回单个公共成员方法对象(包括父类)
public Method getMethod(String name,Class<?>... parameterTypes)
- 返回所有成员方法对象(包含私有的,不包含父类)
public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
如下代码:
package com.cht.reflect;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception {
Class c1 = Class.forName("com.cht.reflect.Student");
//第一个参数:方法名
//第二个参数: 方法的参数类型,如果有多个参数,那么参数之间用逗号隔开,如果没参数,就用null
Method work = c1.getMethod("showInfo", null);
System.out.println(work);
}
}
注意,第二个参数是可以不写null的,只要showInfo方法是没有参数的,如下:
Method work = c1.getMethod("showInfo");
那如果有参数呢?比如如下:
public String showInfo(String age,Integer num){
return "我是一名学生";
}
那么应该如下:
Method work = c1.getMethod("showInfo", String.class,Integer.class);
设置第二个参数的原因是为了区分方法重载。然后像getDeclaredMethod就不用多说了,它带有Declared字眼表示是可以访问私有方法的,但是只能是本类。
package com.cht.reflect;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception {
Class c1 = Class.forName("com.cht.reflect.Student");
Method[] methods = c1.getMethods();
for (int i=0;i<methods.length;i++){
System.out.println(methods[i]);
}
}
}
结果如下:
public java.lang.String com.cht.reflect.Student.showInfo(java.lang.String,java.lang.Integer)
public void com.cht.reflect.Person.sleep()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
是不是觉得好多呀,也就是说getMethods它获取的是所有的公共方法(只能是public修饰的),包括父类,比如Object类。
获取方法的信息,如下:
package com.cht.reflect;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Test {
public static void main(String[] args) throws Exception {
Class c1 = Class.forName("com.cht.reflect.Student");
Method method = c1.getMethod("showInfo",String.class,Integer.class);//如果参数是数组,比如String[] a或者String... a,那么相应的,这里就是String[].class
//获取方法名
System.out.println("方法名:"+method.getName());
//获取方法参数
Class<?>[] types = method.getParameterTypes();//对应的,像getExceptionTypes()可以获取异常,
for (int i=0;i<types.length;i++){
System.out.println("参数类型"+i+":"+types[i]);
}
//返回值类型
Class<?> returnType = method.getReturnType();
System.out.println("返回值类型:"+returnType);
//方法的修饰符
int modifiers = method.getModifiers();
System.out.println("为public?:"+Modifier.isPublic(modifiers));
System.out.println("是静态的吗?:"+Modifier.isStatic(modifiers));
System.out.println("权限修饰符是哪一个呢?:"+Modifier.toString(modifiers));//modifiers对应的数字就代表了某个权限修饰符,通过调用toString方法就可以看到真正的修饰符了。
}
}
结果如下:
方法名:showInfo
参数类型0:class java.lang.String
参数类型1:class java.lang.Integer
返回值类型:class java.lang.String
为public?:true
是静态的吗?:false
权限修饰符是哪一个呢?:public
通过反射来调用方法:
package com.cht.reflect;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception {
Class c1 = Class.forName("com.cht.reflect.Student");
Student student = new Student();
Method method = c1.getMethod("showInfo",String.class,Integer.class);
//参数1:对象(因为我们调的是成员方法,成员方法的调用需要对象)
//参数2之后:是方法的参数值。
System.out.println(method.invoke(student, "21", 10));//调方法,拿到返回值
}
}
结果如下:
空参构造器
我是一名学生
6. 反射静态方法
对Student类的work方法加上static,如下:
private static void work(){
System.out.println("我去工作了");
}
如下代码:
package com.cht.reflect;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception {
Class c1 = Class.forName("com.cht.reflect.Student");
Method work = c1.getDeclaredMethod("work");
work.setAccessible(true);//暴力破解
//invoke有两个参数,第一个参数是对象,第二个参数是方法的参数值,因为此方法没有,所以默认不写
work.invoke(null);
}
}
结果如下:
我去工作了
7. 反射构造方法
通过Class对象的如下方法可获取一个对象的构造方法信息:
- 返回所有公共(public)构造方法对象的数组(仅本类)
public Constructor<?>[] getConstructors()
- 返回所有构造方法对象的数组(包含私有的)(仅本类)
public Constructor<?>[] getDeclaredConstructors()
- 返回单个公共构造方法对象
public Constructor<T> getConstructor(Class<?>... parameterTypes)
- 返回单个构造方法对象(可以使用私有的)
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
如下代码:
package com.cht.reflect;
import java.lang.reflect.Constructor;
public class Test {
public static void main(String[] args) throws Exception {
Class c1 = Class.forName("com.cht.reflect.Student");
//1. 得到无参的public构造方法
Constructor constructor = c1.getConstructor(null);//null可以不写,表示空构造
System.out.println(constructor);
//2. 得到有参的private构造方法
Constructor declaredConstructor = c1.getDeclaredConstructor(int.class);
System.out.println(declaredConstructor);
//3. 获取本类所有的公共方法
Constructor[] constructors = c1.getConstructors();
for (int i=0;i<constructors.length;i++){
System.out.println("所有的公共构造方法"+i+":"+constructors[i]);
}
//4. 获取本类所有的私有方法,包括protected修饰的,默认的
Constructor[] declaredConstructors = c1.getDeclaredConstructors();
for (int i=0;i<declaredConstructors.length;i++){
System.out.println("所有的构造方法"+i+":"+declaredConstructors[i]);
}
}
}
结果如下:
public com.cht.reflect.Student()
private com.cht.reflect.Student(int)
所有的公共构造方法0:public com.cht.reflect.Student()
所有的构造方法0:com.cht.reflect.Student(int,double)
所有的构造方法1:private com.cht.reflect.Student(int)
所有的构造方法2:protected com.cht.reflect.Student(int,double,double)
所有的构造方法3:public com.cht.reflect.Student()
通过获取到的构造方法来创建对象,如下:
package com.cht.reflect;
import java.lang.reflect.Constructor;
public class Test {
public static void main(String[] args) throws Exception {
Class c1 = Class.forName("com.cht.reflect.Student");
Constructor constructor = c1.getConstructor(null);
Object o = constructor.newInstance(null);
System.out.println(o);
Constructor declaredConstructor = c1.getDeclaredConstructor(int.class);
declaredConstructor.setAccessible(true);
Object o1 = declaredConstructor.newInstance(20);
System.out.println(o1);
}
}
注意,不通过构造器其实也能创建对象,如下:
package com.cht.reflect;
public class Test {
public static void main(String[] args) throws Exception {
Class c1 = Class.forName("com.cht.reflect.Student");
//newInstance()方法调的是Student里的无参构造,所以Student中一定要有无参构造
Object o = c1.newInstance();
System.out.println(o);
}
}
如果方法是有参的,那就必须先获取构造器,无参,就直接newInstance即可。
总结:Class类的常用方法
方法名 | 功能说明 |
---|---|
static Class forName(String name) | 返回指定类名name的Class对象 |
Object newInstance() | 调用缺省构造函数,返回该Class对象的一个实例 |
getName() | 返回此Class对象所表示的实体(类,接口,数组类,基本类型等)名称 |
Class getSuperClass() | 返回当前Class对象的父类的Class对象 |
Class[] getInterfaces() | 获取当前Class对象的接口 |
ClassLoader getClassLoader() | 返回该类的类加载器 |
Class getSuperclass() | 返回表示此Class所表示的实体的超类的Class |
Constructor[] getConstructors() | 返回一个包含某些Constructor对象的数组 |
Field[] getDeclaredFields() | 返回Field对象的一个数组 |
Method getMethod(String name,Class … paramTypes) | 返回一个Method对象,此对象的形参类型为paramType |