国王陛下万万岁

导航

 

在学习java的spring框架时老是要与java的反射机制打交道,为止花了一些时间来了解java的反射机制。

在创建数据库的jdbc也有遇到java的反射机制比如MySQL的JDBC,Class.forName("com.mysql*").

 

一:Java的反射(reflection)是什么?

我的一个大概的理解是:java反射是用来获取一个java类本身的一些信息,比如类里面声明的静态变量,实例变量,公有方法,私有方法。

除此之外,反射机制还能帮我们获取,或者创建一个类的对象。

Java的反射机制主要通过Java.lang.Class和Java.lang.reflect包下的API来实现的,而且java反射机制是与运行中的JVM打交道的。

 

来看Oracle官方文档对反射机制的两种解释:

解释一:

Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, 
and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security
restrictions. The API accommodates applications that need access to either the public members of a target
object (based on its runtime class) or the members declared by a given class. It also allows programs to
suppress default reflective access control.

 

解释二:

Reflection is a feature in the Java programming language. It allows an executing Java program to examine or "introspect" upon itself,
and manipulate internal properties of the program. For example, it's possible for a Java class to obtain the names of all its members
and display them.

The ability to examine and manipulate a Java class from within itself may not sound like very much, but in other programming languages
this feature simply doesn't exist. For example, there is no way in a Pascal, C, or C++ program to obtain information about the
functions defined within that program.
One tangible use of reflection is in JavaBeans, where software components can be manipulated visually via a builder tool.
The tool uses reflection to obtain the properties of Java components (classes) as they are dynamically loaded.

 

二: 示例

先写一个java类

package com.qa.reflection;

public class Student {
    private String studentName;
    public int studentAge;
    public Student(){
        System.out.println("This is a public Constructor without arguments.");
    }

    private Student(String studentName){
        this.studentName=studentName;
        System.out.println("This is a private constructor with argument.");
    }

    public void setStudentAge(int studentAge) {
        this.studentAge = studentAge;
        System.out.println("This is a public method with argument, to set student Age.");
    }

    private String show(){
        System.out.println("This is a private method, show massage.");
        System.out.println("Show massage,student name:"+studentName+"--Student Age:"+studentAge);
        return "Show Method---------";
    }
}

上面的Student类里面既有public属性也有private属性

既有public方法也有private方法.

三:获取Class对象的三种方法

// 1.通过字符串获取Class对象,这个字符串必须带上完整路径名
Class studentClass = Class.forName("com.test.reflection.Student");
// 2.通过类的class属性
Class studentClass2 = Student.class;
// 3.通过对象的getClass()函数
Student studentObject = new Student();
Class studentClass3 = studentObject.getClass();

其运行结果如下:

//以上三种获取Class对象的方法默认会调用无参数的构造方法
//并且:我们用了三种方式去获取Class对象,但实际上生成的对象是同一个,这是单例模式。

//注意这句输出结果,它表明反射机制默认调用了无参数构造方法。这句话是我们在编写Student()这个无参构造方法十加的。

This is a public Constructor without arguments.
查看Class的对象是否为同一个. Student Class1:
class com.qa.reflection.Student Student Class2:class com.qa.reflection.Student Student Class3:class com.qa.reflection.Student Student Class1==Student Class2:true Student Class2==Student Class3:true

 

 

以上三种获取Class对象的方法默认会调用无参数的构造方法
并且:我们用了三种方式去获取Class对象,但实际上生成的对象是同一个,这是单例

创建一个测试类

package com.qa.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/*
反射类的操作
*/

public class ReflectionTest {

