深入分析Java反射(一)-核心类库和方法 (6)

运行后输出结果:

name->club.throwable.reflect.Main$Supper canonicalName->club.throwable.reflect.Main.Supper simpleName->Supper ====================================== name->[[Ljava.lang.String; canonicalName->java.lang.String[][] simpleName->String[][]

简单理解为:

getName():用于获取类在Java虚拟机中的类名表示。

getCanonicalName():用于获取全类名,包括包路径,包路径以点号分隔。

getSimpleName():用于获取类名,不包括包路径。

下面再举一个例子通过类名进行实例化对象和操作,从例子可以看到,实例化对象可以不依赖new关键字,这就是反射的强大之处:

public class Main3 { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("club.throwable.reflect.Main3$Supper"); Supper supper = (Supper) clazz.newInstance(); System.out.println(supper.sayHello("throwable")); } public static class Supper { public String sayHello(String name) { return String.format("%s say hello!", name); } } }

这里需要注意一点,Class.forName方法只能使用在修饰符为public的类上,如果使用在其他修饰符类上会抛出异常(IllegalAccessException),那么,如果上面的Supper类的修饰符修改为private,怎么样才能正常实例化它?这个问题将会在下面分析Constructor的时候得到解决。另外,这里的Class.forName方法不是获取Class实例的唯一方式,总结有以下三种方式:

1、使用类的字面量"类名.class"。类字面常量使得创建Class对象的引用时不会自动地初始化该对象,而是按照之前提到的加载,链接,初始化三个步骤,这三个步骤是个懒加载的过程,不使用的时候就不加载。

2、使用Class.forName(全类名);方法。

3、使用实例的getClass()方法。getClass()是所有的对象都能够使用的方法,因为getClass()方法是Object类的方法,所有的类都继承了Object,因此所有类的对象也都具有getClass()方法。

一般来说,使用"类名.class",这样做即简单安全又比较高效。因为在编译时就会受到检查,因此不需要置于try语句块中,并且它根除了对forName()方法的调用(forName()方法是一个耗时比较多的方法),所以相对比较高效。

最后,分析一下这几个比较难懂的方法getEnclosingClass()、getEnclosingConstructor()、getEnclosingMethod():

getEnclosingClass():返回一个类,当前类(一般是成员类)在这个类(一般叫封闭类,相对于内部类的外部类或者说外面一层)中定义。

getEnclosingConstructor():返回构造器,当前类是在这个构造函数中定义。

getEnclosingClass():返回方法,当前类是在这个方法中定义。

我们在新建一个类的时候,这个类可以使另一个类中定义的成员类、构造方法中定义的内部类、方法中定义的内部类。可以通过当前的类反向获取定义当前的类的类、构造或者方法,这三种情况对应上面三个方法。举个例子:

getEnclosingClass()方法使用例子:

public class Main5 { public static void main(String[] args) throws Exception{ Class<Outter.Inner> clazz = Outter.Inner.class; Class<?> enclosingClass = clazz.getEnclosingClass(); System.out.println(enclosingClass.getName()); } // Inner类是Outter类的成员类 public static class Outter { public static class Inner { } } }

输出结果:

org.throwable.inherited.Main5$Outter

在这里,Inner就是当前定义的类,它是Outter的静态成员类,或者说Outter是Inner的封闭类,通过Inner的Class的getEnclosingClass()方法获取到的就是Outter的Class实例。

getEnclosingConstructor()方法使用例子:

public class Main6 { public static void main(String[] args) throws Exception { Outter outter = new Outter(); } public static class Outter { //Outter的无参数构造器 public Outter() { //构造中定义的内部类 class Inner { } Class<Inner> innerClass = Inner.class; Class<?> enclosingClass = innerClass.getEnclosingClass(); System.out.println(enclosingClass.getName()); Constructor<?> enclosingConstructor = innerClass.getEnclosingConstructor(); System.out.println(enclosingConstructor.getName()); } } }

输出结果:

org.throwable.inherited.Main6$Outter org.throwable.inherited.Main6$Outter

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zywspx.html