黑马程序员——Reflectfab反射的原理透析通俗易懂

------- android培训、 java培训、java学习型技术博客、期待与您交流! ----------




/*反射:就是将java类中的所有成员反射成为相对应的java类。

1.java中所有包中的类这一类事物,它们都有一个特性,就是它们都属于类,所以就将他们封装成:类Class

java中每一个类都是Class的对象。

2,.所有的类中都有共同的特性,就是都有成员变量,构造函数,和方法。

然后在将成员变量这一类事物封装成为对象:field类,

将构造函数封装成对象:Constructor类,

将方法这一类事物在封装成对象就是:Method类。

3.怎么将某一个类变成Class对象?

有三种方式,分别相对应cls1,cls2,cls3:

String str1="abc";
//获取这个类型属于的字节码。即其属于哪个class文件。即:将一个类变成Class对象。
//而class文件中都是将代码编译成为了的字节码,二进制数据
Class cls1=str1.getClass();
Class cls2=String.class;
Class cls3=Class.forName("java.lang.String");
System.out.println(cls1==cls2);//true
System.out.println(cls2==cls3);//true

4.有9种预定义的Class对象,表示八个基本类型和 void:

即:基本的 Java 类型(booleanbytecharshortintlongfloatdouble)和关键字void 也表示为 Class 对象。


5.下面通过代码来验证和阐述反射的一些方法和用法:

第一个:

public class ReflectTest 
{
public static void main(String[]args) throws Exception
{
String str1="abc";
//获取这个类型属于的字节码。即其属于哪个class文件。
//而class文件中都是将代码编译成为了的字节码,二进制数据
Class cls1=str1.getClass();
Class cls2=String.class;
Class cls3=Class.forName("java.lang.String");
System.out.println(cls1==cls2);//true
System.out.println(cls2==cls3);//true

//isPrimitive()判断指定的Class对象是否表示一个基本类型
//有九种预定义的 Class 对象,表示八个基本类型和 void
System.out.println(cls1.isPrimitive());
//false.对象不是基本数据类型。

System.out.println(int.class.isPrimitive());
//true.int是基本类型。

System.out.println(int.class==Integer.class);
//false.int是基本类型,Tnteger是类类型。

System.out.println(int.class==Integer.TYPE);
//Integer.TYPE:表示基本类型 int 的 Class 实例。
//表示一个Integer实例的int类型。

System.out.println(int[].class.isPrimitive());
//false.数组类型不是基本类型。

System.out.println(int[].class.isArray());
//isArray():判断一个类型是否是数组类型
//true.

*/

第二个复杂 的:

public class ReflectPoint {
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 String toString() {
// TODO 自动生成的方法存根
return str1+":"+str2+":"+str3;
}


}

public class ReflectTest 
{
public static void main(String[]args) throws Exception
{

}

/*

//new String(new StringBuffer("abc"));
/
/通过反射来完成创建一个向上面的字符串:

Constructor c1
=String.class.getConstructor(StringBuffer.class);

String str2
=(String)c1.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));//5.
 
//获取x会报错,失败,因为变量x是私有的,而getField()只能获取共有的成员变量。
//Field fieldX=pt1.getClass().getField("x");
//System.out.println(fieldX.get(pt1));
Field fieldX=pt1.getClass().getDeclaredField("x");//获取类中私有的成员变量字节码
fieldX.setAccessible(true);//暴力反射,将这个私有的字节码设置为可进入的。
System.out.println(fieldX.get(pt1));
 
changeStringValue(pt1);
System.out.println(pt1);
 
//str1.charAt(1);
Method methodCharAt=String.class.getMethod("charAt",int.class);
System.out.println(methodCharAt.invoke(str1,1));
//invoke:这个方法的对象,调用他自己的方法作用于某个对象上。
 
//System.out.println(methodCharAt.invoke(null,1));
//如果第一个参数数null,也就是说,方法对象的调用它自己的方法,不需要作用于某个对象,就可以调用,
//说明这个方法,在它所在的类中是static静态的。
 
System.out.println(methodCharAt.invoke(str1),new Object[]{2});
//这是针对JDK1.4版本没有可变参数的情况下,你要传入多个参数时。因为我不知道你要传入什么
//样的参数,所以用Object数组,什么都可以传。上面表示的就是数组中有一个Integer类型的参数2
//它对应的值是2.对2有个自动装箱的过程。
 
 
 
 
}
private static void changeStringValue(Object obj)throws Exception
{
Field[] fields=obj.getClass().getFields();
for(Field field:fields)
{
//if(field.getType().equals(String.class))
//对于字节码的比较用==,用equals也能比,但不科学。因为字节码只有一份,就相当于说,看他指向的是整形
//类字节码,还是字符串型的字节码
if(field.getType()==String.class)
{
String oldValue=(String)field.get(obj);
String newValue=oldValue.replace('b', 'a');
field.set(obj,newValue);
}
}
}
}

}


------- android培训、java培训、java学习型技术博客、期待与您交流! ----------









你可能感兴趣的:(黑马程序员——Reflectfab反射的原理透析通俗易懂)