致自己:Java学习笔记之初识反射

本文详细介绍了Java反射机制,包括反射的概念、获取Class对象的三种方式、通过反射创建对象、访问和修改对象属性、调用方法、反编译类和构造方法,以及实例化对象等。此外,还展示了如何利用反射调用类的静态方法和获取类的父类信息。
摘要由CSDN通过智能技术生成

反射

一、认识反射机制

1、反射的基本概念

1.1、反射是指程序可以访问、检测和修改它本身状态或行为的一种能力, 并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

1.2、反射工作机制:程序运行时,java 系统会一直对所有对象进行所谓的运行时类型识别,这项信息记录了每个对象所属的类,通过专门的类可以访问这些信息,用来保存这些信息的类是class 类,class 类为编写可动态操纵的 java 代码程序提供了强大功能。

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

1、第一种方式

1.1、Class c = Class.forName(“带包名的完整类名”);

package reflect;

public class Test1 {
    public static void main(String[] args){
        //获取Class对象的第一种方式:Class c = Class.forName("带包名的完整类名");
        try {
            Class strClass = Class.forName("java.lang.String");
            Class dateClass = Class.forName("java.util.Date");
            Class intClass = Class.forName("java.lang.Integer");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
2、第二种方式

2.1、Class c = 对象.getClass();

package reflect;

public class Test1 {
    public static void main(String[] args) {
        //获取Class对象的第二种方式:Class c = 对象.getClass();
        Class strClass = null;
        try {
            strClass = Class.forName("java.lang.String");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        //java中任何一个对象都有一个方法:getClass()
        String s = "abc";
        Class str = s.getClass();
        //  true(==判断的是对象的内存地址
        System.out.println(strClass == str);
    }
}
3、第三种方式

3.1、Class c = 任何类型.class;

package reflect;

import java.util.Date;

public class Test1 {
    public static void main(String[] args) {
        //获取Class对象的第二种方式:Class c = 任何类型.class;
        //Java语言中任何一种类型,包括基本数据类型。都有.class属性
        Class str = String.class;
        Class date = Date.class;
        Class i = int.class;
        Class d = double.class;
    }
}

三、获取类来实例化对象

1、通过反射机制创建对象

1.1、代码示例

package reflect;

/*
    通过Class对象的newInstance()方法来实例化对象
    newInstance()其实内部调用的是无参构造方法,
    所以必须保证无参构造方法存在
 */
public class Test2 {
    public static void main(String[] args) {
        //不使用反射机制创建对象
        User user1 = new User();
        System.out.println("Usr1 = " + user1);

        //通过反射机制创建对象
        try {
            //获取Class对象
            Class c = Class.forName("reflect.User");
            //通过Class来实例化对象
            Object user2 = c.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
}

1.2、Class.forName(“完整类名”);方法的执行会导致类加载

package reflect;

public class MyClass {
    static {
        System.out.println("MyClass类的静态代码块执行了");
    }
}
package reflect;

/*
    Class.forName("完整类名");
    此方法的执行会导致类加载,类加载时静态代码块会执行
    如果你只是希望一个类的静态代码块执行,其它代码一律不执行,
    你可以使用此方法
 */
public class Test3 {
    public static void main(String[] args) {
        try {
            Class c = Class.forName("reflact.MyClass"); //MyClass类的静态代码块执行了
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
2、通过反射机制获取类中所有field

2.1、代码示例

package reflact;

public class Student {
    private String name;
    private int age;
    boolean sex;
    public int num;
    public static final double PI = 3.1415926;
}
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

/*
    通过反射机制获取Student类中的所有field
 */
public class Test4 {
    public static void main(String[] args) throws ClassNotFoundException {
        //创建这个为了拼接字符串
        StringBuilder str = new StringBuilder();
        //通过反射机制获取Student类
        Class c = Class.forName("reflect.Student");
        str.append(Modifier.toString(c.getModifiers()) + "class" + c.getSimpleName() + "{\n");
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            str.append("\t");
            str.append(Modifier.toString(field.getModifiers()));
            str.append(" ");
            str.append(field.getType().getSimpleName());
            str.append(" ");
            str.append(field.getName());
            str.append(";\n");
        }
        str.append("}");
        System.out.println(str);
    }
}
3、通过反射机制访问java对象的属性

3.1、代码示例

public class Student {
    private String name;
    private int age;
    boolean sex;
    public int num;
    public static final double PI = 3.1415926;
}
import java.lang.reflect.Field;

public class Test5 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        //通过反射机制访问对象的属性
        Class c = Class.forName("reflact.Student");
        //obj即是Student对象,底层是调用了无参构造方法
        Object obj = c.newInstance(); 

        //获取num属性,根据属性的名称获取
        Field numField = c.getDeclaredField("num");
        //给obj对象(Student对象)的num属性赋值
        numField.set(obj,1001);
        //获取属性的值
        System.out.println("numValue = " + numField.get(obj));

        //获取私有属性
        Field nameField = c.getDeclaredField("name");
        //打破封装,设置之后,在外部也可以访问private
        nameField.setAccessible(true);
        //给name属性赋值
        nameField.set(obj,"jack");
        //获取name属性的值
        System.out.println("nameValue = " + nameField.get(obj));
    }
}
4、反射Method

4.1、代码示例

public class UserService {
    //登陆方法
    public boolean login(String name,String password){
        if("admin".equals(name) && "123".equals(password)){
            return true;
        }
        return false;
    }

    public void login(int i) {
        System.out.println("您已登陆系统");
    }

    public void logout() {
        System.out.println("您已退出系统");
    }
}
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

//反射Method
public class Test6 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取类
        Class userClass = Class.forName("reflect.UserService");
        //获取所有的Method,包括私有的
        Method[] methods = userClass.getDeclaredMethods();
        System.out.println("方法的数量:" + methods.length);
        //遍历Method
        for (Method method : methods) {
            //获取修饰符列表
            System.out.println(Modifier.toString(method.getModifiers()));
            //获取方法的返回值类型
            System.out.println(method.getReturnType().getSimpleName());
            //获取方法名
            System.out.println(method.getName());
            //获取方法的修饰符列表,一个方法可能有多个
            Class[] parametreTypes = method.getParameterTypes();
            for (Class parameterType : parametreTypes) {
                System.out.println(parameterType.getSimpleName());
            }
        }
    }
}
5、反编译一个类的方法

5.1、代码示例

package reflect;

public class UserService {
    //登陆方法
    public boolean login(String name,String password){
        if("admin".equals(name) && "123".equals(password)){
            return true;
        }
        return false;
    }

    public void login(int i) {
        System.out.println("您已登陆系统");
    }

    public void logout() {
        System.out.println("您已退出系统");
    }
}
package reflect;

//反编译一个类的方法

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Test7 {
    public static void main(String[] args) throws ClassNotFoundException {
        //为了拼接字符串
        StringBuilder s = new StringBuilder();
        Class c = Class.forName("reflect.UserService");
        s.append(Modifier.toString(c.getModifiers()) + "class" + c.getSimpleName() + "{\n");
        //获取所有方法
        Method[] methods = c.getDeclaredMethods();
        //遍历方法
        for (Method method : methods) {
            s.append("\t");
            //获取修饰符
            s.append(Modifier.toString(method.getModifiers()));
            s.append(" ");
            //获取返回值
            s.append(method.getReturnType().getSimpleName());
            s.append(" ");
            //获取方法名
            s.append(method.getName());
            s.append(" (");
            //获取参数列表
            Class[] paramTypes = method.getParameterTypes();
            //遍历参数列表
            for (Class paramType : paramTypes) {
                s.append(paramType.getSimpleName());
                s.append(",");
            }
            //删除指定下标位置上的字符
            s.deleteCharAt(s.length()-1);
            s.append(") {}\n");
        }
        s.append("}");
        System.out.println(s);
    }
}
6、通过反射机制调用类的方法

6.1、示例代码

package reflect;

public class UserService {
    //登陆方法
    public boolean login(String name,String password){
        if("admin".equals(name) && "123".equals(password)){
            return true;
        }
        return false;
    }

    public void login(int i) {
        System.out.println("您已登陆系统");
    }

    public void logout() {
        System.out.println("您已退出系统");
    }
}
package reflect;

//通过反射机制调用类的方法

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test8 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class c = Class.forName("reflect.UserService");
        //创建对象
        Object obj = c.newInstance();
        //获取方法
        Method loginMethod = c.getDeclaredMethod("login",String.class,String.class);
        //调用方法
        Object retValue = loginMethod.invoke(obj,"admin","123123");
        System.out.println(retValue);
       
        Method logoutMethod = c.getDeclaredMethod("logout");
        System.out.println(logoutMethod.invoke(obj));
    }
}
7、反编译一个类的构造方法

7.1、示例代码

package reflect;

//反编译一个构造方法

import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;

public class Test9 {
    public static void main(String[] args) throws ClassNotFoundException {
        //为了拼接字符串
        StringBuilder s = new StringBuilder();
        Class c = Class.forName("java.lang.String");
        s.append(Modifier.toString(c.getModifiers()) + "class" + c.getSimpleName() + "{\n");

        //拼接构造方法
        Constructor[] constructors = c.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            s.append("\t");
            //获取修饰符列表
            s.append(Modifier.toString(constructor.getModifiers()));
            s.append(" ");
            //获取构造方法名
            s.append(c.getSimpleName());
            s.append("(");
            //获取参数
            Class[] params = constructor.getParameterTypes();
            for (Class param : params){
                s.append(param.getSimpleName());
                s.append(",");
            }
            //删除多余下标位置上的字符
            if (params.length > 0){
                s.deleteCharAt(s.length()-1);
            }
            s.append("){}\n");
        }
        s.append("}");
        System.out.println(s);
    }
}
8、通过反射机制调用构造方法实例化对象

8.1、示例代码

package reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

//通过反射机制实例化对象
public class Test10 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class c = Class.forName("reflect.VipUser");
        //调用无参构造方法实例化对象
        Object obj = c.newInstance();
        System.out.println("obj:" + obj);

