栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java 反射

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java 反射

1 基本概念
  1. 反射机制有什么用?
    通过反射机制可以操作字节码文件。
    反射机制让代码有很高的通用性,可变化的内容写到配置文件中,在使用中只需要修改配置文件,就能创建不同的对象,调用不同的方法,让代码有很高的重复利用率,符合OCP开发原则。
  1. 反射机制的相关类在哪个包? java.lang.reflect.*
  1. 反射机制重要的类
    Java.lang.Class :代表整个类
    Java.lang.reflect.Method :代表类中的方法(重要)
    Java.lang.reflect.Constructor :代表类中的构造函数
    Java.lang.reflect.Field : 代表类中的成员变量
  1. 反射机制的灵活性。
    Class.forName("完整的包名+类名")方法,只要在配置文件中修改"完整的包名+类名"就能改变获得的Class。
2 获取Class的三种方式

第一种:通过Class.forName("完整的包名+类名")方法
第二种:类对象的getClass()方法。这个方法是Object类中就有的,所有的类都有这个方法
第三种:通过类的.class属性,所有的类都有.class属性,可通过类.class获取
案例

public class Reflect {

    public static void main(String[] args) throws ClassNotFoundException {
        // 第一种:通过类名
        Class reflectClass1 = Class.forName("Reflect");
        // 第二种:通过类对象
        Reflect reflect = new Reflect();
        Class reflectClass2 = reflect.getClass();
        // 第三种:通过.Class属性
        Class reflectClass3 = Reflect.class;
        
        System.out.println(reflectClass1);
        System.out.println(reflectClass2);
        System.out.println(reflectClass3);
        System.out.println(reflectClass1 == reflectClass2 && reflectClass2 == reflectClass3);
    }
}

获取类的完整包名:

3 通过反射机制实例化对象
  • 通过newInstance()方法实例化对象:

通过newInstance()方法实例化对象,需要调用类中的无参构造方法,假如这个类没有无参构造方法则无法通过这个方式实例化对象。

package bean;

public class User {
    public User(){
        System.out.println("User的无参构造方法");
    }
}

package reflect;
public class Reflect2 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Class aClass = Class.forName("bean.User");
        Object user = aClass.newInstance();
    }
}

4 类的静态代码块执行

Class.forName("完整的包名+类名")方法执行,会导致类的静态代码块: static{}会执行,不需要返回值

5 获取文件的绝对路径 以流的形式直接返回

读取配置文件,或者资源。

  1. 文件一定要在src目录下
  2. 实际查找目录是编译后的out文件夹下
  3. 找不到.java文件,只能找到编译后的.class 文件
  4. 其他不需要编译的文件,直接使用原后缀
public class AboutPath {
    public static void main(String[] args) {
        
        String path = Thread.currentThread().getContextClassLoader().getResource("bean/User.class").getPath();
        System.out.println(path);
        
    }
}
  • 获得文件的数据流
        InputStream resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("File");

6 通过反射机制反编译Class文件
  1. 获取类名、属性名等:Class.getSimpleName();
  2. 获取类中的属性:获得全部属性:Class.getDeclaredFields();;获取public修饰的属性:Class.getFields();
  3. 获取修饰符:先获取修饰符的代号:Int Class.getModifiers();,通过代号获得修饰符Modifier.toString(Int);
  4. 获取类中的属性:Class field.getType();得到类型,在通过类型获得类型的名字:String Class.getSimpleName();
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

//通过反射将Class文件反编译
public class Reflect3 {
    public static void main(String[] args) throws ClassNotFoundException {
        StringBuilder stringBuilder = new StringBuilder();
        Class c = Class.forName("java.lang.Thread");
        String className = c.getSimpleName();//获得类名
        int modifiers = c.getModifiers();//类修饰符的代号
        String s = Modifier.toString(modifiers);//通过代号获得修饰符

        stringBuilder.append(s+" class "+className+"{n");
//        Field[] fields = c.getFields();//类中public修饰的属性
        Field[] fields = c.getDeclaredFields();//类中所有的属性
        System.out.println("类共有"+fields.length+"个属性");
        for (Field field : fields) {
            int modifiers1 = field.getModifiers();//属性修饰符的代号
            String s1 = Modifier.toString(modifiers1);//通过代号获得修饰符
            Class type = field.getType();//属性的类型
            String typeName = type.getSimpleName();//获得该类型的名字
            String name = field.getName();
            stringBuilder.append("t"+s1+" "+typeName+" "+name+";n");
        }
        stringBuilder.append("}n");
        System.out.println(stringBuilder);
    }
}

7 Field 给属性赋值
import java.lang.reflect.Field;

public class Reflact4 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        Class userClass = Class.forName("bean.User");
        // 使用newInstance()创建对象
        Object userObj = userClass.newInstance();
        Field number = userClass.getField("number");//如果要给属性赋值,属性的必须是public修饰的属性
        // 给userObj对象的number属性赋值
        number.set(userObj,123);
        System.out.println(number.get(userObj));
        //给私有属性赋值
        Field nameField = userClass.getDeclaredField("name");
        nameField.setAccessible(true);// 打破封装,name属性不是私有的了
        nameField.set(userObj,"jack");
        System.out.println(nameField.get(userObj));
    }
}
public class User {
    public int number;
    private String name;
    boolean sex;
    public boolean login(String name,int number){
        if (name.equals("admin") && number==123)
        return true;
        else return false;
    }
}

8 Method 的调用(重要)

调用哪个方法,第一需要方法名,第二需要参数

  1. 获取到Class
  2. 创建对象
  3. 获得该方法
  4. 调用方法,由于参数的不同,类中可能会有重构的方法,所以参数很重要

Object 返回的值 = 获取的方法.invoke(对象,参数(可变长度的参数))

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

public class Reflect5 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        Class userClass = Class.forName("bean.User");
        // 实例化对象
        Object userObj = userClass.newInstance();
        // 获得方法
        Method loginMethod = userClass.getDeclaredMethod("login", String.class, int.class);
        //执行方法,参数很重要(对象,方法的所有参数作为可变长度参数传入)
        Object result = loginMethod.invoke(userObj, "admin", 123);

        System.out.println(result);
    }
}
public class User {
    public int number;
    private String name;
    boolean sex;
    public boolean login(String name,int number){
        if (name.equals("admin") && number==123)
        return true;
        else return false;
    }
}

9 Constructor 构造方法

获得哪个构造方法,靠参数来区别.getDeclaredConstructor(参数);

import java.lang.reflect.Constructor;

public class Reflect6 {
    public static void main(String[] args) throws Exception {
        Class UserClass = Class.forName("bean.User");
        // 无参构造方法,参数为空
        Constructor constructor1 = UserClass.getDeclaredConstructor();
        Object user1 = constructor1.newInstance();
        System.out.println(user1);
        // 有参数的构造方法
        Constructor constructor2 = UserClass.getDeclaredConstructor(int.class, String.class, boolean.class);
        Object user2 = constructor2.newInstance(123, "jack", true);
        System.out.println(user2);
    }
}
10 获取父类和接口

获取父类:类.getSuperclass();
获取接口:类.getInterfaces()

public class Reflect7 {
    public static void main(String[] args) throws Exception {
        Class StringClass = Class.forName("java.lang.String");
        // 获取父类
        Class superclass = StringClass.getSuperclass();
        System.out.println("String类的父类:"+ superclass.getName());
        // 获取接口
        Class[] interfaces = StringClass.getInterfaces();
        System.out.println("String类的接口:");
        for (Class anInterface : interfaces) {
            System.out.println(anInterface.getName());
        }
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/826806.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号