首页 > 代码库 > 黑马程序员——反射
黑马程序员——反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
有时候我们说某个语言具有很强的动态性,有时候我们会区分动态和静态的不同技术与作法。我们朗朗上口动态绑定(dynamic binding)、动态链接(dynamic linking)、动态加载(dynamic loading)等。然而“动态”一词其实没有绝对而普遍适用的严格定义,有时候甚至像面向对象当初被导入编程领域一样,一人一把号,各吹各的调。
一般而言,开发者社群说到动态语言,大致认同的一个定义是:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。
尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机制:Reflection。这个字的意思是“反射、映象、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。这种“看透class”的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。
Java如何能够做出上述的动态特性呢?这是一个深远话题,本文对此只简单介绍一些概念。整个篇幅最主要还是介绍Reflection APIs,也就是让读者知道如何探索class的结构、如何对某个“运行时才获知名称的class”生成一份实体、为其fields设值、调用其methods。本文将谈到java.lang.Class,以及java.lang.reflect中的Method、Field、Constructor等等classes。package cn.itcast.com;
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 ReflectText {
/**
* @param args
*/
public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
String str1 = "abc";
Class cls1 = str1.getClass();
Class cls2 = String.class;
Class cls3 = Class.forName("java.lang.String");
System.out.println(cls1==cls2);
System.out.println(cls1==cls2);
System.out.println(cls1.isPrimitive());//cls1是否是基本类型字节码false String非基本类型
System.out.println(int.class.isPrimitive());//true
System.out.println(int.class==Integer.class);//flse
System.out.println(int.class==Integer.TYPE);//true
System.out.println(int[].class.isPrimitive());//false
System.out.println(int[].class.isArray());//ture
/*得到某个类的所有构造方法
* Constructor[] constructors = Class.forName("类名").getConstructors();
*/
//编译器只看代码的定义
//得到String的构造方法夸号里的是该构造方法的参数,说明是返回这个构造方法字节码
Constructor constructor1 = String.class.getConstructor(StringBuffer.class);
String str5 = (String)constructor1.newInstance(new StringBuffer("abc"));
System.out.println(str5.charAt(2));
ReflectPoint pt1 = new ReflectPoint(3,5);
Field fieldY = pt1.getClass().getField("y");
//fieldY是对应是类上的变量而 不是不是对应某个指定对象上的变量!!!
System.out.println(fieldY.get(pt1));//取出pt1对应的fieldY值=5
//y是共有的,而x是私有的要改变访问方法
Field fieldX = pt1.getClass().getDeclaredField("x");
//能访问但不能读取值
fieldX.setAccessible(true);
System.out.println(fieldX.get(pt1));
changeStringValue(pt1);
System.out.println(pt1);
//Method类中的方法
//用字节码得到String中的charAt方法再去作用str1这个对象
//str1.charAt(1);
//String对象下的charAt方法charAt方法的参数是int
//methodCharAt是一个方法对象
Method methodCharAt = String.class.getMethod("charAt", int.class);
//用反射机制得到字节码中某个方法,再用这个方法去作用这个对象
//用methodCharAt方法对象去调用(invoke)这个方法(charAt)
//如果invoke第一个参数是null则他调用的是静态方法
System.out.println(methodCharAt.invoke(str1,2));
//在程序中直接用静态的方式调用main方法
TestArguements.main(new String[]{"111","222","333"});
//用反射机制来调用main
String startingClassName = args[0];
Class clazz = Class.forName(startingClassName);
Method mainMethod = clazz.getMethod("main", String[].class);
//Method mainMethod = Class.forName(startingClassName.getClass().getMethod("main",String[].class));
//mainMethod.invoke(null,new String[]{"111","222","333"});
//上面这种方法不行,虽然是一个字符串数组,但jdk1.5把他拆开看做3个,就有3各参数,与main的参数个数不一致
mainMethod.invoke(null,new Object[]{new String[]{"111","222","333"}});//封装成一个对象数组
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());//ture同一类型的字节码 int 且一维
//System.out.println(a1.getClass() == a4.getClass());//false
//System.out.println(a1.getClass() == a3.getClass());
System.out.println(a1.getClass().getName());//[I 说明是整型
System.out.println(a1.getClass().getSuperclass().getName());//java.lang.Object
System.out.println(a4.getClass().getSuperclass().getName());//java.lang.Object
/*Object可以引用任何的类,像int double char这类是基本类型,Object不能引用,
* 但是可以引用他们的封装类,Integer Double这种,
* 因此,Object数组能放除了8个基本类型之外的所有类
* */
Object Obj1 = a1;
Object Obj2 = a4;
//Object[] Obj3 = a1;//不对 a1是一维数组,里面每个元素师基本数据类型
//String对象类型,二维数据分为一维数组装了几个一维数组,其中一维数组是对象
Object[] Obj4 = a3;
Object[] Obj5 = a4;
System.out.println(a1);
System.out.println(a4);
//Arrays.asList(对象类型)
System.out.println(Arrays.asList(a1));//整数不打印出每个元素,把所有数据看做一个内容
System.out.println(Arrays.asList(a4));//打印出每个元素
printObject(a4);// a回车b回车c
printObject("xyz");//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 {
// TODO Auto-generated method stub
Field[] fields = obj.getClass().getFields();
for(Field field : fields){
//不能写field.getType().equals(String.class)
//虽然正确但字节码只有一份肯定比较的是地址,上面的有语义错误
if(field.getType() == String.class){
String oldValue = http://www.mamicode.com/(String)field.get(obj);
String newValue = http://www.mamicode.com/oldValue.replace(‘b‘, ‘a‘);
field.set(obj, newValue);
}
}
}
}
class TestArguements
{
public static void main(String[] args){
for(String arg : args){
System.out.println(arg);
}
}
}
package cn.itcast.day1;
import java.util.Date;
public class ReflectPoint {
private Date birthday = new Date();
private int x;
public int y;
public String str1 = "ball";
public String str2 = "basketball";
public String str3 = "itcast";
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
public String toString(){
return str1+":"+str2+":"+str3;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ReflectPoint other = (ReflectPoint) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
详情请查看:http://edu.csdn.net/heima
黑马程序员——反射
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。