Java_反射_Class类(Method,Field,Constructor)

1.获得字节码实例对象

    Person p = new Person();
    (1).Class clazz = Person.class;
    (2).Class clazz = P.getClass();
    (3).Class clazz = Class.forName("String path");

    (4).Class clazz = ClassLoader.getSystemClassLoader().loadClass("com.baidu.Person");

   上述四种字节码可以获得字节码对象,在获得之前先判断是否载入,没有则查找载入(还可以通过类的实例化对象载入),否则返回先前载入的class,符合单例设计模式

   通过类加载器将需求类加载至内存中,类加载器会采用事件委托机制,如果该类已经加载,则不需重新再加载!实现步骤:

        1).调用 findLoadedClass(String) 来检查是否已经加载类
        2).在父类加载器上调用 loadClass 方法。如果父类加载器为 null,则使用虚拟机的内置类加载器。 
        3).调用 findClass(String) 方法查找类。

    更多类加载器参考>>

[java]  view plain copy
  1. System.out.println(P.getClass().getClass().getClass().getName());//字节码的字节码A是Class,A字节码的字节码还是Class  

     注意:与通过代理获得的字节码区别

[java]  view plain copy
  1. public static void main(String[] args) throws Exception {  
  2.     Class clazz1 = List.class;  
  3.     Class clazz2 = Class.forName("java.util.List");  
  4.     Class clazz3 = ClassLoader.getSystemClassLoader().loadClass("java.util.List");  
  5.     Class clazz4 = Proxy.getProxyClass(null, List.class);  
  6.       
  7.     System.out.println(clazz1 == clazz2);   //true  
  8.     System.out.println(clazz1 == clazz3);   //true  
  9.     System.out.println(clazz1 == clazz4);   //false  
  10.         /* 
  11.          * getProxyClass(null, Class<?> ...)接收的是可变参数而普通的是的单个类或者接口 
  12.          * 显然Class字节码文件不一样 
  13.          */  
  14. }  

2.九中预定义字节码实例对象

    有九种预定义的Class 对象,表示八个基本类型和 void,象由 Java 虚拟机创建,与其表示的基本类型同名,即booleanbytecharshortintlongfloat 和double

[java]  view plain copy
  1. System.out.println(int.class == Integer.TYPE);  //true 其中Integer.TYPE中TYPE字段表示基本类型 int的 Class 对象。  
  2. System.out.println(int.class.isPrimitive());    //true 判定指定的 Class 对象是否表示一个基本类型  

3.Class主要方法

    1).获取Constructor对象
        getConstructor(Class<?>... parameterTypes) 
            返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
        getDeclaredConstructor(Class<?>... parameterTypes) 
            所有非public的构造方法,都应该用该方法获取,而public可以使用getConstructor
        getConstructors() 
            返回Constructor 对象数组
        getDeclaredConstructors() 


        Constructor的操作过程
            Constructor<Person> con = Person.class.getDeclaredConstructor(String.class, int.class);//与构造函数一致
            Person p = con.newInstance("haha", 10);//newInstance实现

    2).获取Field对象
        getField(String name) 
            返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
        getDeclaredField(String name) 
        getFields() 
        getDeclaredFields() 


        Field的操作过程
            Field f = Person.class.getDeclaredField("name");//能看见
            f.setAccessible(true); //指示反射的对象在使用时是否取消 Java 语言访问检查能用
            f.set(p, "zhangsan"); //指定该字段所对应的对应的值
         Field的常见方法
            Object get(Object obj) 
            String s1 = (String)ff.get(p);//返回Object类要进行强转
            getType()
                返回一个class类型的二进制码文件
            set(Object obj, Object value) 
            f.setAccessible(true)

    3).获取Method对象

        getMethod(String name, Class<?>... parameterTypes) //由于方法名队员可能有多个函数,应该在其后指明对应的class对象
            返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
        getDeclaredMethod(String name, Class<?>... parameterTypes) 
        getMethods()
        getDeclaredMethods()

 

        Method的操作过程
            Method m = Person.class.getMethod("set", String.class, int.class);
            m.invoke(p, "wangwu", 100);

    4).Class也能newInstance()!!!

        Person p = (Person)Class.forName("Person").newInstance();

        T newInstance(),但是只能为空参数!!!注意和Constructor的newInstance的区别~~~得到的是一个对象Object要注意转换

    5).Perosn.class.getResourceAsStream(String path)
        path 不以 / 开头时默认是从此类所在的包下取资源(即Person所在的类class目录中,存在一个path文件)
        path 以 / 开头,以ClassPath根下获取一个绝对路径。

    6).Perosn.class.getClassLoader().getResourceAsStream(String path)
        默认则是从ClassPath根下获取

