📝个人主页:哈__
期待您的关注
我想要通过反射来打印如下效果的类信息。
Student类如下代码所示。
package com.my.reflect;
public class Student {
public String name;
public int age;
public Student(){}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
private void test(String str){
System.out.println("哈哈哈"+str);
}
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 String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
你是否有思路?如果你不了解反射的话,我来给大家简单的介绍一下反射的使用方法。
一、反射简介
1、Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。
2、Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。
在具体的东西,本文章不在这里叙述,总而言之,我们可以通过反射获取一个类的class对象,并且通过这个class对象获得这个类当中的信息。就是说,只要我能知道是哪个类,那么这个类对于我来说基本上就是透明的了。
二、反射的一些常用方法
1.获取一个类的class对象的三种方法
通过包名获取。
Class clazz = Class.forName("com.my.reflect.Student");
通过类获取。
Class clazz = Student.class;
通过类的对象获取 (能够拿到这个类的对象但是不知道是什么类,你可以假定下边的代码没有第一行,只有第二行,那么你能否知道s是哪个类的对象?)。
Student s = new Studnet();
Class clazz = s.getClass();
以上三种获取方式相同,但是需要区分不同的场景采取不同的获取方式。
2.获取一个类的构造函数
通过class对象我们可以获取这个类的构造函数。传入的参数是一些class对象,通过这些class对象能确定你要获取的是哪个构造函数,例如下边代码。我们获取的构造函数有两个参数,第一个参数是String类型,第二个参数是int类型,通过这两个class对象,我们能够正确的获取构造参数。
//class.getConstructor(Class<?>... parameterTypes)
Constructor constructor= clazz.getConstructor(String.class,int.class);
//public Student(String name,int age){}
//获取类的全部构造函数
Constructor [] constructors= clazz.getConstructors();
3.获取一个类的方法
通过调用如下代码获取一个类的方法。注意参数,第一个参数是name,代表着你想要获取的方法的名称,第二个参数不陌生了吧,在上边我们获取构造函数的时候见过,这个参数就代表着你要获取的方法的参数类型都是什么,防止方法重载的影响。
//getMethod(String name, Class<?>... parameterTypes)
Method method = clazz.getMethod();
//获取全部的方法 不需要传参
Method [] method = clazz.getMethods();
我们都知道在一个类中,方法有public修饰也有private修饰,还有protected和什么都不写,那么我们在获取Method的时候,我们只能获得类中的公有方法,私有方法我们是无法获取的,这时候就要用到下边的方法来获取一个类中的私有方法。
Method method = clazz.getDeclaredMethod();
//获取全部的方法,包括私有 不需要传参
Method [] methods = clazz.getDeclaredMethods();
写了这行代码,不管你的方法是共有的还是私有的都可以获取到。
4.获取一个类中的属性
通过下边的代码来获取一个类当中的属性。传入的name就是要获取的属性的名称。当然除了获取单个的属性外我们还可以获取全部的属性。如果你想要获取私有属性同样的要调用带有Declared的方法。
//getField(String name)
Field field = clazz.getField();
//不需要传入参数
Field [] fields = clazz.getFields();
// 获取单个私有属性
Field privateField = clazz.getDeclaredField(name);
// 获取全部私有属性 不要参数
Field [] allPrivateField = clazz.getDeclaredField();
5.获取一个类、方法和属性的修饰符
我们都知道类、方法和属性都是有修饰符的,如public、final、private、static等,我们可以通过调用以下的方法来获取。
Class clazz = Class.forName("com.my.reflect.Student");
Constructor constructor = clazz.getConstructor(String.class, int.class);
int modifiers = constructor.getModifiers();
System.out.println(modifiers);
System.out.println(Modifier.toString(modifiers));
Method method = clazz.getDeclaredMethod("test",String.class);
int modifiers1 = method.getModifiers();
System.out.println(modifiers1);
System.out.println(Modifier.toString(modifiers1));
结果如下所示。
这个modifers到底该如何使用呢,别急这里有一张表格。
modifier的值是一个累加的结果,大家可以自己试一试。在上边的代码中我们能够看到,构造方法和普通方法都可以调用 getModifiers()方法,当然属性也可以。
以上就要反射的简单介绍,在这片文章中我并没有介绍通过class获取的constructor、method和field该如何使用,以后有机会的话我会发一篇文章介绍,我这篇文章主要的目的是解决一开始的问题。
三、问题解决
有了上面的基础之后,我们来解决问题,要打印一个类的信息,我们先要打印这是哪个类。这里用到了一个getSuperclass方法,获取这个类的父类的class对象,帮助我们打印继承关系。下边我们先打印了这个类的修饰符public 然后打印了类名,通过调用getName方法。
try{
Class c1 = Class.forName("com.my.reflect.Student");
Class superc1 = c1.getSuperclass();
//获取类的修饰符
String modifiers = Modifier.toString(c1.getModifiers());
System.out.print(modifiers);
System.out.print(" class "+c1.getName());
if(modifiers.length()>=0) System.out.println(" extends "+superc1.getName());
System.out.print("\n{\n");
System.out.print("\n}\n");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
结果如下。是不是有些样子了?
现在我们打印构造函数。构造方法不止一个,我们调用的是getDeclaredConstructors(),之后进行for循环遍历,每一个获取到的constructor对象我们获取他的名称,获取这个构造方法的修饰符,然后打印。这时问题来了,一个方法是有参数的,我们需要获取这个构造方法的所有参数信息。这里调用getParameterTypes()方法,然后对所有的参数类型进行for循环进行遍历,然后打印这个方法的所有的参数的类型。
public static void printConstrctors(Class c1){
Constructor[] constructors = c1.getDeclaredConstructors();
for(Constructor c:constructors){
String name = c.getName();
System.out.print(" ");
//获取构造方法的作用域
String modifiers = Modifier.toString(c1.getModifiers());
if(modifiers.length()>0) System.out.print(modifiers+" ");
System.out.print(name+"(");
Class[] paramTypes = c.getParameterTypes();
for(int j = 0;j< paramTypes.length;j++){
if(j>0) System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
System.out.println(")");
}
}
看结果。
之后就是我们的方法了,既然构造函数会打印了,方法是一个道理。不在讲解了。注意一个resType,也就是返回值类型。
public static void printMethods(Class c1){
Method[] methods = c1.getDeclaredMethods();
for(Method m:methods){
Class resType = m.getReturnType();
String name = m.getName();
System.out.print(" ");
String modifiers = Modifier.toString(m.getModifiers());
if(modifiers.length()>0) System.out.print(modifiers+" ");
System.out.print(resType.getName()+" "+name+"(");
Class [] paramTypes = m.getParameterTypes();
for(int j = 0;j< paramTypes.length;j++){
if(j>0) System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
System.out.println(")");
}
}
最后就是我们的属性了。
public static void printFields(Class c1){
Field [] fields = c1.getDeclaredFields();
for (Field field : fields) {
Class type = field.getType();
String name = field.getName();
System.out.print(" ");
String modifiers = Modifier.toString(field.getModifiers());
if(modifiers.length()>0) System.out.print(modifiers+" ");
System.out.println(type.getName()+" "+name+";");
}
}
完美解决。
四、完整代码
public class ReflectTest {
public static void main(String[] args) {
try{
Class c1 = Class.forName("com.my.reflect.Student");
Class superc1 = c1.getSuperclass();
//获取类的作用域
String modifiers = Modifier.toString(c1.getModifiers());
System.out.print(modifiers);
System.out.print(" class "+c1.getName());
if(modifiers.length()>=0) System.out.println(" extends "+superc1.getName());
System.out.print("\n{\n");
printConstrctors(c1);
System.out.println();
printMethods(c1);
System.out.println();
printFields(c1);
System.out.print("\n}\n");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void printConstrctors(Class c1){
Constructor[] constructors = c1.getDeclaredConstructors();
for(Constructor c:constructors){
String name = c.getName();
System.out.print(" ");
//获取构造方法的作用域
String modifiers = Modifier.toString(c1.getModifiers());
if(modifiers.length()>0) System.out.print(modifiers+" ");
System.out.print(name+"(");
Class[] paramTypes = c.getParameterTypes();
for(int j = 0;j< paramTypes.length;j++){
if(j>0) System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
System.out.println(")");
}
}
public static void printMethods(Class c1){
Method[] methods = c1.getDeclaredMethods();
for(Method m:methods){
Class resType = m.getReturnType();
String name = m.getName();
System.out.print(" ");
String modifiers = Modifier.toString(m.getModifiers());
if(modifiers.length()>0) System.out.print(modifiers+" ");
System.out.print(resType.getName()+" "+name+"(");
Class [] paramTypes = m.getParameterTypes();
for(int j = 0;j< paramTypes.length;j++){
if(j>0) System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
System.out.println(")");
}
}
public static void printFields(Class c1){
Field [] fields = c1.getDeclaredFields();
for (Field field : fields) {
Class type = field.getType();
String name = field.getName();
System.out.print(" ");
String modifiers = Modifier.toString(field.getModifiers());
if(modifiers.length()>0) System.out.print(modifiers+" ");
System.out.println(type.getName()+" "+name+";");
}
}
}
如果对您有帮助,希望可以博主一个关注。