反射机制

来源:互联网 发布:no sleep for mac下载 编辑:程序博客网 时间:2024/05/17 02:29

反射机制

     反射的基本概念

反射就是把Java类中的各种成分映射成相应的java.


Class

   表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是FieldMethodContructorPackage等等。

   一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象


    字节码 :

    一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示

   三种获得字节码的方式:

    类名.class();

       对象.getClass();

       Class.forName(“类名”);

String str = "asd";//输出结果为class java.lang.StringSystem.out.println(String.class);System.out.println(str.getClass());System.out.println(Class.forName("java.lang.String"));

    九个预定义Class实例对象:

         分别为:char,short,byte,int,long,float,double,booleanvoid.

         Class.isPrimitive可以检查是否为基本类型

     Int.class ==Integer.TYPE 

         Class.isArray()

System.out.println(int.class);                  //intSystem.out.println(int.class.isPrimitive());    //trueSystem.out.println(int.class == Integer.TYPE);  //true<span lang="EN-US"></span>

      Constructor

Constructor类代表某个类中的一个构造方法

根据构造方法的参数的个数和类型,来获取不同的构造方法.方法的各个参数的类型用Class对象表示


//得到某个类中所有构造方法Constructor[] con = Class.forName("java.lang.String").getConstructors();//获得某个类并创建Constructor constructor = String.class.getConstructor(StringBuffer.class);String str1 = (String)constructor.newInstance(new StringBuffer("itheima"));System.out.println(str1);


    可以利用泛型提前确定数据类型省去强制类型转换

        Constructor<String> constructor2 = String.class.getConstructor(StringBuffer.class);String str2 = constructor2.newInstance(new StringBuffer("itheima"));

   

    Class类提供货了newInstance()方法用于直接构造没有参数的类

String.class.newInstance();


 Field

Field类代表某个类中的一个成员变量

public static void main(String[] args) throws Exception{Point p = new Point(1,4);//获得public属性的值Field fieldY = p.getClass().getField("y");//类中的非静态的属性需要一个对象来取出这个对象中的值System.out.println(fieldY.get(p)); //获取private属性的值//私有属性不能使用getField()方法Field fieldX = p.getClass().getDeclaredField("x");//获得私有属性后,需强制破解才能获得或修改值fieldX.setAccessible(true);fieldX.set(p, 12);//获得类的静态属性Field fieldZ = p.getClass().getField("z");System.out.println(fieldZ.get(Point.class));}}class Point {private int x;public int y;public static int z = 0;public Point(int x, int y) {super();this.x = x;this.y = y;}}

    作业:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的"b"改成"a"

package com.itheima.reflect;import java.lang.reflect.Field;public class replaceChar {public static void main(String[] args) {TestClass test = new TestClass();System.out.println("替换前" + test);replaceCharB(test);System.out.println("替换后" + test);}private static void replaceCharB(Object obj) {Field[] fields = obj.getClass().getFields();for(Field field : fields) {     if(field.getType() == String.class) {     //检测是否为String  String str = null;try {str = (String)field.get(obj);   } catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}String newStr = str.replace('b', 'a');    //replace方法不会改变str的原值try {field.set(obj, newStr);          //将str重新设置回去} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}class TestClass {public String str1 = "bbbbbbbbbbbbb";public String str2 = "babfbdsbd";public String str3 = "ball";public int i = 0;@Overridepublic String toString() {return "TestClass [str1=" + str1 + ", str2=" + str2 + ", str3=" + str3+ ", i=" + i + "]";}}


        Method
   

        Method类代表某个类中的一个成员方法

String str = "abc";//调用String类的chatAt(int) 方法Method stringCharAt = String.class.getMethod("charAt", int.class);System.out.println(stringCharAt.invoke(str, 1));
    当Method.invoke(null, )方法的第一个参数为null时,代表Method方法为静态方法.


      main方法的反射:

mian方法传递String数组数据的两个解决办法:

mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});

mainMethod.invoke(null,(Object)new String[]{"xxx"});,编译器会作特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数了

Method reflectMainMethod = Class.forName(args[0]).getMethod("main", String[].class);reflectMainMethod.invoke(null, (Object)new String[]{"111", "222", "333"});reflectMainMethod.invoke(null, new Object[]{new String[]{"111", "222", "333"}});


      数组的反射

      具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。

代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class

基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;

非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。

public static void main(String[] args) {int[] a1 = new int[3];int[] a2 = new int[4];int[][] a3 = new int[1][3];String[] a4 = new String[1];a4[0] = "sdfs";System.out.println(a1.getClass() == a2.getClass());System.out.println(a1.getClass() == (Object)a3.getClass());System.out.println((Object)a1.getClass() == a4.getClass());//不加强制转换会直接报错  不知道为什么  强制转换加到哪是一样的System.out.println(a1.getClass().getName());System.out.println(a3.getClass().getSuperclass().getName());Object o1 = a1;Object o2= a4;//Object[] o3 = a1;Object[] o4 = a3;Object[] o5 = a4;//Arrays类System.out.println(Arrays.asList(a3));Object obj;printObject(a1);}

//利用数组的反射输出数据private static void printObject(Object obj) {Class claszz = obj.getClass();if(claszz.isArray()){int len = Array.getLength(obj);for(int i=0; i<len; i++){System.out.println(Array.get(obj, i));}}else{System.out.println(obj);}}

    简单框架实例

  

   框架与工具类有区别,工具类被用户的类调用,而框架则是调用用户提供的类。

public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {//根据配置文件来调用配置文件中的Collection的子类String objectClass;FileInputStream fis = new FileInputStream("ReflectClass.Properties");Properties pro = new Properties();pro.load(fis);fis.close();objectClass = pro.getProperty("objectClass");Class cla = Class.forName(objectClass);Collection collection = (Collection)cla.newInstance();}


   配置文件的位置

       配置文件应尽量写绝对路径,最好在使用时专门设置一个放配置文件的目录

    类名.Class.getClassLoader.getResourceAsStream(String name)
     可以指定当前包下的文件


0 0