高薪<反射>

1. 反射

      1.概述

             Java类用于描述一类事物的共性,其类有什么属性,不同的实例对象有不同的属性值。就是把java类中的各种成分映射成相应的java类。

      Class:表示的是各个java类是否属于同一类事物。描述的是:类的名字,类的访问属性,类所属于的包名,字段名称的列表,方法名称的列表。

         比较记忆:

          Person类代表人,他的实例是:张三,李四。。等具体的人,

          Class类代表java类,他的实例对象对应的是:

       对象各个类在内存中的字节码,例如:Person类的字节码,ArrayList类的字节码

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

 
      2.基本方法

          格式:

        格式1:类名.class;

        格式2:对象.getClass()

        格式3:Class.forName(“包名.类名”);

        九个预定义对象 基本数据类型(boolean、byte、char、short、int、long、float 和double。)和void

        只有这写基本类型的包装类可以通过包装类.TYPE获得所包装的基本类型的Class对象。

1.  public class reflectDemo {  

2.   public static void main(String[] args) throws Exception {  

3.     String str = "hello";  

4.     Class strClass= String.class;// 类名.class  

5.     Class strClass1 = str.getClass();// 对象.getClass  

6.     Class strClass2 = Class.forName("java.lang.String");// 使用Class.forName("包名.类名")  

7.     System.out.println("String的字节码:" + strClass);  

8.     System.out.println(strClass == strClass1);// true  

9.     System.out.println(strClass == strClass2);// true  

10.     // 从而可以证明,String在内存的字节码是唯一的  

11.     /* 

12.      * boolean isPrimitive()判断Class对象是否是表示一个基本类型 

13.      */  

14.     System.out.println("String是否是基本类型:" + strClass.isPrimitive());  

15.     System.out.println("int是否是基本类型:" + int.class.isPrimitive());  

16.     /* 包装类通过包装类.TYPE获得所封装的基本类型的Class字节码对象 */  

17.     System.out.println("Integer.TYPE是否是基本类型:" + Integer.TYPE.isPrimitive());  

18.     /* 

19.      * public boolean isArray()判定此 Class 对象是否表示一个数组类。 

20.      */  

21.     System.out.println("int []是否是数组类型:" + int[].class.isArray());  

22.    

23.   }  

24.    

25. }  

26. 结果:  

27. String的字节码:class java.lang.String  

28. true  

29. true  

30. String是否是基本类型:false  

31. int是否是基本类型:true  

32. Integer.TYPE是否是基本类型:true  

33. int []是否是数组类型:true  

      3.构造函数(反射)

         通过Constructor类来获得构造函数,然后获得对象。

    也可以通过Class中的newInstance方法获得无参的构造函数的对象,  

1.  import java.lang.reflect.Constructor;  

2.    

3. public class reflectDemo {  

4.   public static void main(String[] args) throws Exception {  

5.     Class strClass = String.class;// 类名.class  

6.     /* 

7.      * 使用Constructor类获得构造方法,调用Class的getConstructor(Class...para)方法, 

8.      * 调用此方法的时候,参数是是Class,通过参数的类型指定获得那一个构造方法。 

9.      * newInstance(和指定参数类型的那个一样的对象)来获得对象 

10.      */  

11.     Constructor con=strClass.getConstructor(StringBuffer.class);  

12.           String str=(String) con.newInstance(new StringBuffer("abc"));  

13.           System.out.println(str);  

14.           /** 

15.            * 也可以通过Class的newInstance()获得无参的构造方法的对象 

16.            */  

17.           String str1=(String)strClass.newInstance();  

18.           str1="bdc";  

19.           System.out.println(str1);  

20.   }  

21.    

22. }  

23. 结果:  

24. abc  

25. bdc  

   用获得的构造方法创建实例,此时创建的时候的参数和你获得构造方法时的参数类型要一样

 

   4.字段(Filed)反射

             4.1字段反射

1.  import java.lang.reflect.Field;  

