Java中的反射

导读:本篇文章讲解 Java中的反射,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

1、反射机制

在程序运行状态中,对于任意一个类或对象,都能够获取到这个类的所有属性和方法(包括私有属性和方法),这种动态获取信息以及动态调用对象方法的功能就称为反射机制。通过反射,类对我们是完全透明的,可以获取类中的任何东西。

2、获取Class对象的三种方式

我们知道,Java是完全面向对象的,所以在Java的世界里任何事物都可以理解为对象,类也不例外,下面是获取Class对象的三种方式。

在这里插入图片描述

package com.demo;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException {

        //Source源代码阶段   Class.forName("全限定名")(常用)
        Class class1 = Class.forName("com.demo.Person");
        System.out.println("class1 = " + class1);

        //Class类对象阶段     类名.class
        Class class2 = Person.class;
        System.out.println("class2 = " + class2);

        //Runtime运行时阶段   对象.getClass()
        Person person = new Person();
        Class class3 = person.getClass();
        System.out.println("class3 = " + class3);
        
		//对比获取的对象是否相同
        System.out.println(class1==class2);
        System.out.println(class2==class3);
    }
}
class1 = class com.demo.Person
class2 = class com.demo.Person
class3 = class com.demo.Person
true
true

通过运行结果可证明,同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,无论通过哪一种方式获取的Class对象都是同一个。

3、Class对象的功能

  • 3.1 获取构造方法并调用
    • 3.1.1 获取

测试类

package com.demo;

import java.lang.reflect.Constructor;

public class Test {
    public static void main(String[] args) throws Exception {

        //获取Class对象
        Class studentClass = Class.forName("com.demo.Student");

        //获取单个public修饰的无参构造方法
        Constructor constructor1 = studentClass.getConstructor();
        System.out.println("constructor1 = " + constructor1);
        System.out.println();

        //获取单个public修饰的有多个参数的构造方法
        Constructor constructor2 = studentClass.getConstructor(String.class, String.class, int.class, int.class);
        System.out.println("constructor2 = " + constructor2);
        System.out.println();

        //获取单个构造方法(不论修饰符)
        Constructor constructor3 = studentClass.getDeclaredConstructor(String.class, int.class, int.class);
        System.out.println("constructor3 = " + constructor3);
        System.out.println();

        //获取所有public修饰的构造方法
        Constructor[] constructors1 = studentClass.getConstructors();
        for (Constructor constructor : constructors1) {
            System.out.println(constructor);
        }
        System.out.println();

        //获取所有的构造方法(不论修饰符)
        Constructor[] constructors2 = studentClass.getDeclaredConstructors();
        for (Constructor constructor : constructors2) {
            System.out.println(constructor);
        }
    }
}

Person类

package com.demo;

//@Setter 替代Setter方法
@Setter
//@Getter 替代Getter方法
@Getter
//替代toString方法
@ToString
public class Person {
    public String name;

    protected int age;

    char sex;

    private double height;

    //无参的公开构造
    public Person() {

    }

