黑马程序员——反射

来源:互联网 发布:如何改变自己 知乎 编辑:程序博客网 时间:2024/04/30 10:22

反射技术(一)

在反射中,有个Class类,被称为反射的基石,注意此处的C为大写。

例如在Person类中

Person p1= new Person();

那么就有

Class p1=Person.class();

p1就表示Person 类在内存中存储的字节码文件,该字节码的类型为Class

获取类字节码的方式有三种(那Person类举例):

1.Class p1=Person.class ;

2.p1.getClass();根据对象p1获取对象p1所在对象的字节码

3.Class.forName("类名");在实际开发中类名一般为变量,,开发中使用这一种方式做反射。

Class.forName("类名")方法分为两种情况,一种情况是类已经被加载到虚拟机内存,那么就可以直接返回字节码,另外一种,没有加载,那么就先加载进虚拟机,然后返回字节

码。


在Class中,有九个预定义的实例对象,包括八个基本数据类型,和一个void类型

数组类型的Class实例对象:

数组类型的Class实例对象,用的是Class.isArray()

总之只要在源程序中出现的数据类型,又有各自对应的实例对象。


反射定义:就是把Java类中的各种成分映射成相应的Java类。

反射的内容包括四个:Field,Method,constructor,package


1.Constructor

首先来看看怎么反射Constructor,其他几个反射的内容都是类似,依葫芦画瓢。

Constructor类为构造方法类,作用:

可以通过Constructor得到某个类的所有的构造方法

eg;Constructor constructor[]=Class.forName("java.lang.String").getConstructor();


首选需要创建实例对象:

(1)通常方式:String str =new String(new StringBuffer("abc"));

  (2)反射方式:String str=(String)constructor.new Instance(new StringBuffrer("abc"));


Constructor类的基本方法:

getName();得到Constructor所属类的名字;

hashCode();返回此Constructor的哈希值

newInstance*(); 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。

toString();返回描述此 Constructor 的字符串。


思想和步骤:

1) Constructor  constructor=String.classgetConstructor(StringBuffer.class);

第一步获得String的所属类的字节码,表示选择哪个构造方法


2)String str=(String)constructor.newInstance(new StringBuffer("abc"));

第二部把获取的方法强制转换为String类型


此处需要注意:得到方法的时候需要类型;用方法的时候传递的类型要和第一步的保持一致。

使用映射的实例:


package cn.itcast.day1;


import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
public class ReflectTest 
public static void main(String[] args) throws Exception {

String str1 = "abc";
Class cls1 = str1.getClass();
Class cls2 = String.class;
Class cls3 = Class.forName("java.lang.String");

System.out.println(cls1.isPrimitive());
System.out.println(int.class == Integer.class);
System.out.println(int.class == Integer.TYPE);
System.out.println(int[].class.isPrimitive());
System.out.println(int[].class.isArray());

Constructor constructor1 = String.class
.getConstructor(StringBuffer.class);
String str2 = (String) constructor1
.newInstance(new StringBuffer("abc"));
System.out.println(str2.charAt(2));

ReflectPoint pt1 = new ReflectPoint(3, 5);
Field fieldY = pt1.getClass().getField("y");
System.out.println(fieldY.get(pt1));

Field fieldX = pt1.getClass().getDeclaredField("x");
fieldX.setAccessible(true);
System.out.println(fieldX.get(pt1));
changeStringValue(pt1);
System.out.println(pt1);
Method methodCharAt = String.class.getMethod("charAt", int.class);
System.out.println(methodCharAt.invoke(str1, 1));
System.out.println(methodCharAt.invoke(str1, new Object[] { 0 }));
String startingClassName = args[0];
Method mainMethod=Class.forName(startingClassName).getMethod("main",String[].class);
mainMethod.invoke(null,new Object[]{new String[] { "2", "33", "55" }});
int [] a1=new int[]{1,2,3};
int [] a2=new int[4];
int [][] a3=new int[2][3];
String [] a4= new String[]{"a","b","c"};
System.out.println(a1.getClass() == a2.getClass());
System.out.println(a1.getClass().getName());
System.out.println(a1.getClass().getSuperclass().getName());
System.out.println(a4.getClass().getSuperclass().getName());
Object aObj1=a1  ;
Object aObj2=a4 ;
Object[] aObj4=a3  ;
Object[] aObj5=a4  ;
System.out.println(Arrays.asList(a1));
System.out.println(a1);
System.out.println(a4);
System.out.println(Arrays.asList(a1));//因为是int类型,jdk1.5 Obkect没法处理int类型
System.out.println(Arrays.asList(a4));
printObject(a4);
printObject("xyz");
}
private static void printObject(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");
   } }
private static void changeStringValue(Object obj) throws Exception {
Field[] fields = obj.getClass().getFields();
for (Field field : fields) {
if (field.getType() == String.class) {
String oldValue = (String) field.get(obj);
String newValue = oldValue.replace('b', 'a');
field.set(obj, newValue);
}
}}
}
class TestArguments {
public static void main(String args[]) {
for (String arg : args) {
System.out.println(arg);
}}}

自我学习心得:在学习机制中,学习到反射是用来反射出类字节码中的Field(成员字段),Method,constructor,package一系列信息,是一个很强大的技术,真正的去理解反射是用来做什么的,在上述中有示例代码中的Constructor类的反射,其他的几个也是类似,基本思想是一样的。

0 0