    public static void main(String[] args) throws ClassNotFoundException {
        Class studentClass1 = Class.forName("com.qa.reflection.Student");
        Class studentClass2 =Student.class;
        Student stu=new Student();
        Class studentClass3=stu.getClass();

        System.out.println("查看Class的对象是否为同一个.");
        System.out.println("Student Class1:"+studentClass1.toString());
        System.out.println("Student Class2:"+studentClass2.toString());
        System.out.println("Student Class3:"+studentClass3.toString());
        System.out.println("Student Class1==Student Class2:"+(studentClass1==studentClass2));
        System.out.println("Student Class2==Student Class3:"+(studentClass2==studentClass3));

//     1. Class.getDeclaredFields()方法能够获取一个类里面声明的所有字段,而不管这个字段是public的还是private。
        Field[] declaredFieldList=studentClass1.getDeclaredFields();
        for(Field declaredField:declaredFieldList){
            System.out.println("Declared Filed:"+declaredField);
        }

//       2.获取所有公有的字段
        Field[] fieldList = studentClass1.getFields();
        for (Field field : fieldList) {
            System.out.println("-----获取公有字段-------");
            System.out.println("field: " + field);
        }

//        3.获取声明的所有构造方法
        System.out.println("-----获取所有构造方法-------");
        Constructor[] declaredConstructorList=studentClass2.getDeclaredConstructors();
        for(Constructor declaredConstructor:declaredConstructorList){
            System.out.println("Constructor:"+declaredConstructor);
        }
//        4.获取所有的public的构造方法
        System.out.println("-----获取公有构造方法-------");
        Constructor[] constructorList=studentClass3.getConstructors();
        for (Constructor constructor:constructorList) {
            System.out.println("Constructor:"+constructor);

//           5.获取所有声明的函数
            System.out.println("-----获取所有非构造方法-------");
            Method[] declaredMethodList = studentClass1.getDeclaredMethods();
            for (Method declaredMethod : declaredMethodList) {
                System.out.println("declared Method: " + declaredMethod);
            }
//           6.获取所有公有的函数
            System.out.println("-----获取所有public的非构造方法-------");
            Method[] methodList = studentClass2.getMethods();
            for (Method method : methodList) {
                System.out.println("method: " + method);
            }
        }
    }
}

 

测试类的运行结果如下:

"C:\Program Files\Java\jdk1.8.0_221\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=50543:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_221\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_221\jre\lib\rt.jar;D:\ideaSpace\out\production\ideaSpace" com.qa.reflection.ReflectionTest
This is a public Constructor without arguments.
查看Class的对象是否为同一个.
Student Class1:class com.qa.reflection.Student
Student Class2:class com.qa.reflection.Student
Student Class3:class com.qa.reflection.Student
Student Class1==Student Class2:true
Student Class2==Student Class3:true
Declared Filed:private java.lang.String com.qa.reflection.Student.studentName
Declared Filed:public int com.qa.reflection.Student.studentAge
-----获取公有字段-------
field: public int com.qa.reflection.Student.studentAge
-----获取所有构造方法-------
Constructor:public com.qa.reflection.Student()
Constructor:private com.qa.reflection.Student(java.lang.String)
-----获取公有构造方法-------
Constructor:public com.qa.reflection.Student()
-----获取所有非构造方法-------
declared Method: public void com.qa.reflection.Student.setStudentAge(int)
declared Method: private java.lang.String com.qa.reflection.Student.show()
-----获取所有public的非构造方法-------
method: public void com.qa.reflection.Student.setStudentAge(int)
method: public final void java.lang.Object.wait() throws java.lang.InterruptedException
method: public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
method: public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
method: public boolean java.lang.Object.equals(java.lang.Object)
method: public java.lang.String java.lang.Object.toString()
method: public native int java.lang.Object.hashCode()
method: public final native java.lang.Class java.lang.Object.getClass()
method: public final native void java.lang.Object.notify()
method: public final native void java.lang.Object.notifyAll()

Process finished with exit code 0

 

四:Java.lang.Class里面的部分方法

JAVA反射API

 

 

五:Oracle官方文档:

Reflcet API

https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/package-summary.html

Class 类

https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html

知乎

https://zhuanlan.zhihu.com/p/86293659

 

后记:

今天是2020年2月12日,农历正月十九,上海,晴朗。

由于武汉2019-nCov疫情,呆在家。

世界卫生组织正式把这个virus命名位SARS CoV2

SARS-CoV-2(Severe Acute Respiratory Syndrome Coronavirus 2)
COVID-19(Corona Virus Disease 2019)

 

posted on 2020-02-12 21:54  国王陛下万万岁  阅读(188)  评论(0编辑  收藏  举报