Class文件加载流程
类的加载条件:
当创建一个类的实例时,如 通过new创建对象,或者通过反射、克隆、反序列化
调用类方法时,即使用了字节码的invokestatic指令
当使用类或接口的类字段(除final常量外),比如使用了getstatic或pushstatic指令
当使用了java.lang.reflect包中的方法反射类的方法时
当初始化子类时,要求先初始化父类
作为启动虚拟机,含有main方法的哪个类
类加载器
类加载器(CLassLoader)用于加载类,在Java中主要有以下四种类加载器:
Bootstrap ClassLoader:此加载器采用C++编写,一般开发中是看不到的,加载系统核心类,如String类;
Extension ClassLoader:用来进行扩展类的加载,一般对应的是jrelibext目录中的类;
AppClassLoader:加载classpath指定的类,即加载用户类,也就是应用程序的类。
自定义类加载器
Class类型获取
public class Class_test { public static void main(String[] args) throws ClassNotFoundException { 1
Class<Class_test> class_testClass = Class_test.class; System.out.println(class_testClass); //class com.zym.com.zym.Class_test 2 Class_test class_test = new Class_test(); Class aClass = class_test.getClass(); System.out.println(aClass); //class com.zym.com.zym.Class_test 3 Class aClass1 = Class.forName("com.zym.com.zym.Class_test"); System.out.println(aClass1); //class com.zym.com.zym.Class_test } }
反射
public class fanshe { public static void main(String[] args) { //获得一个类 Class<Student1> cls = Student1.class; //获取类所在的包 Package apackage = cls.getPackage(); System.out.println(apackage); //获得属性(公开) System.out.println("获得属性(公开)"); Field[] attr_Student1 = cls.getFields(); for (Field s : attr_Student1 ) { System.out.println(s); } //获得属性(所有) System.out.println("------------------"); System.out.println("获得属性(所有)"); Field[] fileds_all_stu1 = cls.getDeclaredFields(); for (Field f : fileds_all_stu1 ) { System.out.println(f); } //获得构造方法(公开的),一般加Declared的都是所有 System.out.println("-----------"); Constructor<?>[] constructors = cls.getConstructors(); for (Constructor con:constructors ) { System.out.println(con); } //获得普通的犯法,公开的方法,包括继承的方法 System.out.println("-----------"); Method[] methods = cls.getMethods(); for (Method m:methods ) { // System.out.println(m); } //获得普通方法,所有本类的所有方法,不包括继承方法 System.out.println("-----------"); Method[] declaredMethods = cls.getDeclaredMethods(); for (Method s : declaredMethods ) { System.out.println(s); } } }
执行类中的方法,普通方法,构造方法
public class TestPropertyDescriptor { public static void main(String[] args) { Person person = new Person(); person.setName("zhangsan"); person.setAge(18); getFiled(person, "name");//结果输出 zhangsan } // 通过反射得到name // 通过得到属性的get方法(pd.getReadMethod())再调用invole方法取出对应的属性值 // 调用set方法() private static void getField(Object object, String field) { Class<? extends Object> clazz = object.getClass(); PropertyDescriptor pd = null; Method getMethod = null; Method setMethod = null; try { pd = new PropertyDescriptor(field, clazz); if (null != pd) { // 获取field属性的get方法 getMethod = pd.getReadMethod(); Object getInvoke = getMethod.invoke(object); // 获取field属性的set方法 setMethod= pd.getWriteMethod(); Object setInvoke = setMethod.invoke(object,"123"); System.out.println(setInvoke+ getInvoke); } } catch (Exception e) { e.printStackTrace(); } } }
public static void main(String[] args) throws Exception { //给对象赋值 /*Person p = new Person(); p.setAge(20); p.setAddress("北京"); p.setName("张三");*/ //获得Person的Class类型 Class<Person> cls = Person.class; //实例化Person /*Person p = cls.newInstance();//通过Person无参构造方法实例化 p.setAge(20); p.setAddress("北京"); p.setName("张三"); System.out.println(p);*/ Constructor<Person> con = cls.getConstructor(String.class,int.class,String.class); Person p=con.newInstance("张三",23,"昌平"); //获得set方法 Field field = cls.getDeclaredField("age"); // System.out.println(field.getName()); String mname="set"+field.getName().substring(0, 1).toUpperCase()+field.getName().substring(1); System.out.println(mname); Method m = cls.getMethod(mname, int.class); //执行方法 m.invoke(p,21); System.out.println(p); //调用show Method show = cls.getMethod("show", String.class); // obj 实例对象,args 参数 show.invoke(p, "测试"); }
反射缺点
破坏了类的封装;
平时开发不会使用反射机制!!!
设计模式
静态代理
一个接口一个功能,也可以在代理类中写功能
对其他对象提供一种代理以控制对这个对象的访问。
对已经存在的类,添加功能,不能修改原有类的任何功能!!!
public class compute implements PublicObject { @Override public void Info(String name, double price) { System.out.println("电脑名称:"+name+"价格:"+price); } }
public class proxy implements PublicObject{ public PublicObject po; public proxy(PublicObject po) { this.po = po; } @Override public void Info(String name, double price) { po.Info(name,price); } public void gift(){ System.out.println("反现金"); } }
public interface PublicObject{ public void Info(String name,double price); }
public class proxy_test { public static void main(String[] args) { compute c = new compute(); proxy p = new proxy(c); p.Info("zzzz", 123); p.gift(); } }
动态代理
之前曾为读者讲解过代理机制的操作,但是之前所讲解的代理设计,属于静态代理,因为每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理了,最好的做法是可以通过一个代理类完成全部的代理功能,那么此时就必须使用动态代理完成。
在Java中要想实现动态代理机制,则需要java.lang.reflect.InvocationHandler接口和java.lang.reflect.Proxy类的支持。
public class MyProxy implements InvocationHandler{//动态代理 private Object obj; //绑定的对象 public Object bind(Object o){ this.obj=o; // ClassLoader loader:类加载器 // Class<?>[] interfaces:得到全部的接口 // InvocationHandler h:得到InvocationHandler接口的子类实例 return Proxy.newProxyInstance(o.getClass().getClassLoader(), o.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // System.out.println("参数:"+Arrays.toString(args)); // System.out.println(method.getName()); return method.invoke(obj, args); //执行目标对象的方法 } }
//目标对象 public class Computer implements PublicObj { @Override public void Info(String name, double price) { System.out.println(name+"系列电脑!"+price); } }
//抽象对象 public interface PublicObj { //电脑系列 public void Info(String name,double price); }
public class Test { public static void main(String[] args) { MyProxy handler = new MyProxy(); PublicObj po =new Computer();//真实目标对象 PublicObj o = (PublicObj) handler.bind(po); o.Info("IBM", 9999.99); } }