        //获取有参构造方法
        Constructor con = c.getConstructor(int.class,String.class,String.class,boolean.class);
        //调用构造方法创建对象
        Object newObj = con.newInstance(110,"jack","2022-03-02",true);
        System.out.println("newObj:" + newObj);

        //获取无参构造方法
        Constructor con2 = c.getConstructor();
        Object newObj2 = con2.newInstance();
        System.out.println("newObj2:" + newObj2);
    }
}
9、获取一个类的父类

9.1、示例代码

package reflect;

//获取一个类的父类方法

public class Test11 {
    public static void main(String[] args) throws ClassNotFoundException {
        //String类型
        Class c = Class.forName("java.lang.Class");
        //获取String的父类
        Class superClass = c.getSuperclass();
        System.out.println("String的父类是:" + superClass.getSimpleName());

        //获取String类实现的所有接口
        Class[] interfaces = c.getInterfaces();
        for (Class in : interfaces){
            System.out.println(in.getName());
        }
    }
}
10、获取文件中的内容

10.1、示例代码

//className=comztt

package reflect;

/*
    java.util包下提供了一个资源绑定器,便于获取属性配置文件中的内容。
    使用以下这种方式的时候,属性配置文件xxx.properties必须放到类路径下。
 */

import java.util.ResourceBundle;

public class Test12 {
    public static void main(String[] args) {
        // 资源绑定器,只能绑定xxx.properties文件,并且这个文件必须在类路径下,文件扩展名也必须是properties
        // 并且在写路径的时候,路径后面的扩展名不能写
        ResourceBundle bundle = ResourceBundle.getBundle("reflect/db");
        String className = bundle.getString("className");
        System.out.println(className);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值