java反射基本知识

1.反射是什么

反射机制:指在运行状态下,对于任意一个类,可以知道该类的属性和方法、并且可以调用它们;这种动态获取信息以及动态调用对象方法的功能成为Java 语言的反射机制。 现有的框架都以反射为基础,是将框架和类揉在一起的调和剂。

2.反射核心类

2.1 Class类

Class为反射核心类,Class第一个字母为大写,注意不是class,在运行的时候,jvm中只会含有一份Class对象。先创建一个A类,下面所有的例子均以此为基础。

public class A {
    public String address;
    private int age;
    private String name;

    public A() {
    }
    public A(int age, String name) {
        this.age = age;
        this.name = name;
    }
    private A (int age){
    }

    public int getAge() {
        return age;
    }

    @Deprecated
    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private void setAge1(int age){
        this.age = age;
    }
    @Override
    public String toString() {
        return "A{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

创建Class对象有三种方式。

 //一:得到Class的三种方式
    //1.使用class静态成员变量
    Class c1 = A.class;
    //2.使用对象的getClass()
    Class c2 = a.getClass();
    //3.通过路径名得到
    Class c3 = Class.forName("reflex.A");
     
	//验证是否相等
    System.out.println(c1==c2);
    System.out.println(c2==c3);

    //打印结果为:
    true
    true

打印结果均为true,说明不管用哪种方式得到的Class对象,都是同一个。

2.2 创建一个对象的方法

由于可以通过Class类得到该类的属性和方法,这样的话,也会导致创建该类的对象有多种。

 	//第一种方式new
    A b = new A();
    //第二种方式,通过得到的Class对象的newInstance();
    A c = (A) c1.newInstance();
    //第三种方式,通过用Constructor对象的 newInstance()方法,参数为Class类型。
    Constructor constructor = c1.getConstructor(int.class,String.class);
    A d = (A) constructor.newInstance(18,"zhangsan");
   
    //打印结果为: 
    A{age=0, name='null'}
    A{age=0, name='null'}
    A{age=18, name='zhangsan'}

3.Constructor类

通过Class对象得到该类的构造函数的方法,主要有四种,区别在于指定、所有、还有公有等。

//第一种方式:返回类的特定的public的构造函数,参数可以指定
Constructor Constructor1 = c1.getConstructor(int.class,String.class);
System.out.println("第一种方式:");
System.out.println(Constructor1);

//第二种方式:返回类的所有的public的构造函数
Constructor[] Constructor2 = c1.getConstructors();
System.out.println("第二种方式:");
for(Constructor constructor : Constructor2){
	System.out.println(constructor);
}
//第三种方式:返回类的特定的构造函数(不限制为Public),参数可以指定
Constructor Constructor3 = c1.getDeclaredConstructor(int.class);
System.out.println("第三种方式:");
System.out.println(Constructor3);

//第四种方式:返回类的所有的构造函数
Constructor[] Constructor4 = c1.getDeclaredConstructors();
System.out.println("第四种方式:");
for(Constructor constructor : Constructor4){
	System.out.println(constructor);
}

//打印结果为:
第一种方式:
public reflex.A(int,java.lang.String)
第二种方式:
public reflex.A(int,java.lang.String)
public reflex.A()
第三种方式:
private reflex.A(int)
第四种方式:
private reflex.A(int)
public reflex.A(int,java.lang.String)
public reflex.A()

4.Field类

通过Class对象得到该类的方法,主要有四种,区别在于指定、所有、还有公有等。

//第一种方式:通过getField(),根据名称获取public成员变量
Field field1 = c1.getField("address");
System.out.println("第一种方式");
System.out.println(field1);

//第二种方式:通过getFields()获取所有的public成员变量
Field[] fields2 = c1.getFields();
System.out.println("第二种方式");
for(Field field:fields2){
	System.out.println("成员变量名称:" +field.getName());
}

//第三种方式:通过getDeclaredField(),根据名称获取成员变量,不包含父类
Field field3 = c1.getDeclaredField("age");
System.out.println("第三种方式");
System.out.println(field3);
//第四种方式:通过getDeclaredFields(),获取所有的成员变量,不包含父类
Field[] fields4 = c1.getDeclaredFields();
System.out.println("第四种方式");
for(Field field:fields4){
	System.out.println("成员变量名称:" +field.getName());
}

//打印结果为:
第一种方式
public java.lang.String reflex.A.address
第二种方式
成员变量名称:address
第三种方式
private int reflex.A.age
第四种方式
成员变量名称:address
成员变量名称:age
成员变量名称:name

5.Method类

通过Class对象得到该类的变量,区别在于指定、所有、还有公有等

 //第一种方法:使用getMethod()得到指定的public方法,第一个参数方法名,后面为参数类对应的Class对象
    Method method1 = c1.getMethod("setAge",int.class);
    System.out.println("第一种方法:");
    System.out.println(method1);
    //使用invoke调用方法,a是对象
    method1.invoke(a,20);
    System.out.println(a.getAge());
    
    //第二种方法:使用getMethods()得到所有的public方法,包括父类的Public方法
    Method[] methods2 = c1.getMethods();
    System.out.println("第二种方法:");
    for (Method method:methods2){
    	System.out.println(method);
    }
    //第三种方法:使用getDeclaredMethod()得到指定的方法,第一个参数方法名,后面为参数类对应的Class对象
    Method method3 = c1.getDeclaredMethod("setAge1", int.class);
    System.out.println("第三种方法:");
    System.out.println(method3);
    
    //第四种方法:getDeclaredMethods()得到所有的方法,不包括父类的方法
    Method[] methods4 = c1.getDeclaredMethods();
    System.out.println("第四种方法:");
    for (Method method:methods4){
    	System.out.println(method);
    }

    //打印结果为:
    第一种方法:
    public void reflex.A.setAge(int)
    20
    第二种方法:
    public java.lang.String reflex.A.toString()
    public java.lang.String reflex.A.getName()
    public void reflex.A.setName(java.lang.String)
    public void reflex.A.setAge(int)
    public int reflex.A.getAge()
    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 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()
    第三种方法:
    private void reflex.A.setAge1(int)
    第四种方法:
    public java.lang.String reflex.A.toString()
    public java.lang.String reflex.A.getName()
    public void reflex.A.setName(java.lang.String)
    private void reflex.A.setAge1(int)
    public void reflex.A.setAge(int)
    public int reflex.A.getAge()

另外还可以得到该方法的参数、返回类型、方法名以及是否含有注解等基本信息。

 //得到类的方法,可以方法的名称、返回类型
    Method method5 = c1.getMethod("setAge",int.class);
    System.out.println("-------");
    //然后可以得到方法的返回值类型的类类型
    Class returnType = method5.getReturnType();
    //得到方法的返回值类型的名字
    System.out.println("方法的返回类型:"+returnType.getName()+" ");
    //得到方法的名称
    System.out.println("方法的名称:"+method5.getName() + " ");
    //得到方法的参数
    Class[] paramTypes = method5.getParameterTypes();
    for (Class class1 : paramTypes) {
    	System.out.println("方法的参数:"+class1.getName()+" ");
    }
    Annotation[] annotations = method5.getAnnotations();
    for (Annotation annotation : annotations) {
    	System.out.println("注解:"+annotation+" ");
    }
    
    //打印的结果为:
    方法的返回类型:void 
    方法的名称:setAge 
    方法的参数:int 
    注解:@java.lang.Deprecated() 

6.总结

主要使用一个思维导图来概括一下基本的函数和内容。
在使用反射得到该类的信息时,基本步骤为:
1.首先得到该类的Class对象。
2.调用对应的方法,得到构造函数、方法、属性。
3.在上面的基础上,可以创建对象、调用函数、解析注解等操作
图1

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章