反射的概念:
反射就是把java类中的各种成份映射成相应的java类。例如,一个java类中的用一个Class类的对象来表示,一个类中的组成部分,成员变量、方法、构造函数、包等等信息也用一个个java类来表示。表示java类的Class类显然要提供一系列的方法,来获得其中的变量、方法、构造函数、修饰 符、包等信息,这些类就是用相应的类的实例对象来表示,他们是Filed、Method、Constructor、Package等。
一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象
反射的用途:
反射的主要作用是:用来扩展系统和动态调用程序集。
扩展系统:就是先把系统写好,系统里面定义接口,后面开发的人去写接口的代码。
此时该系统就要用反射了,系统用反射调用接口,当接口没写,系统利用反射就不会不会出错,此时就等于没实现此功能而已,当接口被人写好了,系统就会自动调用接口的功能展现在系统上。即反射实现即插即用功能。
动态调用程序集就是利用反射去调用编译好的程序,反射具有一定灵活性,不需改变你所建的工程。
反射最主要的用户适用于做框架的
反射的基石-Class类:
如何得到各个字节码对应的实例对象
类名:class,例如System.class
对象.getClass(),例如,new Date().getClass();
Class.forName(“类名”),例如Class.forName(“java.util.Date”);
publicclassReflectDemo1 {
publicstaticvoid main(String[] args) throwsException {
Stringstr1 = "abc";
//得到字节码的三种方式
Classcls1 =str1.getClass();
Classcls2 = String.class;
Classcls3 = Class.forName("java.lang.String");
System.out.println(cls1 == cls2);//true
System.out.println(cls1 == cls3);//true
//打印出是否是基本類型
System.out.println(cls1.isPrimitive());//false
System.out.println(int.class.isPrimitive());//true
System.out.println(int.class == Integer.class);//false
System.out.println(int.class == Integer.TYPE);//true
System.out.println(int[].class.isPrimitive());//false
System.out.println(int[].class.isArray());//true
}
}
总之,只要在源程序中出现的类型,都有各自的Class实例对象,例如int[],void
得到字节码的三种方式:
publicclassReflectDemo1 {
publicstaticvoidmain(String[] args) throws Exception {
Stringstr1 = "abc";
//得到字节码的三种方式
Classcls1 =str1.getClass();
Classcls2 = String.class;
Classcls3 = Class.forName("java.lang.String");
System.out.println(cls1 == cls2);//true
System.out.println(cls1 == cls3);//true
//打印出是否是基本類型
System.out.println(cls1.isPrimitive());//false
System.out.println(int.class.isPrimitive());//true
System.out.println(int.class == Integer.class);//false
System.out.println(int.class == Integer.TYPE);//true
System.out.println(int[].class.isPrimitive());//false
System.out.println(int[].class.isArray());//true
}
成员构造函数的反射:
使用到的ReflectPoint类
publicclassReflectPoint {
privateintx;
publicinty;
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
}
publicclassReflectDemo2 {
publicstaticvoidmain(String[] args) throws Exception {
//new String(new StringBuilder("abc"));
//得到类型
Constructorconstructor1= String.class.getConstructor(StringBuilder.class);
//得到方法的对象
Stringstr2 = (String) constructor1.newInstance(new StringBuilder("c"));
System.out.println(str2);
}
}
字段的反射:
使用到的ReflectPoint类
publicclassReflectPoint {
privateintx;
publicinty;
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
}
publicclassReflectDemo2 {
publicstaticvoidmain(String[] args) throws Exception {
ReflectPoint rp = newReflectPoint(3,5);
FieldfieldY = rp.getClass().getField("y");
System.out.println(fieldY.get(rp));
Fieldfieldx = rp.getClass().getDeclaredField("x");
fieldx.setAccessible(true);
System.out.println(fieldx.get(rp));
}
}
反射成员变量的综合案例:
publicclassReflectPoint {
privateintx;
publicinty;
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可以判断重载的方法是否写正确
@Override
public String toString(){
return"ReflectPoint [x="+ x + ", y=" + y + ", str1="+ str1
+", str2="+ str2+ ", str3="+ str3+ "]";
}
}
publicclassReflectDemo2 {
publicstaticvoidmain(String[] args) throws Exception {
//操作field字段
changeStringValue(rp);
System.out.println(rp);
}
privatestaticvoidchangeStringValue(Object obj) throwsException {
Field[]fields = obj.getClass().getFields();
for(Field field : fields) {
//比较同一份字节码使用==而不是使用equals
if(field.getType() ==String.class){
Stringvalue = (String) field.get(obj);
StringnewValue = value.replace('b', 'a');
field.set(obj,newValue);
}
}
}
}
反射得到类的方法:
methodCharAt.invoke(null, 1)当第一个参数为null时,意味着调用的是静态的方法
//jdk1.4的语法来调用
System.out.println(methodCharAt.invoke(str1,newObject[] {2}));
//jdk1.5的语法来调用
System.out.println(methodCharAt.invoke(str1, 1));
publicclassReflectDemo1 {
publicstaticvoidmain(String[] args) throws Exception {
Stringstr1 = "abc";
//得到类的方法,String.charAt方法
MethodmethodCharAt = String.class.getMethod("charAt", int.class);
//methodCharAt.invoke(null,1)当第一个参数为null时,意味着调用的是静态的方法
System.out.println(methodCharAt.invoke(str1,1));//jdk1.5的语法来调用
System.out.println(methodCharAt.invoke(str1,newObject[] {2}));//jdk1.4的语法来调用
}
}
反射执行某个类中的main方法:
对接收数组参数的成员方法进行反射
方法一: mainMethod.invoke(null, new Object[]{new String[] {"111","222","333"}});
方法二: mainMethod.invoke(null, (Object)newString[]{"111","222","333"});
publicclassReflectDemo1 {
publicstaticvoidmain(String[] args) throws Exception {
//反射执行某个类中的main方法
StringstartingClassName = args[0];
MethodmainMethod =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"});
}
}
classTestArguments {
publicstaticvoidmain(String[] args) {
for(String s : args) {
System.out.println(s);
}
}
}
注意在运行的时候要传递TestArguments类的包给ReflectDemo1
数组的反射:
publicclassReflectDemo1 {
publicstaticvoidmain(String[] args) throws Exception {
int[]a1 =newint[3];
int[] a2 = newint[4];
int[][] a3 = newint[2][3];
String[] a4 = new String[] {"abc","bcd","cde"};
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));
}
}
数组的反射应用:
publicclassReflectDemo1 {
publicstaticvoidmain(String[] args) throws Exception {
String[] a4 = newString[]{"abc","bcd","cde"};
printObject(a4);
printObject("xyz");
}
privatestaticvoidprintObject(Object obj) {
Classclazz = 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);
}
}
}
反射的综合案例:
ArrayList_HashSet的比较以及HashCode的分析
ArrayList是线性的存放,有多少放多少,按照先后的顺序
HashSet是存放不重复的,存放之前先判断集合中是否存在,不存在才放入
HashCode是一种编码方式,在Java中,每个对象都会有一个hashcode,Java可以通过这个hashcode来识别一个对象
publicclassReflectDemo2 {
publicstaticvoidmain(String[] args) {
Collectioncollection= newHashSet();
ReflectPointpt1 = newReflectPoint(3, 3);
ReflectPointpt2 = newReflectPoint(5, 5);
ReflectPointpt3 = newReflectPoint(3, 3);
collection.add(pt1);
collection.add(pt2);
collection.add(pt3);
collection.add(pt1);
/*
*此处并不能移走pt1,因为将数据加入hashset中以后不能再去更改他,
这样会导致内存泄露
内存泄露的作用,此处是一个例子,java中有内存泄露吗?为什么?
pt1.y= 7;
collection.remove(pt1);
*/
System.out.println(collection.size());
}
}
packagecom.wj.reflect;
publicclassReflectPoint {
privateintx;
publicinty;
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
@Override
publicint hashCode() {
finalint prime = 31;
int result = 1;
result= prime * result + x;
result= prime * result + y;
return result;
}
@Override
publicbooleanequals(Object obj) {
if (this == obj)
returntrue;
if (obj == null)
returnfalse;
if (getClass() !=obj.getClass())
returnfalse;
ReflectPointother = (ReflectPoint) obj;
if (x != other.x)
returnfalse;
if (y != other.y)
returnfalse;
returntrue;
}
@Override
public String toString(){
return"ReflectPoint [x="+ x + ", y=" + y + ", str1="+ str1
+", str2="+ str2+ ", str3="+ str3+ "]";
}
}
用类加载器管理资源和配置文件,也会使用到反射。详见另一篇博客