当前位置:网站首页>反射(一)
反射(一)
2022-07-04 17:48:00 【Cold Snowflakes】
Properties
void load(InputStream inStream)
void load(Reader reader)
void store(OutputStream out,String comments)
void store(Writer writer,String comments)
读取文件内容
Properties properties = new Properties();
properties.load(new FileInputStream("idea_test\\src\\re.properties"));
String classfullpath = properties.getProperty("classfullpath"); // 读取 导入进来的信息
String methodName = properties.getProperty("method");
写入文件内容
Properties prop = new Properties();
prop.setProperty("001","林青霞");
prop.setProperty("002","张曼玉");
prop.setProperty("003","王祖贤");
prop.store(new FileWriter("idea_test\\src\\re.txt"),null);
类加载
当程序要使用某个类时,如果该类还未被加载到内存,则系统会通过类的加载,类的连接,类的初始化这三个步骤来对类进行初始化。
一般情况下,JVM将会连续完成这三个步骤,所以有时也把这三个步骤统称为类加载。
类的加载:将 .class 文件读入内存,并为之创建一个Class类的实例。
类的连接
验证阶段:确保 .class 文件的字节流中包含信息符合当前虚拟机要求,不会危害虚拟机自身安全。
准备阶段:为static修饰的字段变量分配内存并且设置初始值为0,不包含用final修饰的static,因为final在编译的时候就会分配了。
解析阶段:主要将常量池中的符号引用替换为直接引用的过程。
类的初始化:类加载最后阶段,若该类具有超类,则对其进行初始化,执行静态初始化器和静态初始化成员变量(如前面只初始化了默认值的static变量将会在这个阶段赋值,成员变量也将被初始化)。
// 传统创建对象的方式
Cat cat = new Cat();
cat.hi();
// 根据 配置文件指定的信息, 创建对象
Properties properties = new Properties();
properties.load(new FileInputStream("idea_test\\src\\re.properties"));
String classfullpath = properties.getProperty("classfullpath");
String methodName = properties.getProperty("method");
// 加载类, 并得到 Class对象
Class<?> cls = Class.forName(classfullpath);
// 得到 被加载的类的 一个对象实例
Object instance = cls.getDeclaredConstructor().newInstance();
System.out.println("instance 的运行类型为: " + instance.getClass());
// 得到 被加载的类的 方法methodName 的一个对象
// 在反射中, 可以把方法视为对象
Method method1 = cls.getMethod(methodName);
System.out.println("================================");
// 调用该方法
method1.invoke(instance);
反射的优点:可以通过不修改源代码,只修改配置文件,达到控制程序的效果。
类加载器加载Cat.class字节码文件,然后在堆中就产生了一个Class对象(Class类的一个实例)(一个类只有一个Class对象),这个对象包含了Cat类的完整结构信息。(成员变量 Field[] fields,构造器 Constructor[] cons,成员方法 Method[] ms,等等)
反射相关的类
public class Cat {
private String name;
private Integer age;
private Integer sex;
public Cat(){
}
public Cat(String name){
}
public Cat(String name,Integer age,Integer sex){
}
public void hi(){
System.out.println("hi...");
}
public void cry(){
System.out.println("cry...");
}
}
// 加载类, 并得到 Class对象
Class<?> cls = Class.forName("com.itheima.Cat");
Field[] fields = cls.getDeclaredFields();
Method[] methods = cls.getDeclaredMethods();
Constructor<?>[] constructors = cls.getDeclaredConstructors();
System.out.println();
Stream.of(fields).forEach(System.out::println);
System.out.println("========================");
Stream.of(methods).forEach(System.out::println);
System.out.println("========================");
Stream.of(constructors).forEach(System.out::println);
// 也可以指定要取哪一个
Field age = cls.getDeclaredField("age");
// 得到参数为一个 String 的构造方法对象
Constructor<?> constructor1 = cls.getDeclaredConstructor(String.class);
// 得到无参的构造方法对象
Constructor<?> constructor2 = cls.getDeclaredConstructor();
// Output
private java.lang.String com.itheima.Cat.name
private java.lang.Integer com.itheima.Cat.age
private java.lang.Integer com.itheima.Cat.sex
========================
public void com.itheima.Cat.hi()
public void com.itheima.Cat.cry()
========================
public com.itheima.Cat(java.lang.String,java.lang.Integer,java.lang.Integer)
public com.itheima.Cat(java.lang.String)
public com.itheima.Cat()
反射调用优化
使用反射,对执行速度有影响。
// 传统调用方法
m1();
// 反射机制调用
m2();
// Output
m1() 耗时:12
m2() 耗时:2895
public static void m1(){
Cat c = new Cat();
long start = System.currentTimeMillis();
for(int i = 0; i < 900000000; i++){
c.hi();
}
long end = System.currentTimeMillis();
System.out.println("m1() 耗时:" + (end - start));
}
public static void m2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> cls = Class.forName("com.itheima.Cat");
Object newInstance = cls.getDeclaredConstructor().newInstance();
Method hiMethod = cls.getMethod("hi");
long start = System.currentTimeMillis();
for(int i = 0; i < 900000000; i++){
hiMethod.invoke(newInstance);
}
long end = System.currentTimeMillis();
System.out.println("m2() 耗时:" + (end - start));
}
Method,Field,Constructor对象都有setAccessible方法。
setAccessible作用是启动和禁用访问安全检查的开关。
设置为true,关闭检查,可以加快一点点速度。
Class类
1.Class类实例不是new出来的,而是系统进行类加载的时候创建的。
2.对于某个类的Class类实例,在内存中只有一份,因为类只加载一次。
3.通过Class类实例可以完整的得到一个类的完整结构。
4.Class类实例是存放在堆的。
5.Cat类的字节码文件二进制数据,是存放在方法区的,有的地方称为类的元数据。
一些其他的API
Class<?> cls = Class.forName("com.itheima.Cat");
System.out.println(cls.getName()); // 被加载的类的全限定名
System.out.println(cls.getPackage().getName()); // 被加载的类的包名
Field name = cls.getDeclaredField("name");
System.out.println(name.get(instance)); // 得到属性对应的值
name.set(instance,"xxx"); // 设置属性的值
System.out.println(name.get(instance));
如何得到Class类的实例?
// 多用于配置文件, 读取类的全路径, 加载类。
Class<?> cls1 = Class.forName("com.itheima.Cat");
// 类名.class, 多用于参数传递。
Class<Cat> cls2 = Cat.class;
// 对象.getClass()
Class<? extends Cat> cls3 = new Cat().getClass();
// 通过类加载器[4种]
ClassLoader classLoader = Cat.class.getClassLoader();
Class<?> cls4 = classLoader.loadClass("com.itheima.Cat");
// 基本数据类型(int,char,double,boolean,long,short), 按如下方式
Class<Integer> integerClass = int.class;
Class<Character> characterClass = char.class;
Class<Boolean> booleanClass = boolean.class;
// 包装类
Class<Integer> type1 = Integer.TYPE;
Class<Character> type2 = Character.TYPE;
哪些类型有Class类的实例?
Class<Cat> catClass = Cat.class; // 类,(内部类也有)
Class<Serializable> serializableClass = Serializable.class; // 接口
Class<Integer[]> aClass = Integer[].class; // 数组
Class<float[][]> aClass1 = float[][].class; // 二维数组
Class<Deprecated> deprecatedClass = Deprecated.class; // 注解
Class<Thread.State> stateClass = Thread.State.class; // 枚举
Class<Long> longClass = long.class; // 基本数据类型
Class<Void> voidClass = void.class; // void
Class<Class> classClass = Class.class; // Class类自身也有
深入理解Java类加载器
getDeclaredFields() 和 getFields() 区别
Class对象是放在方法区还是堆中
边栏推荐
- C language printing exercise
- node_exporter部署
- 1672. 最富有客户的资产总量
- 指定输出的字符集
- The latest progress of Intel Integrated Optoelectronics Research promotes the progress of CO packaging optics and optical interconnection technology
- One question per day (2022-07-02) - Minimum refueling times
- 千万不要只学 Oracle、MySQL!
- 2022CoCa: Contrastive Captioners are Image-Text Fountion Models
- Use canal and rocketmq to listen to MySQL binlog logs
- Process of manually encrypt the mass-producing firmware and programming ESP devices
猜你喜欢
Basic tutorial of scala -- 16 -- generics
升级智能开关,“零火版”、“单火”接线方式差异有多大?
The 300th weekly match of leetcode (20220703)
One question per day (2022-07-02) - Minimum refueling times
Stream流
读写关闭的channel是啥后果?
Lex and yacc based lexical analyzer + parser
Nebula Importer 数据导入实践
My colleagues quietly told me that flying Book notification can still play like this
Don't just learn Oracle and MySQL!
随机推荐
876. 链表的中间结点
node_exporter部署
建立自己的网站(15)
DeFi生态NFT流动性挖矿系统开发搭建
2022 ByteDance daily practice experience (Tiktok)
Uni app and uviewui realize the imitation of Xiaomi mall app (with source code)
页面元素垂直水平居中、实现已知或者未知宽度的垂直水平居中。
1672. Total assets of the richest customers
指定输出的字符集
更安全、更智能、更精致,长安Lumin完虐宏光MINI EV?
[uniapp] uniapp development app online Preview PDF file
Is the securities account opened by qiniu safe?
Oracle with as ORA-00903: invalid table name 多表报错
基于NCF的多模块协同实例
LeetCode 赎金信 C#解答
Unity editor extends C to traverse all pictures in folders and subdirectories
请教一下 flinksql中 除了数据统计结果是状态被保存 数据本身也是状态吗
Leetcode fizzbuzz C # answer
Scala basic tutorial -- 20 -- akka
性能优化之关键渲染路径