3.反射机制

1.反射机制概述

(1)reflection反射机制被视为动态语言(运行时改变内部结构的语言)的关键,借助于反射API取得任何累的内部信息,并能直接操作任意对象的内部属性和方法。

(2)加载完类之后,在堆内存的方法中就产生了一个Class类型的对象,这个对象包含了完整的类的结构信息,可以通过这个类看到类的结构。

// 反射: 实例化对象---------》getclass()方法---------------》得到完整的“包类”信息

(3)功能:

在运行时 判断对象所属的类、构造任意一个类的对象、判断任意一个类所具有的成员变量和方法、获取泛型信息 、调用任意一个对象的成员变量和方法、处理注解,生成动态代理

API:java.lang.Class 代表一个类

java.lang.reflect.Method 代表类方法

java.lang.reflect.Field 代表类的成员变量

java.lang.reflect.Construtor 代表类的构造器

package com.qiku.reflection;

import org.junit.Test;

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

/**
 * 2022/6/1 21:19
 *
 * @author yrc
 * @version JavaSE
 */
public class TestReflection {
    //反射之前
    @Test
    public  void test01(){
        //创建Person对象
        Person p1 = new Person("tom",12);
        p1.age=10;
        System.out.println(p1);//Person{name='tom', age=10}
        p1.show();
        //不可调用其私有的成员变量和方法 例如 name 和shownation()

    }
    //反射之后 对于Person的操作
    @Test
    public  void test02() throws Exception {
        Class cc= Person.class;
        // 通过反射 创建 person对象
        Constructor cons = cc.getConstructor(String.class, int.class);

        Object obj = cons.newInstance("Tom", 12);

        Person p=(Person)obj;
        System.out.println(p.toString());
        //通过反射 获取对象指定的属性和方法
        Field age = cc.getDeclaredField("age");
        age.set(p,10);//
        System.out.println(p.toString());//Person{name='Tom', age=10}
        Method show = cc.getDeclaredMethod("show");
        System.out.println(show);
        //通过反射 可以调用 Person类的私有属性,比如私有的构造器方法和属性

        //调用私有的构造器
        Constructor cons1 = cc.getDeclaredConstructor(String.class);
        //值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java
        // 语言访问检查;实际上setAccessible是启用和禁用访问安全检查的开关,并不是为true就能访问为false就不能访问 ;
        //由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的

        cons1.setAccessible(true);
        Person p1 =(Person) cons1.newInstance("Jerry");
        System.out.println(p1);
        //调用私有的属性
        Field name = cc.getDeclaredField("name");
        name.setAccessible(true);
        name.set(p1,"Jack");
        System.out.println(p1);
        //调用私有的方法
        Method showNation = cc.getDeclaredMethod("showNation",String.class);
        showNation.setAccessible(true);
        //相当于  p1.showNation("中国"); 调用完此方法有个返回值  invoke的返回值就是nation
        String nation = (String)showNation.invoke(p1, "中国");
        System.out.println(nation);

        //通过直接new对象的方式或者反射的方式都能调用公共的结构 ,开始之中到底用哪一个?
        //  建议直接用new的方式。反射的特征:动态性
       //反射机制与面向对象的封装性是否矛盾?如何看待两种技术
        // 封装性写一些实体类的时候使用 比如单例模式,提供一个私有的构造器 但是提供了个公开的方法  ,返回的是私有的静态对象
        //反射解决的是能不能调的问题
        /*
        java.lang.Class类的理解
        1.类加载的过程:
        程序经过javac.class命令以后,会生成一个或者多个字节码文件(.class结尾) 接着使用java.exe命令对某个字节码文件进行解析
        运行。相当于将字节码文件加载到内存中,此过程就是类的加载加载到内存中的类,我们就称为运行时类此运行时类就作为Class的
        一个实例。
        2.on The other hand  :Class的实例就对应着一个运行时类。
        3.加载到内存中的运行时类,会缓存一定的时间,在此时间之内,我们可以通过不同的方式来获取运行时类。
         */

    }
    //获取Class的实例方式
    @Test
    public void test03() throws ClassNotFoundException {
     //方式一:调用运行时类的属性:.class  泛型之后就不用强转了
        Class<Person> cc1 = Person.class;
        System.out.println(cc1);
        // 方式二 通过运行时对象调用 getClass()
        Person p1= new Person();
        Class cc2 = p1.getClass();
        System.out.println(cc2);
        //方式三: 通过嗲用Class的静态方法 forName(String classPath)
        Class cc3 = Class.forName("com.qiku.reflection.TestReflection");
        System.out.println(cc3);
        System.out.println(cc1==cc2);
        System.out.println(cc1==cc3);
        //方式四:类的加载器ClassLoader
        ClassLoader classLoader = TestReflection.class.getClassLoader();
        Class cc4 = classLoader.loadClass("com.qiku.reflection.TestReflection");
        System.out.println(cc4);
        System.out.println(cc1==cc4);
        //编译不确定 具有动态性  第三种方式最重要
    }
    //class.  看i意识int,String, 数组 枚举类 注解 Class等等 ,还有只要数组的类型和维度一样 就是同一个Class

}

package com.qiku.reflection;

import org.junit.Test;

import java.io.InputStream;
import java.util.Properties;

/**
 * 2022/6/6 21:30
 *
 * @author yrc
 * @version JavaSE
 */
public class TestClassLoader {
    @Test
    public void test01(){
        //对于自定义类  调用系统加载器进行加载
        ClassLoader classLoader = TestClassLoader.class.getClassLoader();
        System.out.println(classLoader);
        //调用系统加载器的getParent()获取扩展类加载器
        ClassLoader parent = classLoader.getParent();
        System.out.println(parent);
        //调用系统加载器的getParent()无法获取扩展类加载器
        //引导加载器主要负责加载java的核心类库 无法加载自定义类的
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);
    }
    @Test
    public  void test02() throws Exception {
//        properties 读取配置文件
        Properties properties =new Properties();
//        FileInputStream fis= new FileInputStream("jdbc.properties");
//        properties.load(fis);
      ClassLoader classLoader = ClassLoader.class.getClassLoader();
        InputStream resourceAsStream = classLoader.getResourceAsStream("jdbc.properties");
        properties.load(resourceAsStream);


        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        System.out.println("user"+user+"password"+password);

    }
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值