反射

来源:互联网 发布:程序员和运维工程师 编辑:程序博客网 时间:2024/05/20 13:09

反射的概述:

 

Java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是多少,则由这个类的实例对象来确定。

Java程序中的各个java类,他们是否属于一类事物,描述这类事物的java类名就是Class

如何得到各个字节码对象对应的实例对象(Class类型)

1、类名.class 例如:Class class1 =Person.class//字节码1;

2、对象.getClass() 例如:P1.getClass();

3\Class.forName(“类名”) 例如:Class.forName(“java.lang.String”);//作用:返回类字节码

有两种形式可以得到字节码

1、 字节码 已经加载到内存中,找到字节码返回;

2、 没有加载到内存中,用类加载器加载到内存中,缓存字节码,用返回字节码。

  • 数组类型的Class实例对象

class.isArray()

总之,只要是在源程序中出现的类型,都有各自的Class实例对象

  String str1 = "abc";Class class1 =str1.getClass();Class class2 =String.class;Class class3 =Class.forName("java.lang.String");System.out.println(class1==class2);      //trueSystem.out.println(class1==class3); //trueSystem.out.println(class1.isPrimitive());       //falseSystem.out.println(int.class.isPrimitive());       //基本类型trueSystem.out.println(int.class==Integer.class);      //falseSystem.out.println(int.class==Integer.TYPE);       //常量trueSystem.out.println(int[].class.isPrimitive());       //false  System.out.println(int[].class.isArray());      //true

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

例如:一个java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,修饰符、包等信息用一个个的java类来表示。

//编译器只看变量的定义不看代码的执行

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

1)得到某个类所有的构造方法:

例子

   Constructor[]  constructors =    Class.forName(“java.lang.String”).getConstructor();//class—>constructor-->new object

2)得到某一个构造方法:

例子:

   Constructor  constructor =    Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);

3)创建实例对象

通常方式:String str = new String(new StringBuffer(“abcd”));

反射方式:String str =

(String)constructor. newInstance(new StringBuffer("abc"));

//调用获得的方法时要用到上面相同类型的实例对象

.newInstance()方法返回值类型是Object

//表示用这个构造方法时,传递的StringBuffer对象(同样类型的对象)


4Class.newInstance()方法

例子:String obj = (String) Class.forName(“java.lang.String”).newInstance();

  该方法内部先得到默认的构造方法,然后用构造方法创建实例对象。

用缓存机制保存默认构造方法的对象。

  • 成员变量的反射:

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

  ReflectPoint pt1 = new ReflectPoint(3, 5);Field fieldY = pt1.getClass().getField("y");//fieldY 代表类字节码中的变量,不是对象本身的变量,而是类上,要用它去取某个对象的值System.out.println(fieldY.get(pt1));Field fieldX = pt1.getClass().getDeclaredField("x");fieldX.setAccessible(true);//暴力反射(变量为私有)看见了取不到 用暴力反射   System.out.println(fieldX.get(pt1));   

  public class ReflectPoint {private int x;public int y;  public String str1 = "ball";public String str2 = "basketball";public String str3 = "itcast";//自动生成构造函数public ReflectPoint(int x, int y) {super();this.x = x;this.y = y;}}   private static void changeStringValue(Object obj) throws IllegalArgumentException, IllegalAccessException {Field[] fields = obj.getClass().getFields();for(Field field:fields){//if(field.getType().euqals(String.class))//因为是同一份字节码if (field.getType()==String.class) {String oldValue = (String)field.get(obj);String newValue = oldValue.replace('b', 'a');field.set(obj, newValue);}}   }

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

1) 得到类中的某一个方法:

例子:Method charAt = 

Class.forName(“java.lang.String”).getMethod(“charAt”,int.class);

2) 调用方法

通常方式:System.out.println(str.charAt(1));

反射方式:System.out.println(charAt.invoke(str,1));

如果传递给method对象的invoke()方法的第一个参数为null,则该method对象对应的是一个静态方法!

Jdk1.4jdk1.5invoke方法的区别(可变参数)

//拿出字节码的方法 再作用于某个对象Method methodCharAt = String.class.getMethod("charAt", int.class);System.out.println(methodCharAt.invoke(str1, 1));//jdk1.4的调用方法System.out.println(methodCharAt.invoke(str1,new Object[]{2}));   //1.5 可变参数   methodCharAt.invoke(Object obj,Object[] args);

  • 对接收数组参数的成员方法进行反射

用反射方式执行某个类中的main方法

  class TestArguments {public static void main(String[] args) {for(String arg :args){System.out.println(arg);}}//调用main方法//TestArguments.main(new String[]{"123","345","sss"});    //用反射去调用    String startingStringClassName = args[0];    Method mainMethod = Class.forName(startingStringClassName).getMethod("main", String[].class);//方法1java兼容性 传递数组时拆封    mainMethod.invoke(null, new Object[]{new String[]{"ss","123"}});//方法2java兼容性 传递数组时拆封mainMethod.invoke(null,(Object)new String[]{"ss","123"});

  • 数组的反射

数组字节码类型相同的要满足:

1·元素类型相同

2·维数相同 

则它们具有相同的Class实例对象

注意:基本类型的一维数组可以被当作Object类型使用,不能当作能当作Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以做Object[]类型使用。

Arrays.aslist()方法处理intString[]时的差异--

不能得到整个数组的类型 可以得到某个值的类型

例子:a[0].getClass().getName();

//数组    int[] a1 = new int[3];    int[] a2 = new int[4];    int[][] a3 = new int[2][3];    String[] a4 = new String[]{"ad","bd","cd"};        System.out.println(a1.getClass()==a2.getClass());     //true    //System.out.println(a1.getClass()==a4.getClass());//false    //System.out.println(a1.getClass()==a3.getClass());//false    System.out.println(a1.getClass().getName());    System.out.println(a1.getClass().getSuperclass().getName());//Object    System.out.println(a4.getClass().getSuperclass().getName());//Object        Object aObj1 = a1;    Object aObj2 = a4;    //Object[] aObj3 = a1; int 不是object    Object[] aObj4 = a3;    Object[] aObj5 = a4;    System.out.println(a1);    System.out.println(a4);    System.out.println(Arrays.asList(a1));//一个参数[I@1cfb549]    System.out.println(Arrays.asList(a4));//[a,b,c]        printlnObject(a4);    printlnObject(123);//通用方法private  static void  printlnObject(Object obj) {Class clazz = obj.getClass();if (clazz.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);}



怎么得到数组的元素类型

Int[]a=new int[2]

    直接用数组对象a无法得到

只能先得到一个元素的类型a[0].getClass().getName()


  • ArrayList_HashSet的比较及Hashcode分析

Arraylist 无论对象是否相同,都可存入引用

Hashset 如果集合中已有该对象,则不再存入。

Hashcode 的作用:每个集合分区域 哈希值对应区域(提高查找效率)提高对集合操作的效率 (内存泄漏) (内存一直被占用)

计算Hashcode 值得参数一般不要改变,如果改变可能造成数据操作失败。

  • 反射的作用--->实现框架功能
框架:别人调用你的类 

框架要解决的核心问题:利用反射

InputStream ips= new FileInputStream("config.properties");Properties ps = new Properties();ps.load(ips);ips.close();String className = ps.getProperty("className");   Collection collections = (Collection)Class.forName(className).newInstance();


原创粉丝点击