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);
引入
Cat cat = new Cat();//传统创建对象的方式
//根据配置文件指定的信息,创建对象
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());
Method method1 = cls.getMethod(methodName);//得到被加载的类的方法methodName的一个对象
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();//传统调用方法,耗时: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(){
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");//设置属性的值
//获取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类自身也有
//包装类
Class<Integer> type1 = Integer.TYPE;
Class<Character> type2 = Character.TYPE;
Class<?> cls1 = Class.forName("com.itheima.Cat");//多用于配置文件,读取类的全路径,加载类
Class<? extends Cat> cls3 = new Cat().getClass();//通过对象
ClassLoader classLoader = Cat.class.getClassLoader();//通过类加载器[4种]
Class<?> cls4 = classLoader.loadClass("com.itheima.Cat");
深入理解Java类加载器
getDeclaredFields() 和 getFields() 区别
Class对象是放在方法区还是堆中