反射(一)

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对象是放在方法区还是堆中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值