Java的反射机制

来源:互联网 发布:24点计算器软件 编辑:程序博客网 时间:2024/06/05 09:13
1,反射的基石-->class

    一个类被类加载器加载到内存中,占用一片存储空间,一个类对应一个字节码对象,但是这个字节码对象可以对应多个实例对象。这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的。

    反射就是把Java类中的各种成分映射成相应的java类。一个类中的组成部分:成员变量,方法,构造方法,包等等信息用一个个的Java类来表示,它们是Field、Method、Contructor、Package等等。

    JAVA反射机制是在运行状态中,对于任意一个类 (class文件),都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。动态获取类中信息,就是java反射。可以理解为对类的解剖。要想要对字节码文件进行解剖,必须要有字节码文件对象。如何获取字节码文件对象呢?

2,获取字节码对象的三种方式

1,Object类中的getClass()方法的。 想要用这种方式,必须要明确具体的类,并创建对象,麻烦
Person p = new Person(); 
Class clazz = p.getClass();   
2,任何数据类型都具备一个静态的属性.class来获取其对应的Class对象。相对简单,但是还是要明确用到类中的静态域
Class clazz = Person.class;
3,只要通过给定的类的字符串名称就可以获取该类,更为扩展。可是用Class类中的方法完成。该方法就是forName.这种方式只要有名称即可,更为方便,扩展性更强。 
String className = "cn.com.bean.Person";    
Class clazz = Class.forName(className); 

3,九个预定义Class实例对象

    参看Class.isPrimitive方法的帮助;数组类型的Class实例对象Class.isArray()。总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int[],void…

String str1 = "abc";Class cls1 = str1.getClass();Class cls2 = String.class;Class cls3 = Class.forName("java.lang.String");System.out.println(cls1 == cls2); //trueSystem.out.println(cls1 == cls3);  //true     System.out.println(cls1.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()); //falseSystem.out.println(int[].class.isArray());   //true

4,Constructor类和反射对象
Constructor类代表某个类中的一个构造方法
1,得到某个类所有的构造方法:
Constructor[] constructors= Class.forName("java.lang.String").getConstructors();
2,得到某一个构造方法:
Constructor constructor =Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);
反射对象,不多说,直接上例子:

