java内功系列五(类加载与反射)

1.java程序启动时启动了一个jvm的虚拟机进程,所有线程变量都在该虚拟机中。
2.当程序使用某个类时发现没有那么会从文件中加载到内存中,并创建一个java.lang.class对象。(加载、链接、初始化),类时对事物的抽象,其实类本身也是一种事物,对它的抽闲就是java.lang.class,所以系统中的所有类其实也是实例(java.lang.class实例)。
3.类加载器有根加载器(jvm提供)和其它加载器(java语言编写:本地加载,jar加载,网络加载,其它加载),可以自己继承classloader实现自己的类加载器。jvm允许预先加载某些类。
4.classloaer只是把二进制文件加载但是不会初始化,当使用class.forname方法才会初始化。(对于finnal对象如果在编译时已经能确定值那么在编译的时候会替换成具体的值)
5.类加载器:根加载器(加载java核心类,string,int等)、扩展加载器(一般加载%javahome%jre/lib/ext下的jar)、系统加载器(我们自己写的程序文件)、用户加载器(自定义的加载器),一个类被2中不同的加载器加载那么他们在jvm中是不一样的。

6.java运行大部分对象会出现2中类型:编译时类型和运行时类型。(person p=new student;)编译时person,运行时student。
7.获取类有class.forname(class.forname("全名"))、类.class(person.class)、对象.getclass(pers.getclass())。
8.class对象可以获得对应类的构造函数、方法、属性、annotation、内部类、外部类、实现接口、父类、修饰符、所在包、类名等基本信息。并提供了判断该class对象对应的类是否为接口、枚举注解等。
9.反射用class对象的newinstance方法创建实例(spring就是使用配置文件生成具体的类)、也可用class对象获取对应类的构造函数后创建对象。
10.class对象可以获取对应对象的方法method对象,然后调用method对象的invoke方法调用实例对象方法,spring使用该方法给对象的字段或者依赖对象赋值(setter方法)。这也是ioc的核心思想。
10.class对象可以获取对应类的成员变量,并且可以对变量进行赋值或读取。
11.数组也可以实现反射创建、获取、设置。
12.使用proxy和invocationHander创建动态代理对象。
 Proxy.getProxyClass(arg0, arg1) 创建动态代理类
 Proxy.newProxyInstance(loader, interfaces, h) 创建动态代理对象(使用多),代理对象的执行最后都是调用h对象的invoke执行的。
13.aop实现的原理就是使用proxy和invocationHander创建动态代理。首先实现invocationHander接口,在invocationHander实习类中保留一个真正被代理对象,在invocationHander中只有一个invoke方法,这样需要在方法调用前后做必要的处理(验证、日志等或者直接不让函数执行返回空),proxy负责根据接口生成代理对象框架,代理对象内部调用全部使用invocationHander实现类对象的invoke方法,只是每个方法传递的参数不一样(method方法和参数),这样就可以根据反射调用真正被代理对象的方法(method.invoke(真正对象,参数))。这样就实现了在一个地方(invocationHander实现类的invoke方法中)集中的编写横切面逻辑(日志、验证等)让所有的方法都可以应用到。
14.java的class类增加了泛型功能,例如:string.class实际上就是class<Sring>,如果class对应的类型未知可以使用class<?>。使用泛型可以解决反射中类型的强制转换。
15.反射可以获取到一个类的字段类型,但是这个字段类型只能是非泛型化的(int,对应字段类型是map<string,int>这种不行),如果泛型化的需要得到类型后进行转换。
    public class generictest
    {
        private Map<String, Integer> score;
        public static void main(String[] args) throws Exception
        {
            Class<generictest> clazz=generictest.class;
            Field f=clazz.getDeclaredField("score");
            //直接使用gettype取出类型
            Class<?> a=f.getType();
            System.out.println(a);//只能输出java.util.Map
            Type gtype=f.getGenericType();
            if(gtype instanceof ParameterizedType)
            {
                ParameterizedType ptype=(ParameterizedType)gtype;
                //返回原始类型和上面那个一样
                Type rtype=ptype.getRawType();
                System.out.println(rtype);
                Type[] targs=ptype.getActualTypeArguments();
                for(int i=0;i<targs.length;i++)
                {
                    System.out.println(targs[i]);//这将输出string和Integer
                }
            }
            else
            {
                System.out.println("出错");
            }    
            
        }
    }

猜你喜欢

转载自blog.csdn.net/yuliantao/article/details/82740332