    //有多个参数的公开的有参构造
    public Person(String name, int age, char sex, double height) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.height = height;
    }

    //有一个参数的受保护的有参构造
    protected Person(String name) {
        this.name = name;
    }

    //有两个参数的default的有参构造
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //有多个参数的私有的有参构造
    private Person(String name, int age, char sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

Student类

package com.demo;

//@Setter 替代Setter方法
@Setter
//@Getter 替代Getter方法
@Getter
//替代toString方法
@ToString
public class Student extends Person {
    public String grade;

    protected String classname;

    int studentID;

    private int score;

    //无参的公开构造
    public Student() {

    }

    //有多个参数的公开的有参构造
    public Student(String grade,String classname, int studentID,int score) {
        this.grade = grade;
        this.classname=classname;
        this.studentID = studentID;
        this.score = score;
    }


    //有一个参数的受保护的有参构造
    protected Student(String grade) {
        this.grade = grade;
    }

    //有两个参数的default的有参构造
    Student(String grade, int studentID) {
        this.grade = grade;
        this.studentID = studentID;
    }

    //有多个参数的私有的有参构造
    private Student(String grade, int studentID,int score) {
        this.grade = grade;
        this.studentID = studentID;
        this.score = score;
    }
}

运行结果

constructor1 = public com.demo.Student()

constructor2 = public com.demo.Student(java.lang.String,java.lang.String,int,int)

constructor3 = private com.demo.Student(java.lang.String,int,int)

public com.demo.Student(java.lang.String,java.lang.String,int,int)
public com.demo.Student()

private com.demo.Student(java.lang.String,int,int)
com.demo.Student(java.lang.String,int)
protected com.demo.Student(java.lang.String)
public com.demo.Student(java.lang.String,java.lang.String,int,int)
public com.demo.Student()
  • 3.1.2 调用
package com.demo;

import java.lang.reflect.Constructor;

public class Test {
    public static void main(String[] args) throws Exception {

        //获取Class对象
        Class studentClass = Class.forName("com.demo.Student");

        //获取单个public修饰的无参构造方法
        Constructor constructor1 = studentClass.getConstructor();
        //调用public修饰的无参构造方法
        Object object1=constructor1.newInstance();
        System.out.println(object1+"\n"+object1.getClass()+"\n");

        //获取单个构造方法(不论修饰符)
        Constructor constructor2 = studentClass.getDeclaredConstructor(String.class);
        //调用protected修饰的有一个参数的有参构造
        Object object2=constructor2.newInstance("九年级");
        System.out.println(object2+"\n"+object2.getClass()+"\n");

        //获取单个构造方法(不论修饰符)
        Constructor constructor3 = studentClass.getDeclaredConstructor(String.class, int.class, int.class);
        /*
        调用private修饰的有多个参数的有参构造
        setAccessible(true)  暴力访问(忽略访问修饰符)
        只有private修饰的才需要暴力访问
        */
        constructor3.setAccessible(true);
        Object object3=constructor3.newInstance("八年级",202101,96);
        System.out.println(object3+"\n"+object3.getClass());
    }
}
Student{grade='null', classname='null', studentID=0, score=0}
class com.demo.Student

Student{grade='九年级', classname='null', studentID=0, score=0}
class com.demo.Student

Student{grade='八年级', classname='null', studentID=202101, score=96}
class com.demo.Student
  • 3.2 获取成员变量并调用
    • 3.2.1 获取

测试类

package com.demo;

import java.lang.reflect.Field;

public class Test {
    public static void main(String[] args) throws Exception {

        //获取Class对象
        Class studentClass = Class.forName("com.demo.Student");

        /*
          获取单个public修饰的成员变量(包括从父类中继承的成员变量)
          注意:Student类中未定义成员变量name
          */
        Field field1 = studentClass.getField("name");
        System.out.println("field1 = " + field1);
        System.out.println();

        //获取单个成员变量(不论修饰符)
        Field field3 = studentClass.getDeclaredField("score");
        System.out.println("field3 = " + field3);
        System.out.println();

        //获取所有public修饰的成员变量(包括从父类中继承的成员变量)
        Field[] fields1 = studentClass.getFields();
        for (Field field : fields1) {
            System.out.println(field);
        }
        System.out.println();

        //获取所有的成员变量(不论修饰符,不包括从父类中继承的成员变量)
        Field[] fields2 = studentClass.getDeclaredFields();
        for (Field field : fields2) {
            System.out.println(field);
        }
    }
}

Person类

package com.demo;

//替代toString()方法
@ToString
public class Person {
    public String name;

    protected int age;

    char sex;

    private double height;

    //无参的公开构造
    public Person() {

    }

    //有多个参数的公开的有参构造
    public Person(String name, int age, char sex, double height) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.height = height;
    }

    //有一个参数的受保护的有参构造
    protected Person(String name) {
        this.name = name;
    }

    //有两个参数的default的有参构造
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //有多个参数的私有的有参构造
    private Person(String name, int age, char sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

Student类

package com.demo;

//替代toString()方法
@ToString
public class Student extends Person {
    public String grade;

    protected String classname;

    int studentID;

    private int score;

    //无参的公开构造
    public Student() {

    }

    //有多个参数的公开的有参构造
    public Student(String grade,String classname, int studentID,int score) {
        this.grade = grade;
        this.classname=classname;
        this.studentID = studentID;
        this.score = score;
    }


    //有一个参数的受保护的有参构造
    protected Student(String grade) {
        this.grade = grade;
    }

    //有两个参数的default的有参构造
    Student(String grade, int studentID) {
        this.grade = grade;
        this.studentID = studentID;
    }

    //有多个参数的私有的有参构造
    private Student(String grade, int studentID,int score) {
        this.grade = grade;
        this.studentID = studentID;
        this.score = score;
    }
}

运行结果

field1 = public java.lang.String com.demo.Person.name

field3 = private int com.demo.Student.score

public java.lang.String com.demo.Student.grade
public java.lang.String com.demo.Person.name

public java.lang.String com.demo.Student.grade
protected java.lang.String com.demo.Student.classname
int com.demo.Student.studentID
private int com.demo.Student.score
  • 3.2.2 调用
package com.demo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class Test {
    public static void main(String[] args) throws Exception {

        //获取Class对象
        Class studentClass = Class.forName("com.demo.Student");

        //获取构造方法
        Constructor constructor=studentClass.getDeclaredConstructor(String.class,int.class,int.class);
        //暴力访问
        constructor.setAccessible(true);
        Object object1=constructor.newInstance("八年级",202102,94);
        System.out.println("object1 = " + object1);

        //获取public修饰的成员变量
        Field grade=studentClass.getField("grade");
        //调用public修饰的成员变量
        grade.set(object1,"九年级");
        //获取非public修饰的成员变量
        Field score= studentClass.getDeclaredField("score");
        //暴力访问(忽略访问修饰符)
        score.setAccessible(true);
        score.set(object1,90);
        System.out.println("object1 = " + object1);
    }
}
object1 = Student(grade=八年级, classname=null, studentID=202102, score=94)
object1 = Student(grade=九年级, classname=null, studentID=202102, score=90)
  • 3.3 获取成员方法并调用
    • 3.3.1 获取

测试类

package com.demo;

import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) throws Exception {

        //获取Class对象
        Class studentClass = Class.forName("com.demo.Student");

        /*
        获取单个public修饰的成员方法(包括从父类中继承的成员方法)
        注意:Student类中未重写eat方法
         */
        Method method1=studentClass.getMethod("eat");
        System.out.println("method1= " + method1);
        System.out.println();

        //获取单个成员方法(不论修饰符)
        Method method2=studentClass.getDeclaredMethod("fun4");
        System.out.println("method2 = " + method2);
        System.out.println();

        /*
        getMethods()  获取所有public修饰的成员方法(包括从父类中继承的方法,若该方法被重写,则只返回子类中重写的方法)
        注意:Student类中未重写eat方法,Object类是所有类的父类
        */
        Method[] methods1=studentClass.getMethods();
        for(Method method:methods1){
            System.out.println(method);
        }
        System.out.println();

        //getDeclaredMethods()  获取所有的成员方法(不论修饰符,不包括从父类中继承的方法)
        Method[] methods2=studentClass.getDeclaredMethods();
        for(Method method:methods2){
            System.out.println(method);
        }
    }
}