package cn.com.bean;import java.lang.reflect.Constructor;class Person {String name;int age;public Person() {}public Person(String name) {this.name = name;}public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String toString() {return "Person [name=" + name + ", age=" + age + "]";}}public class Test{public static void main(String[]args) throws Exception{//通过反射实例化对象,一般是通过Constructor的newInstance方法。为了简便,Class类也提供了newInstance方法,但只能调用无参的构造方法。Class clazz = Class.forName("cn.com.bean.Person");Constructor con = clazz.getConstructor(String.class);Object obj = con.newInstance("小明");System.out.println(obj);//Person [name=小明, age=0]Constructor con1 = clazz.getConstructor(String.class,int.class);Object obj1= con1.newInstance("小明",32);System.out.println(obj1);//Person [name=小明, age=32]Constructor con2 = clazz.getConstructor();Object obj2 = con2.newInstance();System.out.println(obj2);//Person [name=null, age=0]Object obj3 = clazz.newInstance();System.out.println(obj3);//Person [name=null, age=0]}}

5,Field类和Method

不多说,上例子:

public class ReflectDemo3 {      public static void main(String[] args) throws Exception { Class clazz = Class.forName("cn.itcast.bean.Person");   Field field = null;//clazz.getField("age");//只能获取公有的,   field = clazz.getDeclaredField("age");//只获取本类,但包含私有。       //对私有字段的访问取消权限检查。暴力访问。   
<span style="white-space:pre"></span>//field.setAccessible(true);      Object obj = clazz.newInstance();      field.set(obj, 89);      Object o = field.get(obj);      System.out.println(o);     }    } public class ReflectDemo4 {     public static void main(String[] args) throws Exception {   Class clazz = Class.forName("cn.itcast.bean.Person");      Method method = clazz.getMethod("paramMethod", String.class,int.class);      Object obj = clazz.newInstance();    
<span style="white-space:pre"></span>//<span style="font-family: Arial, Helvetica, sans-serif; color: red;">如果传递给</span><span style="font-family: Arial, Helvetica, sans-serif; color: red;">Method</span><span style="font-family: Arial, Helvetica, sans-serif; color: red;">对象的</span><span style="font-family: Arial, Helvetica, sans-serif; color: red;">invoke()</span><span style="font-family: Arial, Helvetica, sans-serif; color: red;">方法的第一个参数为</span><span style="font-family: Arial, Helvetica, sans-serif; color: red;">null</span><span style="font-family: Arial, Helvetica, sans-serif; color: red;">,说明该</span><span style="font-family: Arial, Helvetica, sans-serif; color: red;">Method</span><span style="font-family: Arial, Helvetica, sans-serif; color: red;">对象对应的是一个静态方法!</span><span style="white-space:pre"></span>//method.invoke(null,"小强",89);这说明这个paramMethod方法是静态方法。  method.invoke(obj, "小强",89);         }   public static void getMethodDemo_2() throws Exception {      Class clazz = Class.forName("cn.itcast.bean.Person");    Method method = clazz.getMethod("show", null);//获取空参数一般方法。不写效果一样     Method method = clazz.getMethod("show");//和上面效果一样     Constructor constructor = clazz.getConstructor(String.class,int.class);   Object obj = constructor.newInstance("小明",37);      method.invoke(obj, null);    //method.invoke(obj);//和上面效果一样           }     /*   * 获取指定Class中的所有公共函数。       */  public static void getMethodDemo() throws Exception {      Class clazz = Class.forName("cn.itcast.bean.Person");      Method[] methods  = clazz.getMethods();//获取的都是公有的方法。    methods = clazz.getDeclaredMethods();//只获取本类中所有方法,包含私有。    for(Method method : methods){    System.out.println(method);   }    } }
6,数组

1,具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
2,代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。
3,基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。
int [] a1 = new int[]{1,2,3};
Object aObj3 = a1; //对
Object[] aObj3 = a1; //错
4,Arrays.asList()方法处理int[]和String[]时的差异。
Arrays.asList(String[]),放回一个List,List中的元素就是原来String[]中的元素。
而Arrays.asList(int[],放回一个List,只有一个元素,就是int[]本身。

5,补充,理解数组:
int[][] a3 = new int[3][4];
String[] a4 = new String[3];
a3是一个数组,数组的每个元素的类型是int[]
a4是一个数组,数组的每个元素的类型是String

直接上例子:

public class ReflectTest {<span style="white-space:pre"></span>public static void main(String[] args) throws Exception {<span style="white-space:pre"></span>int[] a1 = new int[] { 1, 2, 3 };<span style="white-space:pre"></span>int[] a2 = new int[4];<span style="white-space:pre"></span>int[][] a3 = new int[2][3];<span style="white-space:pre"></span>String[] a4 = new String[] { "a", "b", "c" };<span style="white-space:pre"></span>Object[] a5 = new Object[] { "33", "4" };<span style="white-space:pre"></span>System.out.println(a1.getClass() == a2.getClass());<span style="white-space:pre"></span>System.out.println(a1.getClass().getName());<span style="white-space:pre"></span>System.out.println(a1.getClass().getSuperclass().getName());<span style="white-space:pre"></span>System.out.println(a4.getClass().getSuperclass().getName());<span style="white-space:pre"></span>System.out.println(a4.getClass().getName() == a4.getClass()<span style="white-space:pre"></span>.getSuperclass().getName());<span style="white-space:pre"></span>System.out.println(a5[0].getClass().getName());<span style="white-space:pre"></span>// true<span style="white-space:pre"></span>// [I<span style="white-space:pre"></span>// java.lang.Object<span style="white-space:pre"></span>// java.lang.Object<span style="white-space:pre"></span>// false<span style="white-space:pre"></span>// java.lang.String<span style="white-space:pre"></span>}}
7,用类加载器加载资源文件

直接上例子:

package cn.itcast.day1;import java.io.InputStream;import java.util.Collection;import java.util.Properties;public class ReflectTest2 {public static void main(String[] args) throws Exception {/** * getRealPath(); 一定要记住用完整的路径,但完整的路径不是硬编码,而是运算出来的。 不以/开头的是相对路径,/表示应用 */// InputStream ips = new FileInputStream("config.properties");// InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.properties");// InputStream ips = ReflectTest2.class.getResourceAsStream("resources/config.properties");// 其实ReflectTest2.class.getResourceAsStream内部还是调用了classLoader// public InputStream getResourceAsStream(String name) {// name = resolveName(name);// ClassLoader cl = getClassLoader0();// if (cl==null) {// // A system class.// return ClassLoader.getSystemResourceAsStream(name);// }// return cl.getResourceAsStream(name);// }InputStream ips = ReflectTest2.class.getResourceAsStream("/cn/itcast/day1/resources/config.properties");Properties props = new Properties();props.load(ips);ips.close();String className = props.getProperty("className");Collection collections = (Collection) Class.forName(className).newInstance();System.out.println(collections.size());}}



















0 0
原创粉丝点击