上一篇文章我们已经将反射的基本知识和class类以及类的加载器进行了介绍,在上一篇我们还学习了四种得到Class类对象的方式,但是有了class对象我们能做些什么呢,学习完这篇文章,就可以得到答案了.
获取类的完整结构
这篇文章我们主要通过demo来学习,我先将demo需要用到的代码进行简单介绍.
一个接口MyInterface代码:
package com.tgb.reflect.common; import java.io.Serializable; public interface MyInterface<T> extends Serializable { }
一个父类Creature,代码是:
package com.tgb.reflect.common; public class Creature<T,N> { public double weight; public Creature(){} public void breath() { System.out.println("我是父类Creature的breath()方法"); } }
一个注解类MyAnnotation,代码是:
package com.tgb.reflect.common; import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.LOCAL_VARIABLE; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { public String value(); }
一个Person类,代码是:
package com.tgb.reflect.common; /** * Person类继承泛型Creature父类,实现两个接口,本类含有不同权限修饰符修饰的变量 * 含有不同权限修饰符修饰、不同参数的构造函数;含有不同权限修饰符修饰、不同参数的方法; * @author kang * */ @MyAnnotation(value = "tgb") public class Person extends Creature<String,Object> implements Comparable<Integer>,MyInterface<String> { //不同权限修饰符修饰的变量 private int age; public String name; int id; //不同权限修饰符修饰的拥有不同参数构造函数 private Person(String name) { super(); this.name = name; System.out.println("我是Person类的private修饰的带参数构造函数Person(String name) "); } public Person() { super(); System.out.println("我是Person类的public修饰的空参构造函数Person()"); } Person(String name, int age) { super(); this.name = name; this.age = age; System.out.println("我Person类的修饰符的带参构造函数Person(String name, int age)"); } @Override public String toString() { System.out.println("我是Person类的public修饰的空参方法toString()"); return "Person [name=" + name + ", age=" + age + "]"; } @MyAnnotation(value = "abc123") public void show(){ System.out.println("我是Person类的public修饰的带注解的show()空参方法"); } private void display(String nation){ System.out.println("我是Person类的public修饰的带注解的display()有参方法,参数是:"+nation); } public static void info(){ System.out.println("我是Person类的public修饰的info()空参静态方法"); } class Bird{} public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public int compareTo(Integer o) { return 0; } }
获取运行类构造函数
我们可以用得到的Class对象,通过反射来获取该Class对象的所有构造函数,
获取运行类权限修饰符为public的构造函数
//获取运行类权限修饰符为public的构造函数 @Test public void test2(){ String className = "com.tgb.reflect.common.Person"; Class class1 = Class.forName(className);
<span style="white-space:pre"> </span>Constructor[] conClasses=clazz.getConstructors(); for (int i = 0; i < conClasses.length; i++) { System.out.println(conClasses[i]); } }
运行结果为:
public com.tgb.reflect.common.Person()
获取运行类所有的构造函数
//获取运行类所有的构造函数 @Test public void test2() throws ClassNotFoundException{ String className = "com.tgb.reflect.common.Person"; Class clazz = Class.forName(className); Constructor[] conClasses=clazz.getDeclaredConstructors(); for (int i = 0; i < conClasses.length; i++) { System.out.println(conClasses[i]); } }
运行结果:
com.tgb.reflect.common.Person(java.lang.String,int)
publiccom.tgb.reflect.common.Person()
privatecom.tgb.reflect.common.Person(java.lang.String)
由此我们得出结论,getConstructors()可以获得运行类的public的构造函数,getDeclaredConstructors()可以获得运行类的所有构造函数。
获取运行类对象实例
我们可以用得到的Class对象,来创建类的对象实例,在创建对象实例时,要就用到了我们刚才上面讲到的构造函数,不同的构造函数,创建对象实例的方法也是不一样的.
空参构造器
//利用运行类的空参构造函数,来创建运行类对象的实例 @Test public void test1() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException{ String className = "com.tgb.reflect.common.Person"; Class class1 = Class.forName(className); //获取运行类的空参构造函数 Constructor constructor = class1.getConstructor(); //创建对应的运行类对象时,使用newInstance,实际上就是调用了运行时类的空参的构造器; Person person = (Person)constructor.newInstance(); System.out.println(person); }
运行结果:
我是Person类的public修饰的空参构造函数Person()
我是Person类的public修饰的空参方法toString()
Person [name=null,age=0]
非空参构造器
// 利用运行类的非空参构造函数,创建运行类的实例对象 @Test public void test4() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { String className = "com.tgb.reflect.common.Person"; Class class1 = Class.forName(className); // 获取运行类的带参数的构造函数 Constructor constructor = class1.getDeclaredConstructor(String.class, int.class); constructor.setAccessible(true); // 利用构造器创建运行类的实例对象 Person p = (Person) constructor.newInstance("luowei", 20); System.out.println(p); }
运行结果:
我Person类的修饰符的带参构造函数Person(Stringname, int age)
我是Person类的public修饰的空参方法toString()
Person [name=luowei,age=20]
通过上面两种方法,我们可以学习到的利用空参和非空参构造器来创建运行类的实例对象
有了Class类对象除了可以通过构造函数获取运行类实例,还可以获取运行类的其它一些内容.
获取运行类父类
1.获取运行类的父类
// 1.获取运行类的父类 @Test public void test1() { Class class1 = Person.class; Class parentClass = class1.getSuperclass(); System.out.println(parentClass); }
运行结果:
classcom.tgb.reflect.common.Creature
2.获取运行类的带着泛型的父类
由于我们的父类是带着泛型的,通过上面这种获取到的父类并没有带泛型,所有我们可以通过以下方法来获取运行类的带着泛型的父类.
// 2.获取运行类的带着泛型的父类 @Test public void test2() { // 得到运行类本身 Class class1 = Person.class; // 得到运行类的带泛型的父类 Type type = class1.getGenericSuperclass(); System.out.println(type); }
运行结果:
com.tgb.reflect.common.Creature<java.lang.String,java.lang.Object>
3.获取运行类的父类的泛型
我们已经得到带着泛型的父类了,现在我们要得到父类的泛型,我们可以用接下来的方法.
// 3.获取运行类的父类的泛型 @Test public void test3() throws ClassNotFoundException{ //通过类加载器得到运行类本身 String className= "com.tgb.reflect.common.Person"; ClassLoader classLoader =this.getClass().getClassLoader(); Class class1=classLoader.loadClass(className); //得到运行类的带泛型的父类 Type type = class1.getGenericSuperclass(); ParameterizedType param = (ParameterizedType) type; Type[] types= param.getActualTypeArguments(); for (int i = 0; i < types.length; i++) { System.out.println(((Class)types[i]).getName()); } }
运行结果:
java.lang.String
java.lang.Object
获取运行类实现的接口
1.获取运行类实现的所有接口
//1.获取运行类实现的接口 @Test public void test1() throws ClassNotFoundException{ //通过类加载器得到运行类本身 String className= "com.tgb.reflect.common.Person"; ClassLoader classLoader =this.getClass().getClassLoader(); Class class1=classLoader.loadClass(className); //获取运行类实现的接口 Class[] interfaces=class1.getInterfaces(); for (int i = 0; i < interfaces.length; i++) { System.out.println(interfaces[i]); } }
运行结果:
interfacejava.lang.Comparable
interfacecom.tgb.reflect.common.MyInterface
2.获取运行类的带着泛型的接口
//2.获取运行类实现的带泛型的接口 @Test public void test2() throws ClassNotFoundException{ //通过类加载器得到运行类本身 String className= "com.tgb.reflect.common.Person"; ClassLoader classLoader =this.getClass().getClassLoader(); Class class1=classLoader.loadClass(className); //获取运行类实现的接口 Type[] types=class1.getGenericInterfaces(); for (int i = 0; i < types.length; i++) { System.out.println(types[i]); } }
运行结果:
java.lang.Comparable<java.lang.Integer>
com.tgb.reflect.common.MyInterface<java.lang.String>
3.获取运行类的接口的泛型
//3.获取运行类实现的带泛型的接口 @Test public void test3() throws ClassNotFoundException{ //通过类加载器得到运行类本身 String className= "com.tgb.reflect.common.Person"; ClassLoader classLoader =this.getClass().getClassLoader(); Class class1=classLoader.loadClass(className); //获取运行类实现的接口 Type[] types=class1.getGenericInterfaces(); for (int i = 0; i < types.length; i++) { //获取每一个接口的泛型参数类型 ParameterizedType params = (ParameterizedType) types[i]; Type[] para= params.getActualTypeArguments(); for (int j = 0; j < para.length; j++) { System.out.println(((Class)para[j]).getName()); } }
运行结果:
java.lang.Integer
java.lang.String
通过上面的介绍我们可以获取到运行类接口、泛型接口和泛型的具体类型。
获取运行类的所在的包
//1.获取运行类的所在的包 @Test public void test6(){ //通过运行类本身来得到运行类 Class class1 = Person.class; Package packageClass = class1.getPackage(); System.out.println(packageClass.getName()); }
运行结果:
com.tgb.reflect.common
获取运行类的注解
//获取运行类的注解 @Test public void test7(){ //通过运行类本身来得到运行类 Class class1 = Person.class; //得到运行类的注解 Annotation[] annotations=class1.getAnnotations(); for (int i = 0; i < annotations.length; i++) { System.out.println(annotations[i]); } }
运行结果:
@com.tgb.reflect.common.MyAnnotation(value=tgb)
后记
这篇文章我们通过具体代码学习了,如何在得到运行类的Class对象后通过反射得到运行类的空参和有参的构造函数,并通过这些构造函数生成运行类的实例对象,同时还可以得到运行类的父类和接口,以及包括泛型父类、泛型接口、父类或者接口具体的泛型。下篇文章我们继续反射的学习。