Java——5个Demo带你学懂反射机制中最基础最重要的内容

Posted 张起灵-小哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java——5个Demo带你学懂反射机制中最基础最重要的内容相关的知识,希望对你有一定的参考价值。

文章目录:

写在前面

关于JDK中自带的类加载器

Demo1:获取Class的三种方式

Demo2:如何通过反射机制访问一个Java对象的属性?(Field)

Demo3:如何通过反射机制调用一个对象的方法?(Method)

Demo4:如何通过反射机制创建一个对象?(Constructor)

Demo5:给你一个类,如何获取这个类的父类、已实现的接口?


写在前面

  • 反射机制有什么用?
            通过java语言中的反射机制可以操作字节码文件。
            优点类似于黑客。(可以读和修改字节码文件。)
            通过反射机制可以操作代码片段。(class文件。)
  • 反射机制的相关类在哪个包下?
            java.lang.reflect.*;
  • 反射机制相关的重要的类有哪些?

               java.lang.Class:代表整个字节码,代表一个类型,代表整个类。

               java.lang.reflect.Method:代表字节码中的方法字节码。代表类中的方法。

               java.lang.reflect.Constructor:代表字节码中的构造方法字节码。代表类中的构造方法

               java.lang.reflect.Field:代表字节码中的属性字节码。代表类中的成员变量(静态变量+实例变量)。

//java.lang.Class:
public class User{
    // Field
    int no;

    // Constructor
    public User(){
				
    }

    public User(int no){
	this.no = no;
    }

    // Method
    public void setNo(int no){
	this.no = no;
    }

    public int getNo(){
	return no;
    }
}

关于JDK中自带的类加载器

  • 什么是类加载器?
            专门负责加载类的命令/工具。
            ClassLoader
  • JDK中自带了3个类加载器
            启动类加载器: rt.jar
            扩展类加载器: ext/*.jar
            应用类加载器: classpath
  • 首先通过 “启动类加载器” 加载。如果通过 “启动类加载器” 加载不到的时候,会通过 "扩展类加载器" 加载。如果 “扩展类加载器” 没有加载到,那么会通过 “应用类加载器” 加载。
  • java中为了保证类加载的安全,使用了双亲委派机制。
            优先从启动类加载器中加载,这个称为“父”;“父”无法加载到,再从扩展类加载器中加载,这个称为“母”。双亲委派。如果都加载不到,才会考虑从应用类加载器中加载。直到加载到为止。

Demo1:获取Class的三种方式

package com.szh.reflect;

import java.util.Date;

/**
 * 要操作一个类的字节码,需要先获取这个类的字节码
 * 怎么获取 java.lang.Class 实例?
 *      Class.forName()
 *      1.静态方法
 *      2.方法的参数是一个字符串
 *      3.字符串必须是一个完整类名的全限定名称
 */
public class ReflectTest01 {