2. class Person{  

3.   public String name;  

4.   private int age;  

5.   public Person(String name,int age){  

6.     this.name=name;  

7.     this.age=age;  

8.   }  

9. }  

10. public class FiledDemo {  

11.   public static void main(String[] args) throws Exception {  

12.     Class pC=Person.class;//获得Person类的字节码  

13.     Person p=new Person("abc",23);  

14.     /** 

15.      * 获得公共字段(getField),这只是获得字段对象,不含有值,要是获得某个对象的值 

16.      * 那么需要get(对象)来获得 

17.      */  

18.     Field fieldName=pC.getField("name");//获得字段  

19.     String name=(String)fieldName.get(p);//获得对象中字段的值  

20.     System.out.println("name="+name);  

21.     /** 

22.      * 获得私有字段(getDeclaredField()),这里也只是获得只是简单的字段,不包含值 

23.      * setAccessible()设置可操作 

24.      */  

25.     Field filedAge=pC.getDeclaredField("age");  

26.     filedAge.setAccessible(true);//可操作  

27.      Objectage=filedAge.get(p);//获得此对象的值  

28.     System.out.println("age="+age);  

29.   }  

30.    

31. }  

32. 结果:  

33. name=abc  

34. age=23  

 

   4.2更改字段的值

   将对象中的字段是String类型的,那么就取对象的值,将值中的字符b更改为字符0,然后输出

 1. import java.lang.reflect.Field;  

2.   

3.   

4. class Person{  

5.     public String name;  

6.     private int age;  

7.     public Person(String name,int age){  

8.         this.name=name;  

9.         this.age=age;  

10.     }  

11.     public String toString(){  

12.         return name+":"+age;  

13.     }  

14. }  

15. public class FiledDemo {  

16.     public static void main(String[] args) throws Exception {  

17.         Class pC=Person.class;//获得Person类的字节码  

18.         Person p=new Person("abc",23);  

19.         /** 

20.          * getFields()获得所有字段 

21.          */  

22.         Field [] fileds=pC.getFields();  

23.         for(Field f :fileds){//遍历  

24.             if(String.class==f.getType()){//判断f的类型是否是String类型  

25.                 String oldValue=(String)f.get(p);  

26.                 String newValue=oldValue.replace('b''0');//将字段上的值的b替换成0  

27.                 f.set(p, newValue);//重新传给对象  

28.                   

29.             }  

30.         }  

31.         System.out.println(p);  

32.     }  

33.   

34. }  

35. 结果:  

36. a0c:23  

     5.方法反射(Method)

            5.1普通方法反射

1. import java.lang.reflect.Method;  

2. public class MethodDemo {  

3.   public static void main(String[] args)throws Exception {  

4.     /** 

5.      * 通过getMethod(方法名,参数类型)获得方法对象 

6.      * invoke(对象,参数)来调用获得的方法, 

7.      */  

8.     String str="abcd";  

9.     Method methodcharAt=String.class.getMethod("charAt",int.class);  

10.     System.out.println(methodcharAt.invoke(str, 3));  

11.     System.out.println(methodcharAt.invoke("defh"3));  

12.      

13.   }  

14.    

15. }  

 5.2,静态方法反射

1. import java.lang.reflect.Method;  

2.    

3. public class MethodDemo {  

4.   public static void main(String[] args)throws Exception {  

5.     /** 

6.      * 如果invoke(null,参数),那么就表示调用此方法的方法是静态方法 

7.      */  

8.      

9.     Method methosMax=Math.class.getMethod("max"int.class,int.class);  

10.     System.out.println(methosMax.invoke(null2357));  

11.   }  

12.    

13. }  

  5.3主函数(main)反射

1.  import java.lang.reflect.Method;  

2.    

3. public class mainDemo {  

4.   public static void main(String[] args) throws Exception {  

5.    

6.     Method mianMethod = Class.forName("wang.fuxi.jiaqiang.text").getMethod(  

7.          "main", String[].class);  

8.     mianMethod.invoke(nullnew Object[] { new String[] { "123""456",  

9.          "789" } });  

10.   }  

11.    

12. }  

