当前位置:网站首页>反射(一)
反射(一)
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对象是放在方法区还是堆中
边栏推荐
- 2014合肥市第三十一届青少年信息学奥林匹克竞赛(小学组)试题
- The 300th weekly match of leetcode (20220703)
- 问下各位大佬有用过cdc直接mysql to clickhouse的么
- 请教一下 flinksql中 除了数据统计结果是状态被保存 数据本身也是状态吗
- 【uniapp】uniapp开发app在线预览pdf文件
- Nebula Importer 数据导入实践
- IBM WebSphere MQ检索邮件
- IBM WebSphere MQ retrieving messages
- Download the first Tencent technology open day course essence!
- 删除字符串中出现次数最少的字符【JS,Map排序,正则】
猜你喜欢
2022CoCa: Contrastive Captioners are Image-Text Fountion Models
神经网络物联网应用技术就业前景【欢迎补充】
LeetCode第300场周赛(20220703)
Learning path PHP -- phpstudy "hosts file does not exist or is blocked from opening" when creating the project
Wireshark网络抓包
Stream流
使用canal配合rocketmq监听mysql的binlog日志
Use canal and rocketmq to listen to MySQL binlog logs
Oracle with as ORA-00903: invalid table name 多表报错
Nebula Importer 数据导入实践
随机推荐
C#实现定义一套中间SQL可以跨库执行的SQL语句(案例详解)
Summary and sorting of 8 pits of redis distributed lock
基于lex和yacc的词法分析器+语法分析器
[go ~ 0 to 1] read, write and create files on the sixth day
Stream流
[mathematical basis of machine learning] (I) linear algebra (Part 1 +)
数组中的第K个最大元素
2021 合肥市信息学竞赛小学组
资料下载 丨首届腾讯技术开放日课程精华!
删除字符串中出现次数最少的字符【JS,Map排序,正则】
SSL证书续费相关问题详解
2019年蜀山区第十五届青少年信息学竞赛
Using SSH
Scala basic tutorial -- 18 -- set (2)
[opencv introduction to mastery 9] opencv video capture, image and video conversion
性能优化之关键渲染路径
千万不要只学 Oracle、MySQL!
876. 链表的中间结点
升级智能开关,“零火版”、“单火”接线方式差异有多大?
repeat_P1002 [NOIP2002 普及组] 过河卒_dp