    public static void main(String[] args) {
        /*
            Class.forName()
              1.静态方法
              2.方法的参数是一个字符串
              3.字符串必须是一个完整类名的全限定名称
         */
        try {
            //c1代表String.class文件,或者说c1代表String类型,下面c2、c3、c4同理
            Class c1=Class.forName("java.lang.String");
            Class c2=Class.forName("java.util.Date");
            Class c3=Class.forName("java.lang.Integer");
            Class c4=Class.forName("java.lang.System");
            System.out.println(c4.getName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        //Java中任何一个对象都有一个方法:getClass()
        String s="abc";
        //x代表String.class文件,或者说x代表String类型
        Class x=s.getClass();
        System.out.println(x.getName());

        //Java中任何一种类型(包括基本数据类型),都有一个 class 属性
        Class z=String.class;
        Class i= Date.class;
        Class j=int.class;
        Class k=Double.class;
        System.out.println(i.getName());
    }
}

Demo2:如何通过反射机制访问一个Java对象的属性?(Field)

package com.szh.bean;

/**
 *
 */
public class Student {

    public int id;
    private String name;
    protected int age;
    boolean sex;
}
package com.szh.reflect;

import java.lang.reflect.Field;

/**
 * 必须掌握:如何通过反射机制访问一个Java对象的属性?
 *          给属性赋值 set
 *          获取属性的值 get
 */
public class ReflectTest07 {

    public static void main(String[] args) throws Exception {
        //通过反射机制获取Class,通过Class实例化对象
        Class studentClass=Class.forName("com.szh.bean.Student");
        //newInstance() 这个方法会调用Student类中的无参构造方法,完成对象的创建
        //obj此时是一个Student对象
        Object obj=studentClass.newInstance();

        //获取公共属性:id
        Field idField=studentClass.getDeclaredField("id");
        //给obj对象的id属性赋值
        idField.set(obj,1001);
        //获取obj对象的id属性值
        System.out.println(idField.get(obj));

        //获取私有属性:name
        Field nameField=studentClass.getDeclaredField("name");
        //打破封装
        nameField.setAccessible(true);
        //给obj对象的name属性赋值
        nameField.set(obj,"张起灵");
        //获取obj对象的name属性值
        System.out.println(nameField.get(obj));
    }
}

Demo3:如何通过反射机制调用一个对象的方法?(Method)

package com.szh.bean;

/**
 *
 */
public class UserService {

    public boolean login(String username,String password) {
        if ("root".equals(username) && "12345678".equals(password)) {
            return true;
        }
        return false;
    }

    public void logout() {
        System.out.println("成功退出!");
    }
}
package com.szh.reflect;

import java.lang.reflect.Method;

/**
 * 必须掌握:通过反射机制调用一个对象的方法
 */
public class ReflectTest08 {

    public static void main(String[] args) throws Exception {
        //获取类
        Class userServiceClass=Class.forName("com.szh.bean.UserService");
        //创建对象
        Object obj=userServiceClass.newInstance();
        //获取类中的Method
        Method loginMethod=userServiceClass.getDeclaredMethod("login", String.class, String.class);
        //调用方法
        /*
            loginMethod 是方法
            obj 是对象
            "root","12345678" 是实参
            retValue 是返回值
            合起来:调用UserService类中的userService对象调用login方法,传入"root","12345678"实参,获取retValue返回值
         */
        Object retValue=loginMethod.invoke(obj,"root","12345678");
        System.out.println(retValue);
    }
}

Demo4:如何通过反射机制创建一个对象?(Constructor)

package com.szh.bean;

/**
 *
 */
public class Vip {

    public int no;
    public String name;
    public String birth;
    public boolean sex;

    public Vip() {
    }

    public Vip(int no) {
        this.no = no;
    }

    public Vip(int no, String name) {
        this.no = no;
        this.name = name;
    }

    public Vip(int no, String name, String birth) {
        this.no = no;
        this.name = name;
        this.birth = birth;
    }

    public Vip(int no, String name, String birth, boolean sex) {
        this.no = no;
        this.name = name;
        this.birth = birth;
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Vip{" +
                "no=" + no +
                ", name='" + name + '\\'' +
                ", birth='" + birth + '\\'' +
                ", sex=" + sex +
                '}';
    }
}
package com.szh.reflect;

import java.lang.reflect.Constructor;

/**
 * 必须掌握:通过反射机制创建一个对象
 */
public class ReflectTest09 {

    public static void main(String[] args) throws Exception {
        Class vipClass=Class.forName("com.szh.bean.Vip");

        //调用无参构造方法
        Constructor c=vipClass.getConstructor();
        Object obj=c.newInstance();
        System.out.println(obj);

        //调用有参构造方法
        //第一步:先获取这个对象的有参构造方法
        Constructor constructor=vipClass.getDeclaredConstructor(int.class,String.class,String.class,boolean.class);
        //第二步:调用有参构造方法new对象
        Object newObj=constructor.newInstance(1001,"张起灵","2000-05-01",true);
        System.out.println(newObj);
    }
}

Demo5:给你一个类,如何获取这个类的父类、已实现的接口?

package com.szh.reflect;

/**
 * 给你一个类,如何获取这个类的父类、已实现的接口
 */
public class ReflectTest10 {

    public static void main(String[] args) throws Exception {
        //String
        Class stringClass=Class.forName("java.lang.String");

        //获取String的父类
        Class superClass=stringClass.getSuperclass();
        System.out.println(superClass.getName());

        //获取String类实现的所有接口
        Class[] strings=stringClass.getInterfaces();
        for (Class c : strings) {
            System.out.println(c.getName());
        }
    }
}

 

以上是关于Java——5个Demo带你学懂反射机制中最基础最重要的内容的主要内容,如果未能解决你的问题,请参考以下文章

带你学懂

图像分类一文带你学懂经典网络GoogLeNet

Carson带你学Android:手把手带你深入分析事件分发机制!

Java Demo 学习 理解 反射机制 (基础学习)

一文带你了解Java反射机制

跟我20天学Java:03-6个案例手把手带你学循环结构