13.    

14. class text {  

15.   public static void main(String[] agrs) {  

16.     System.out.println(agrs.length);  

17.   }  

18. }  

19. 结果:  

20. 3  

    注意:在调用主函数的时候,给主函数传数组参数的时候,程序会先拆包,然后取里面的参数,所以我们要先把数组封装起来,否则,报异常,

  在运行主调类的主函数的时候,也可以在在类中右击—run configurations----arguments----然后把被调用类的位置传进去(包名.类名),然后调用的时候就可以使用       Method mianMethod =Class.forName(argus[0]).getMethod("main", String[].class);来获得被调类的主函数。

传参的方式:

       invoke(null,new Object[] { new String[] {"123", "456", "789" } });

或者: 

      invoke(null, (Object)(new String[] {"123", "456","789" } ));

 

    6.数组反射

       数组类型相同并且维数也相同,那么他们的Class字节码对象才相等,还有对于AsList(T…. ts)方法来说,在1.5之后,那么int数组把其当作一个参数来处理,如果是String数组,那么就分来作为参数。

      6.1基本判断

1. import java.util.Arrays;  

2.    

3. public class SuZuDemo {  

4.   public static void main(String[] args) {  

5.     int[] a = new int[3];  

6.     int[] b = new int[4];  

7.     int[][] c = new int[3][4];  

8.     String[] s1 = new String[3];  

9.     System.out.println(a.getClass() == b.getClass());// true  

10.     //System.out.println(a.getClass()==c.getClass());//编译失败  

11.     //System.out.println(a.getClass()==s1.getClass());//编译失败  

12.     /** 

13.      * 获得父类的字节码,从结果知道,他们的父类的是Object 

14.      */  

15.     System.out.println(a.getClass().getSuperclass().getName());  

16.     System.out.println(s1.getClass().getSuperclass().getName());  

17.     int[] a1 = new int[] { 123 };  

18.     String[] s2 = new String[] { "a""b""c" };  

19.     System.out.println(Arrays.asList(a1));// 在1.5后,此此方法会把整形数组当作一个参数处理  

20.     System.out.println(Arrays.asList(s2));// 会把String数组拆分,分别作为参数来处理  

21.   }  

22.    

23. }  

24. 结果:  

25. true  

26. java.lang.Object  

27. java.lang.Object  

