Notes21 day21_反射&枚举

本文详细阐述了Java中类的加载过程,包括加载、连接、验证、准备、解析和初始化等步骤,以及类加载器的作用和机制。此外,还介绍了反射如何通过Class对象操作类的方法和变量。

day21_反射&枚举

类加载器

类加载

当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过类的 【加载】,【连接】,【初始化】 这三个步骤来对类进行初始化。

一个类的生命周期包括了 "加载"、"验证"、"准备"、"解析"、"初始化"、"使用"、"卸载" 这七个阶段,==

类的加载

将编译后的字节码文件加载到内存中,以便在程序运行时使用。类加载器将字节码文件读取到内存,并创建对应的 Class 对象。

用于加载二进制数据,类的加载主要做三件事情:

找到类文件、放入方法区、开个入口

类的连接

==【验证阶段】:用于检验被加载的类是否有正确的内部结构,并和其他类协调一致==

==【准备阶段】:负责为类的类变量分配内存,并设置默认初始化值==

==【解析阶段】:将类的二进制数据中的符号(比如类、方法、字段的引用)替换为直接引用==

类的初始化

类的初始化的主要工作是为静态变量赋程序设定的初值。

类的初始化步骤
  • 假如类还未被加载和连接,则程序先加载并连接该类

  • 假如该类的直接父类还未被初始化,则先初始化其直接父类

  • 假如类中有初始化语句,则系统依次执行这些初始化语句

  • 注意:在执行第2个步骤的时候,系统对直接父类的初始化步骤也遵循初始化步骤1-3

类的初始化时机
  • 创建类的实例

  • 调用类的类方法

  • 访问类或者接口的类变量,或者为该类变量赋值

  • 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象

  • 初始化某个类的子类

  • 直接使用java.exe命令来运行某个主类

类加载器

作用

类加载器的作用,就是把class文件装进虚拟机,并为之生成对应的 java.lang.Class 对象

类加载机制

全盘负责、父类委托、缓存机制、双亲委派机制

双亲委派机制

好处

避免重复加载、保持一致性

Java中的内置类加载器

引导类加载器、扩展类加载器、系统类加载器、自定义类加载器

反射

可以通你这个对象拿到字节码文件,通过子节码文件还原到类的本身(也就是说你拿到类的Class对象去使用这个类的成员方法,成员变量,构造方法)

获取Class类对象的三种方式

  • 类名.class属性

  • 对象名.getClass()方法

  • Class.forName(全限定类名)方法

获取构造方法

方法名说明
Constructor<?>[] getConstructors()返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredConstructors()返回所有构造方法对象的数组
Constructor<T> getConstructor(Class<?>... parameterTypes)返回单个公共构造方法对象
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)返回单个构造方法对象

用于创建对象的方法

方法名说明
T newInstance(Object...initargs)根据指定的构造方法创建对象

获取成员变量

Class类获取成员变量对象的方法

方法名说明
Field[] getFields()返回所有公共成员变量对象的数组
Field[] getDeclaredFields()返回所有成员变量对象的数组
Field getField(String name)返回单个公共成员变量对象
Field getDeclaredField(String name)返回单个成员变量对象
void set(Object obj,Object value)给obj对象的成员变量赋值为value

获取成员方法

Class类获取成员方法对象的方法

方法名说明
Method[] getMethods()返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods()返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class<?>... parameterTypes)返回单个公共成员方法对象
Method getDeclaredMethod(String name, Class<?>... parameterTypes)返回单个成员方法对象
Object invoke(Object obj,Object... args)调用obj对象的成员方法,参数是args,返回值是Object类型

案例-通过反射获取配置文件内容

 

public class Student {
    public  void show(){
        System.out.println("学生学习了");
    }
}

配置文件内容

