反射、类加载与垃圾回收
Java是一种有一定动态性的语言。
动态性:它可以在运行期探究和使用编译期未知的东西,包括类、构造、属性、方法等。
- 目标:使用反射产生对象,通过反射探究类(属性、构造、方法),在运行期去探究和使用任意属性、构造及方法。
类加载
- 类的加载机制
类加载:就是把一个类的信息放入一个Class对象当中去。
连接:把类的二进制的数据合并到JRE中。
初始化:
反射
- 概念:在运行时探究和使用未知的类。
反射步骤:
1.获取Class信息。//1-1、根据实例对象获取Class对象。 //实现方法:调用实例对象获取对象的getClass().该方法来自Object类。 //适用范围:引用数据类型, //动态性:无 Student stu = new Student(); Class stuClass = stu.getClass(); Class strClass = "hello".getClass(); int[] intArray = new int[6]; Class arrayClass = intArray.getClass(); //1-2、根据类型名获取Class对象 //实现方法:调用类型名。class。 //适用范围:所有的类型(基本、引用、甚至包括void) //动态性:无 Class stuClass0 = Student.class; Class strClss1 = String.class; //该方式在JDK1.5以后才有 Class arrayClass0 = int[].class; Class voidClass = void.class; Class intClass = Integer.class; Class intClass1 = Integer.TYPE;//该方式在JDK1.5以前 //1-3、根据类型的字符串名称获取Class对象。 //实现方式:调用Class。forName("类的限定名") //适用范围:只有类类型(包括接口) //动态性:有 Class stuClass1 = null; try { String className = new Scanner(System.in).next(); stuClass1 = Class.forName(className); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); }
2.通过Class对象探究一个类的信息。
//2-1、探究一个类的申明部分信息 String packageName = stuClass2.getPackage().getName();//得到包名 System.out.println("package " + packageName + ";"); String className = stuClass2.getName();//得到全类名 className = stuClass2.getSimpleName();//得到简单类名 int classMod = stuClass2.getModifiers();//得到修饰符,返回的数字 String classModStr = Modifier.toString(classMod);//利用工具方法,将整型修饰符转换成字符串 Class superStuClass = stuClass2.getSuperclass();//得到父类的Class对象 String superClassName = superStuClass.getName(); Class[] interClasses = stuClass2.getInterfaces();//得到本类实现接口的Class对象(可以有多个,所以是数组) String allInter = ""; for(int i = 0; i < interClasses.length; i++){ allInter += interClasses[i].getName(); if(i < interClasses.length - 1){ allInter += ","; } } //打印类的申明部分 System.out.println(classModStr + " class " + className + " extends " + superClassName + " implements " + allInter + "{"); //2-2、探究属性 System.out.println("//属性"); Field[] allPublicFields = stuClass2.getFields();//得到所有的公共属性 Field[] allFields = stuClass2.getDeclaredFields();//得到所有被申明的属性 try { Field thePublicField = stuClass2.getField("score");//得到指定的某个公共属性 Field theField = stuClass2.getDeclaredField("name");//得到指定的某个被申明的属性 } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } //打印属性 for(Field field : allFields){ String fieldName = field.getName();//得到属性名 Class fieldType = field.getType();//得到属性类型 String fieldTypeName = fieldType.getName(); int fieldMod = field.getModifiers();//得到属性对应的修饰符 String fieldModStr = Modifier.toString(fieldMod); System.out.println("\t" + fieldModStr + " " + fieldTypeName + " " + fieldName); } //2-3、探究构造 System.out.println("//构造方法"); Constructor[] allPublicCons = stuClass2.getConstructors();//得到所有的公共构造 Constructor[] allCons = stuClass2.getDeclaredConstructors();//得到所有被申明的构造 try { //得到指定的某个公共构造方法 Constructor thePublicCon = stuClass2.getConstructor(String.class,int.class,boolean.class); //得到指定的某个被申明的构造方法 Constructor theCon = stuClass2.getDeclaredConstructor(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } //打印构造 for(Constructor con : allCons){ String conName = con.getName();//得到构造方法的名字 Class[] paramClasses = con.getParameterTypes();//得到构造方法的参数列表 String params = ""; if(paramClasses != null && paramClasses.length > 0){ for(int i = 0; i < paramClasses.length; i++){ params += paramClasses[i].getName(); if(i < paramClasses.length - 1){ params += ","; } } } int conMod = con.getModifiers();//得到构造方法的修饰符 String conModStr = Modifier.toString(conMod); System.out.println("\t" + conModStr + " " + conName + "(" + params + ")"); } //2-4、探究方法 System.out.println("//普通方法"); Method[] allPublicMethods = stuClass2.getMethods();//得到所有的公共方法 Method[] allMethods = stuClass2.getDeclaredMethods();//得到所有被申明的方法 try { Method thePublicMethod = stuClass2.getMethod("test1");//得到指定的某个公共属性 Method theMethod = stuClass2.getDeclaredMethod("test3",int.class,String.class);//得到指定的某个被申明的属性 } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } //打印方法 for(Method method : allMethods){ String methodName = method.getName();//得到方法的名字 Class[] paramClasses = method.getParameterTypes();//得到方法的参数列表 Class[] methodExs = method.getExceptionTypes();//得到方法的返回类型 String params = ""; String exs = ""; if(paramClasses != null && paramClasses.length > 0){ for(int i = 0; i < paramClasses.length; i++){ params += paramClasses[i].getName(); if(i < paramClasses.length - 1){ params += ","; } } } if(methodExs != null && methodExs.length>0){ exs="throws"; for(int j=0; j<methodExs.length;j++){ exs +=methodExs[j].getName(); if(j<exs.length()-1){ exs += ","; } } } int methodMod = method.getModifiers();//得到构造方法的修饰符 String methodModStr = Modifier.toString(methodMod); Class methodRe = method.getReturnType(); System.out.println("\t" + methodModStr + " " + methodRe + " " + methodName+" "+params+" "+exs+"{"); }
3.操作从Class中探究出的信息。
//3-1、根据Constructor对象,产生实例对象 //实现一:调用Constructor的newInstance方法。 try { //得到指定的某个公共构造方法 Constructor thePublicCon = stuClass2.getConstructor(String.class,int.class,boolean.class); try { Student student = (Student)thePublicCon.newInstance("zhang3",18,true); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } //实现二:直接调用Class对象的newInstance方法--前提是只能调用到公共无参构造 try { Student stu0 = (Student)stuClass2.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } //3-2、根据Field对象,对属性进行取值和赋值。 try { Field thePublicField = stuClass2.getField("score"); thePublicField.set(stu, 100);//赋值(注意第一个参数,代表的是给哪个对象的这个属性赋值) thePublicField.get(stu);//取值(参数代表从哪个对象得到了这个值) } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } //3-3、根据method对象,对方法进行调用 //实现:调用Method对象的invoke方法 try { Method thePublicMethod = stuClass2.getMethod("test3",int.class); thePublicMethod.invoke(stu,4); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); }