4.总结

    总之,对于一个已经存在的实例对象A,假想操作字段或者方法,必得到一个Field或者Method的对象X,对于一个X必须有指定一个的A对象,才能完成对A对象属性的修改。对于不存在的A,可以通过构造函数,返回A
    凡是为静态的字段或者方法,其对应的对象为null!

 

5.反射代码实例

[java]  view plain copy
  1. /* 
  2. 反射的简单应用 
  3. Strawberry2013/5/15 
  4. */  
  5. import java.lang.reflect.*;  
  6. class Demo  
  7. {  
  8.     public static void main(String[] args) throws Exception  
  9.     {  
  10. //Constructor  
  11.         Constructor<Person> con = Person.class.getDeclaredConstructor(String.classint.class);  
  12.         //需注意加泛型  由于Person类的构造函数是非public的,故应该使用getDeclaredConstructor()方法  
  13.         Person p = con.newInstance("haha"10);//实例化对象  
  14.         p.show();  
  15. //Field  
  16.         Field f = Person.class.getDeclaredField("name");//获得单个字段,必须指明字段对应的字符串  
  17.         //Field f = Perosn.class.getField("name");该方法只能获取字段为public的  
  18.         f.setAccessible(true);  //指示反射的对象在使用时是否取消 Java 语言访问检查  
  19.         f.set(p, "zhangsan");   //指定该字段所对应的对应的值  
  20.         p.show();  
  21.   
  22.         Field[] fs = Person.class.getDeclaredFields();//获得全部的字段,数组  
  23.         for(Field ff: fs)  
  24.         {  
  25.             if(!ff.isAccessible())  
  26.                 ff.setAccessible(true);  
  27.             if(ff.getType() == String.class)//getType()返回的是一个class的二进制码文件,由于该文件具有唯一性,直接用等于号进行判断  
  28.             {  
  29.                 ff.set(p, "lisi");  
  30.                 // 得到该字段的对应值,进行修改!  
  31.                 //String s1 = (String)ff.get(p);//get()方法返回的是Object类型,必须进行强制向下转换  
  32.                 //String s = ...修改语句;  
  33.                 //ff.set(p, s);  
  34.             }  
  35.         }  
  36.         p.show();  
  37. //Method  
  38.         Method m = Person.class.getMethod("set", String.classint.class);  
  39.         m.invoke(p, "wangwu"100);  
  40.         p.show();  
  41.   
  42.         Method mm = Person.class.getMethod("haha"); //静态方法的处理  
  43.         mm.invoke(null);//此处为null,凡是为静态的字段或者方法,实例对象位置为null  
  44.   
  45.         Field f1 = Person.class.getDeclaredField("country");//静字段的处理  
  46.         f1.setAccessible(true);  
  47.         String ss = (String)f1.get(null);  
  48.         System.out.println(ss);  
  49.         f1.set(null"usa");  
  50.         Person.haha();  
  51.   
  52.     }  
  53. }  
  54. class Person  
  55. {  
  56.     private int age;  
  57.     private String name;  
  58.     private static String country = "zn";   
  59.     Person(){}  
  60.     Person(String name, int age)  
  61.     {  
  62.         this.name = name;  
  63.         this.age = age;  
  64.     }  
  65.     public void show()  
  66.     {  
  67.         System.out.println(name+":"+age);  
  68.     }  
  69.     public void set(String name, int age)  
  70.     {  
  71.         this.name = name;  
  72.         this.age = age;  
  73.     }  
  74.     public static void haha()  
  75.     {  
  76.         System.out.println("country:"+country);  
  77.     }  
  78. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值