黑马程序员 java高级技术1.5之反射(张孝祥)
2014-01-09 13:06
489 查看
反射
1.Java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则是由这个类的实例对象来确定的,不同的实例对象有不同的属性值。Java程序中的各个Java类,它们是否属于同一类事物,是不是可以用一个类来描述这类事物呢?这个类的名字就是Class,要注意与小写class关键字的区别哦。Class类描述了哪些方面的信息呢?类的名字,类的访问属性,类所属于的包名,字段名称的列表、方法名称的列表,等等。学习反射,首先就要明白Class这个类。写如下代码进行对比理解:
/*Person p1 = new Person("zhangsan");
Person p2 = new Person("lisi");
*/
/*Class x1 = Vector类在内存里的字节码
Class x2= Date类在内存里的字节码*/
Class x1 = Vector.class;
Class x2 = Date.class;
每个java类都是Class的一个实例对象,它们的内容不同,但是,它们的特征相同,譬如,都有方法,有字段,有父类,有包。
2.******讲课时要一定画一张图:多个类的字节码装载入内存,在内存中加入一个个方块空间表示字节码,然后用一个个椭圆表示以这个字节码创建出来的实例对象,并用监视代码来说明字节码只被装载一次,而它构造的实例对象的构造方法被调用了多次。用如下代码更进一步说明Class的实例是什么?是一份字节码,一个类在虚拟机中通常只有一份字节码:
Date d1 = new Date();
Class clazz1 = d1.getClass();
Class clazz2 =
Date.class;
Class clazz3 = null;
clazz3 = Class.forName("java.util.Date");
if(clazz1==clazz2)
{
System.out.println(clazz1.getName());
}
if(clazz1==clazz3)
{
System.out.println(clazz1.getName());
}
3.一个奇怪的问题:加载了字节码,并调用了其getMethods之类的方法,但是没有看到类的静态代码块被执行,只有在第一个实例对象被创建时,这个静态代码才会被执行。准确的说,静态代码块不是在类加载时被调用的,而是第一个实例对象被创建时才执行的。
反射就是把Java类中的各种成分映射成相应的java类。例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。 一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象后,得到这些实例对象后有什么用呢?怎么用呢?这正是学习和应用反射的要点。
例子:
结果:
true
true
false
true
false
true
false
true
c
5
3
aall:aasketaall:itcast
b
c
1.Java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则是由这个类的实例对象来确定的,不同的实例对象有不同的属性值。Java程序中的各个Java类,它们是否属于同一类事物,是不是可以用一个类来描述这类事物呢?这个类的名字就是Class,要注意与小写class关键字的区别哦。Class类描述了哪些方面的信息呢?类的名字,类的访问属性,类所属于的包名,字段名称的列表、方法名称的列表,等等。学习反射,首先就要明白Class这个类。写如下代码进行对比理解:
/*Person p1 = new Person("zhangsan");
Person p2 = new Person("lisi");
*/
/*Class x1 = Vector类在内存里的字节码
Class x2= Date类在内存里的字节码*/
Class x1 = Vector.class;
Class x2 = Date.class;
每个java类都是Class的一个实例对象,它们的内容不同,但是,它们的特征相同,譬如,都有方法,有字段,有父类,有包。
2.******讲课时要一定画一张图:多个类的字节码装载入内存,在内存中加入一个个方块空间表示字节码,然后用一个个椭圆表示以这个字节码创建出来的实例对象,并用监视代码来说明字节码只被装载一次,而它构造的实例对象的构造方法被调用了多次。用如下代码更进一步说明Class的实例是什么?是一份字节码,一个类在虚拟机中通常只有一份字节码:
Date d1 = new Date();
Class clazz1 = d1.getClass();
Class clazz2 =
Date.class;
Class clazz3 = null;
clazz3 = Class.forName("java.util.Date");
if(clazz1==clazz2)
{
System.out.println(clazz1.getName());
}
if(clazz1==clazz3)
{
System.out.println(clazz1.getName());
}
3.一个奇怪的问题:加载了字节码,并调用了其getMethods之类的方法,但是没有看到类的静态代码块被执行,只有在第一个实例对象被创建时,这个静态代码才会被执行。准确的说,静态代码块不是在类加载时被调用的,而是第一个实例对象被创建时才执行的。
反射就是把Java类中的各种成分映射成相应的java类。例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。 一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象后,得到这些实例对象后有什么用呢?怎么用呢?这正是学习和应用反射的要点。
例子:
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 ReflectPoint(int x, int y) { super(); this.x = x; this.y = y; } @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; final ReflectPoint other = (ReflectPoint) obj; if (x != other.x) return false; if (y != other.y) return false; return true; } @Override public String toString(){ return str1 + ":" + str2 + ":" + str3; } 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 Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } }
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 { /** * @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 == cls3); System.out.println(cls1.isPrimitive()); System.out.println(int.class.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()); //new String(new StringBuffer("abc")); Constructor constructor1 = String.class.getConstructor(StringBuffer.class); String str2 = (String)constructor1.newInstance(/*"abc"*/new StringBuffer("abc")); System.out.println(str2.charAt(2)); ReflectPoint pt1 = new ReflectPoint(3,5); Field fieldY = pt1.getClass().getField("y"); //fieldY的值是多少?是5,错!fieldY不是对象身上的变量,而是类上,要用它去取某个对象上对应的值 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[]{2})); //TestArguments.main(new String[]{"111","222","333"}); //通过反射执行main方法 String startingClassName = args[0]; Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class); //mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}}); mainMethod.invoke(null, (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()); //System.out.println(a1.getClass() == a4.getClass()); //System.out.println(a1.getClass() == a3.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[] aObj3 = a1; Object[] aObj4 = a3; Object[] aObj5 = a4; System.out.println(a1); System.out.println(a4); System.out.println(Arrays.asList(a1)); System.out.println(Arrays.asList(a4)); printObject(a4); printObject("xyz"); } //传递一个对象进来,如果是数组,就通过反射提供的操作的数组类Array,取出来并打印。如果不是数组,直接打印 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); } } //作业:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的"b"改成"a"。 private static void changeStringValue(Object obj) throws Exception { Field[] fields = obj.getClass().getFields(); for(Field field : fields){ //if(field.getType().equals(String.class)){ if(field.getType() == String.class){//比较的是地址,比equals好 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); } } }
结果:
true
true
false
true
false
true
false
true
c
5
3
aall:aasketaall:itcast
b
c
相关文章推荐
- 黑马程序员 java高级技术1.5之内省和BeanUtils(1.7)(张孝祥)
- 黑马程序员 java高级技术1.5之枚举(张孝祥)
- 黑马程序员 java高级技术1.5之自动装箱和拆箱(张孝祥)
- 黑马程序员---java高新技术----反射技术
- 黑马程序员——java中的反射技术再探
- 黑马程序员——JAVA基础之JDK1.5新特性高级for循环和可变参数
- 黑马程序员-Java高级:反射
- 黑马程序员_java高级篇反射Day11
- 黑马程序员——Java新技术反射技术1
- 黑马程序员_高薪技术一(java反射)
- 黑马程序员_Java反射技术学习总结
- 黑马程序员——Java新技术反射技术2
- java高级技术学习_反射
- 黑马程序员_Java高薪技术之构造方法的反射应用
- 黑马程序员_Java反射技术
- 黑马程序员——Java中的反射技术
- 黑马程序员------张孝祥Java高新技术-反射
- 黑马程序员——java学习16(张孝祥)——反射
- 黑马程序员--Java反射技术
- 黑马程序员-----java基础二十(java之反射技术)