Person类

package com.demo;

//替代toString方法
@ToString
public class Person {

    public void play(){
        System.out.println("玩耍");
    }

    public void eat() {
        System.out.println("吃饭");
    }

    protected void sleep() {
        System.out.println("睡觉");
    }

    void run() {
        System.out.println("跑步");
    }

    private void study() {
        System.out.println("学习");
    }
}

Student类

package com.demo;

//替代toString方法
@ToString
public class Student extends Person {

    @Override
    public void play(){
        System.out.println("学生在玩耍");
    }

    public void fun1(int num) {
        System.out.println("fun1"+" "+num);
    }


    protected void fun2(){
        System.out.println("fun2");
    }

     void fun3() {
        System.out.println("fun3");
    }

    private void fun4(){
        System.out.println("fun4");
    }
}

运行结果

method1= public void com.demo.Person.eat()

method2 = private void com.demo.Student.fun4()

public java.lang.String com.demo.Student.toString()
public void com.demo.Student.fun1(int)
public void com.demo.Student.play()
public void com.demo.Person.eat()
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()

public java.lang.String com.demo.Student.toString()
public void com.demo.Student.fun1(int)
public void com.demo.Student.play()
void com.demo.Student.fun3()
protected void com.demo.Student.fun2()
private void com.demo.Student.fun4()
  • 3.3.2 调用
package com.demo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) throws Exception {

        //获取Class对象
        Class studentClass = Class.forName("com.demo.Student");

        //获取构造方法
        Constructor constructor= studentClass.getConstructor();
        Object object=constructor.newInstance();

        //获取public修饰的有参数的成员方法  
        Method method1=studentClass.getMethod("fun1", int.class);
        /*
        调用public修饰的成员方法,需要两个参数,一个是要调用的对象,一个是实参
        public void com.demo.Student.fun1(int)
        */
        method1.invoke(object,18);

        //获取非public修饰的成员方法
        Method method2=studentClass.getDeclaredMethod("fun4");
        //暴力访问(忽略访问修饰符)
        method2.setAccessible(true);
        method2.invoke(object);
    }
}
fun1 18
fun4
  • 3.4 反射main方法

在这里插入图片描述
测试类

package com.demo;

import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) throws Exception {
        //获取Class对象
        Class personClass = Class.forName("com.demo.Person");
        
        Method method=personClass.getMethod("main",(String[].class));

        method.invoke(null, (Object) new String[]{});
    }
}

Person类

package com.demo;

public class Person {
    public static void main(String[] args) {
        System.out.println("Person类的main方法");
    }
}

运行结果

Person类的main方法
  • 3.5 获取全类名

测试类

package com.demo;

public class Test {
    public static void main(String[] args) throws Exception {
        Person person = new Person();

        //获取Class对象
        Class personClass = person.getClass();

        System.out.println(personClass.getName());
    }
}

Person类

package com.demo;

public class Person {
   
}

运行结果

com.demo.Person

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/71533.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!