java反射机制

反射

在不修改源码的情况下来控制程序
ocp原则(开闭原则:不修改源码,扩容功能)

快速入门

修改properties的method 即可实现功能的修改

package reflect;

public class A {
    public String name = "Superman";

    public A() {
    }

    public A(String name) {
        this.name = name;
    }

    public void f(){
        System.out.println("hello,world");
    }
    public void f2(){
        System.out.println("今天你好!");
    }
}
/*
a.properties
classfullpath=reflect.A
method=f
*/
public class test {
   public static void main(String[] args) throws Exception {
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\a.properties"));
        String classfullpath = properties.getProperty("classfullpath");
        String methodName = properties.getProperty("method");
        //加载类 返回
        Class<?> aClass = Class.forName(classfullpath);
        System.out.println(aClass); //class reflect.A  哪个类的class对象
        System.out.println(aClass.getClasses()); //运行时态  [Ljava.lang.Class;@5cad8086
        System.out.println(aClass.getPackage().getName());//包名
        System.out.println(aClass.getName());//全类名
        //通过class 得到加载的类
        Object o = aClass.newInstance();
        //得到加载的类的 方法对象
        Method method = aClass.getMethod(methodName);
        //通过方法对象 来调用方法
        method.invoke(o);
        //获取成员变量 name
        Field field = aClass.getField("name"); //不能获取私有的变量
        System.out.println(field.get(o));
        //获取构造器
        Constructor<?> constructor = aClass.getConstructor();
        System.out.println(constructor);
        //获取带形参的构造器 形参的class对象
        Constructor<?> constructor1 = aClass.getConstructor(String.class);
        System.out.println(constructor1);

    }
}

反射机制 java reflection

1.反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息(成员变量,构造器,成员方法等)
2.加载玩类之后,在堆中就产生了一个Class对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到的类结构。

反射原理图

在这里插入图片描述

在这里插入图片描述

反射访问优化

setAccessible(false)

Class

传统 new A();
Class.forName
Class对象不是new 出来的是系统创建的

	 ClassLoader
	 public Class<?> loadClass(String name) throws ClassNotFoundException {
                return loadClass(name, false);
            }

某个类的class类对象,在内存中只有一份,类只能加载一次
每个类的实例都会记得是由那个Class实例所生的
在这里插入图片描述
Class对象放在堆中,类的字节码二进制数据是放在方法区的。类的元数据(包括 方法代码,变量名,方法名,访问权限等等)

获取Class对象

在这里插入图片描述

Properties properties = new Properties();
        properties.load(new FileInputStream("src\\a.properties"));
        String classfullpath = properties.getProperty("classfullpath");
        String methodName = properties.getProperty("method");

        // forName多用于配置文件,读取类的全路径 加载类
        Class<?> aClass = forName(classfullpath);
        System.out.println(aClass);
        //类名.class 多用于参数传递
        Class<A> aClass1 = A.class;
        System.out.println(aClass1);
        //有对象实例 直接getclass()  运行类型 就是这个类关联的Class对象
        A a = new A();
        System.out.println(a.getClass());

        //通过类加载器来获取
        ClassLoader classLoader = a.getClass().getClassLoader();
        System.out.println(classLoader.loadClass(classfullpath));
        //基本数据类型.class
        Class<Integer> integerClass = int.class;
        System.out.println(integerClass);
        //包装类
        Class<Integer> type = Integer.TYPE;
        System.out.println(type);

有Class对象的类型

在这里插入图片描述

类加载

静态加载:编译就加载相关的类(new)
动态加载:运行需要加载时才加载相关的类(forName)

在这里插入图片描述
在这里插入图片描述

加载

在这里插入图片描述

连接在这里插入图片描述在这里插入图片描述
//1. n1 是实例属性, 不是静态变量,因此在准备阶段,是不会分配内存
//2. n2 是静态变量,分配内存 n2 是默认初始化 0 ,而不是 20
//3. n3 是 static final 是常量, 他和静态变量不一样, 因为一旦赋值就不变 n3 = 30
public int n1 = 10;
public static int n2 = 20;
public static final int n3 = 30;

在这里插入图片描述

初始化

在这里插入图片描述

通过反射获取类结构信息

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

使用反射修改类的私有属性(爆破)

public class ReflectCreatInstance {
    public static void main(String[] args) throws Exception{
        Class<?> aClass = Class.forName("reflect.User");
        //无参构造器
        Object user = aClass.newInstance();
        //爆破属性
        Field name = aClass.getDeclaredField("name");
        name.setAccessible(true);
        name.set(user,"mary");
        //如果是static属性  Object 可以填null
        Field salary = aClass.getDeclaredField("salary");
        salary.setAccessible(true);
        salary.set(null,4999.9);
        System.out.println(user);
        //方法
        Method hello = aClass.getDeclaredMethod("hello",String.class);
        hello.setAccessible(true);
        hello.invoke(user,"jack");

        Method hi = aClass.getDeclaredMethod("hi");
        hi.setAccessible(true);
        hi.invoke(null);

        //有参构造器
        Constructor<?> constructor = aClass.getConstructor(int.class);
        Object user1 = constructor.newInstance(10);
        System.out.println(user1);
        //私有的构造器
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(int.class, String.class);
        declaredConstructor.setAccessible(true);//爆破
        Object user2 = declaredConstructor.newInstance(20, "rose");
        System.out.println(user2);


    }
}

class User{
    private int age = 1;
    private String name ="jack";
    private static  double salary = 999.9;

    public User() {
    }

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

    private User(int age, String name) {
        this.age = age;
        this.name = name;
    }

    private void hello(String name){
        System.out.println("hello"+name);
    }
    private static void hi(){
        System.out.println("hi");
    }
    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +  ", salary='" + salary + '\'' +
                '}';
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java反射机制是指在运行时动态地获取一个类的信息,并可以操作类的属性、方法和构造器等。Java反射机制可以使程序员在运行时动态地调用类的方法和属性,扩展类的功能,并可以实现注解、工厂模式以及框架开发等。 Java反射机制的原理如下:首先,Java编译器将Java源代码编译为字节码文件,字节码文件中包含着类的信息,这些信息包括类的名称、方法、属性和构造器等等。接着,Java虚拟机将字节码文件加载到内存中,然后通过类加载器将类加载到内存中形成一个类对象,这个类对象可以操作字节码文件中的信息。 使用Java反射机制的过程如下:首先获取类对象,通过类对象来获取类的构造器、属性、方法等信息,然后调用构造器来创建对象,通过属性获取和设置类的成员属性,通过方法调用类的方法等。 Java反射机制的优点是可以在运行时动态地得到类的信息,使得程序员在程序运行时能够对类进行更加灵活的操作,并可以使得程序更加通用化,同时也存在着一定的性能问题,因为Java反射机制需要Java虚拟机进行一定的额外处理,所以在程序运行时需要进行额外的时间和资源消耗。 总之,Java反射机制Java语言的一项重要特性,在Java开发中广泛应用,在代码编写、框架开发以及API开发中具有重要作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值