28. [[I@1f66cff]  

29. [a, b, c]  

    6.2,反射数组

       使用Array类。

1. import java.lang.reflect.Array;  

2. import java.util.Arrays;  

3.    

4. public class SuZuDemo {  

5.   public static void main(String[] args) throws Exception {  

6.     String[] s = { "abc""def""hig" };  

7.     String ss = "hello";  

8.     print(s);  

9.     print(ss);  

10.   }  

11.    

12.   public static void print(Object ob) {  

13.     Class classzz = ob.getClass();// 反射  

14.     if (classzz.isArray()) {// 判断的是否是数组  

15.       int len = Array.getLength(ob);// 获取长度  

16.       for (int i = 0; i < len; i++) {  

17.          System.out.println(Array.get(ob, i));// 获得数组中的元素  

18.       }  

19.     } else {  

20.       System.out.println(ob);  

21.     }  

22.   }  

23.    

24. }  

25. 结果:  

26. abc  

27. def  

28. hig  

29. hello  

30.    

2. 反射的应用

    1.  HashCode()方法和HashSet的联系

      HashSet集合中,要是存放了对象,那么就不要修改在对象中的字段的值,否则会出现内存泄漏,溢出,只要一修改,那么哈希值会改变,就不会在那个区域找到此对象,

     HashCode(),是为了比较对象,然后就是把不相同的对象存储到集合中,在集合中存放早集合中的对象,不要修改,否则会出现内存泄漏。只用于Set集合中,在List集合中没有起到作用。

1. import java.util.ArrayList;  

2. import java.util.Collection;  

3. import java.util.HashSet;  

4.    

5. public class SetDemo {  

6.   public static void main(String[] args) {  

7.     Collection con = new HashSet();  

8.     TextDemo t1 = new TextDemo("zhangsan"12);  

9.     TextDemo t2 = new TextDemo("lisi"12);  

10.    

11.     con.add(t1);  

12.     con.add(t2);  

13.     con.add(t2);  

14.     //t1.age = 23;// 更改了字段的值,那么hashCode值也变了,那么再移除修改的对象,那么就会找不到  

15.     t1.setAge(22);//这样修改了,那么也会找不到原来的元素  

16.     System.out.println(con.remove(t1));//fasle  

17.     System.out.println(con.size());  

18.   }  

19.    

20. }  

21.    

22. class TextDemo {  

23.   String name;  

24.   int age;  

25.    

26.   public TextDemo(String name, int age) {  

27.     this.name = name;  

28.     this.age = age;  

29.   }  

30.    

31.   @Override  

32.   public int hashCode() {  

33.     final int prime = 31;  

34.     int result = 1;  

35.     result = prime * result + age;  

36.     result = prime * result + ((name == null) ? 0 : name.hashCode());  

37.     return result;  

38.   }  

39.    

40.   @Override  

41.   public boolean equals(Object obj) {  

42.     if (this == obj)  

43.       return true;  

44.     if (obj == null)  

45.       return false;  

46.     if (getClass() != obj.getClass())  

47.       return false;  

48.     TextDemo other = (TextDemo) obj;  

49.     if (age != other.age)  

50.       return false;  

51.     if (name == null) {  

52.       if (other.name != null)  

53.          return false;  

54.     } else if (!name.equals(other.name))  

55.       return false;  

56.     return true;  

57.   }  

58.    

59.   public void setAge(int age) {  

60.     this.age = age;  

61.   }  

62. }  

    2. 框架案例

     框架,框架就是调用你写的类,工具类:就是你调用工具类来完善你的。在你没有写出你的类的时候,

框架已经产生,现在使用把类名存储在文件中,然后利用反射来创建此对象,当你更配置的时候,框架中相应的额跟着改变。

   现在nane.properties文件中存放的是:

       className=java.util.HashSet

1. public static void main(String[] args) throws Exception {  

2.     InputStream in=new FileInputStream("nane.properties");  

3.         Properties pro=new Properties();  

4.         pro.load(in);  

5.         in.close();  

6.         String className=pro.getProperty("className");  

7.         Class c=Class.forName(className);  

8.         Collection con=(Collection)c.newInstance();  

9.         con.add(newPerson(1,2));  

10.         con.add(newPerson(4,2));  

11.         con.add(newPerson(3,2));  

12.         con.add(newPerson(1,2));  

13.         System.out.println("集合长度:"+con.size());  

14.   }结果:  

15. 集合长度:3  

      也可以打开配置文件,然后进行更改里面的值,那么结果就会跟着改变。

  className=java.util.ArrayList

1. public static void main(String[] args) throws Exception {  

2.     InputStream in=new FileInputStream("nane.properties");  

3.         Properties pro=new Properties();  

4.         pro.load(in);  

5.         in.close();  

6.         String className=pro.getProperty("className");  

7.         Class c=Class.forName(className);  

8.         Collection con=(Collection)c.newInstance();  

9.         con.add(new Person(1,2));  

10.         con.add(new Person(4,2));  

11.         con.add(new Person(3,2));  

12.         con.add(new Person(1,2));  

13.         System.out.println("集合长度:"+con.size());  

14.          

15.   }结果:  

16. 集合长度:4  

    3. 加载资源的位置

       1.可是使用绝对路径,但是那么就使用getRealPath,然后进行存数,

       2.使用加载器

         加载器可以加载java文件,那么也可以加载配置文件,但是有一点缺点,就是配置文件只能读取不能修改,可以使用相对路径,那么最前面要加”/”,否则就不用加”/”,表示的是根目录。

         InputStream in=Text.class.getClassLoader().getResourceAsStream("/包名/nane.properties");

Text是运行类的类名,nane.properties是配置的文件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值