当前位置:网站首页>反射(一)
反射(一)
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对象是放在方法区还是堆中
边栏推荐
- 奥迪AUDI EDI INVOIC发票报文详解
- Shell 编程核心技术《一》
- Technology sharing | interface testing value and system
- 876. 链表的中间结点
- Mxnet implementation of googlenet (parallel connection network)
- 6.26cf simulation race e: solution to the problem of price maximization
- Nebula importer data import practice
- 【uniapp】uniapp开发app在线预览pdf文件
- 2022养生展,健康展,北京大健康展,健康产业展11月举办
- PB的扩展DLL开发(超级篇)(七)
猜你喜欢
基于C语言的菜鸟驿站管理系统
用实际例子详细探究OpenCV的轮廓绘制函数drawContours()
Process of manually encrypt the mass-producing firmware and programming ESP devices
Basic tutorial of scala -- 16 -- generics
node_exporter部署
OpenCV的二值化处理函数threshold()详解
MXNet对GoogLeNet的实现(并行连结网络)
Nebula Importer 数据导入实践
2022年字节跳动日常实习面经(抖音)
The 300th weekly match of leetcode (20220703)
随机推荐
[发布] 一个测试 WebService 和数据库连接的工具 - DBTest v1.0
876. 链表的中间结点
BI技巧丨权限轴
生成XML元素
关于判断点是否位于轮廓内的一点思考
测试工程师如何“攻城”(下)
Unity editor extends C to traverse all pictures in folders and subdirectories
2022CoCa: Contrastive Captioners are Image-Text Fountion Models
基于unity的愤怒的小鸟设计
读写关闭的channel是啥后果?
Shell 编程核心技术《四》
Perfect JS event delegation
MySQL数据库基本操作-DDL | 黑马程序员
[go ~ 0 to 1] read, write and create files on the sixth day
From automation to digital twins, what can Tupo do?
Scala basic tutorial -- 13 -- advanced function
Stream流
Li Chi's work and life summary in June 2022
node_exporter部署
Scala基础教程--17--集合