ClassName=cn.yanqi_07.Student
MethodName=show
public static void main(String[] args) throws Exception {
​
    //    Student s = new Student();
    //    s.show();
    //获取ApplicationConfig.properties配置文件,字符流缓冲
    BufferedReader br = new BufferedReader(new FileReader("ApplicationConfig.properties"));
    
    //创建properties属性集合对象
    Properties pro = new Properties();
    
    //加载配置文件
    pro.load(br);
​
    //关闭流
    br.close();
​
    //获取配置文件中的数据
    String className = pro.getProperty("ClassName");
    String methodName = pro.getProperty("MethodName");
​
    //获取字节码class对象
    Class c = Class.forName(className);//cn.properties.com.Student
​
    //创建反射实例
    Constructor con = c.getConstructor();
    Object o = con.newInstance();
​
    //调用方法
    Method method = c.getMethod(methodName);//show
    method.invoke(o);
}
​

枚举

module beep #( parameter TIME_500MS = 25&#39;d24999999, //0.5s计数值 parameter DO = 18&#39;d190839 , //&quot;哆&quot;音调分频计数值(频率262) parameter RE = 18&#39;d170067 , //&quot;来&quot;音调分频计数值(频率294) parameter MI = 18&#39;d151514 , //&quot;咪&quot;音调分频计数值(频率330) parameter FA = 18&#39;d143265 , //&quot;发&quot;音调分频计数值(频率349) parameter SO = 18&#39;d127550 , //&quot;梭&quot;音调分频计数值(频率392) parameter LA = 18&#39;d113635 , //&quot;拉&quot;音调分频计数值(频率440) parameter XI = 18&#39;d101214 //&quot;西&quot;音调分频计数值(频率494) ) ( input wire sys_clk , //系统时钟,频率50MHz input wire sys_rst_n , //系统复位,低有效 output reg beep //输出蜂鸣器控制信号 ); //// //\* Parameter and Internal Signal \// //// //reg define reg [24:0] cnt ; //0.5s计数器 reg [17:0] freq_cnt ; //音调计数器 reg [2:0] cnt_500ms ; //0.5s个数计数 reg [17:0] freq_data ; //音调分频计数值 //wire define wire [16:0] duty_data ; //占空比计数值 //// //\* Main Code \// //// //设置50%占空比:音阶分频计数值的一半即为占空比的高电平数 assign duty_data = freq_data &gt;&gt; 1&#39;b1; //cnt:0.5s循环计数器 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1&#39;b0) cnt &lt;= 25&#39;d0; else if(cnt == TIME_500MS ) cnt &lt;= 25&#39;d0; else cnt &lt;= cnt + 1&#39;b1; //cnt_500ms:对500ms个数进行计数,每个音阶鸣叫时间0.5s,7个音节一循环 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1&#39;b0) cnt_500ms &lt;= 3&#39;d0; else if(cnt == TIME_500MS &amp;&amp; cnt_500ms == 6) cnt_500ms &lt;= 3&#39;d0; else if(cnt == TIME_500MS) cnt_500ms &lt;= cnt_500ms + 1&#39;b1; //不同时间鸣叫不同的音阶 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1&#39;b0) freq_data &lt;= DO; else case(cnt_500ms) 0: freq_data &lt;= DO; 1: freq_data &lt;= RE; 2: freq_data &lt;= MI; 3: freq_data &lt;= FA; 4: freq_data &lt;= SO; 5: freq_data &lt;= LA; 6: freq_data &lt;= XI; default: freq_data &lt;= DO; endcase //freq_cnt:当计数到音阶计数值或跳转到下一音阶时,开始重新计数 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1&#39;b0) freq_cnt &lt;= 18&#39;d0; else if(freq_cnt == freq_data \|\| cnt == TIME_500MS) freq_cnt &lt;= 18&#39;d0; else freq_cnt &lt;= freq_cnt + 1&#39;b1; //beep:输出蜂鸣器波形 always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1&#39;b0) beep &lt;= 1&#39;b0; else if(freq_cnt &gt;= duty_data) beep &lt;= 1&#39;b1; else beep &lt;= 1&#39;b0; endmodule根据蜂鸣器的代码写首稻香
06-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值