<p>
<br />
</p>
<h2>
<span style="font-family:Tahoma,Microsoft Yahei,Simsun; font-size:32px; color:#444444"><span style="line-height:21px">定义与解释</span></span>
</h2>
<p>
<br />
</p>
<p>
<span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"> 反射就是把Java为中的各种成分映射成相应的Java类,例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类表表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类,表示Java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。<br />
一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象后,得到这些实例对象后有什么用呢?怎么用呢?这正是学习和应用反射的要点。<br />
<br />
<br />
</span>
</p>
<h2>
<span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:32px">Constructor类</span></span>
</h2>
<span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">------------------------------------------------------------------------------------------------------------------------------------------</span><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"></span></span></span></span><br />
一:Constructor类代表某个类中的一个构造方法<br />
二:得到某个类所有的构造方法:<br />
例子:Constructor[] constructors = Class.forName("java.lang.String").getConstructors();<br />
三:得到某一个构造方法:<br />
例子:Constructor constructor = Class.forName("java.lang.String").getConstructor<br />
<br />
<br />
(StringBuffer.class);<br />
获得方法时要用到类型<br />
四:创建实例对象:<br />
通常方式:String str = new String(new StringBuffer("abc");<br />
反射方式:String str = (String)constructor.newInstance(new StringBuffer("abc"));<br />
调用获得的方法时要用到上面相同类型的实例对象<br />
五:Class.newInstance()方法:<br />
例子:String obj = (String)Class.forName("java.lang.String").newInstance();<br />
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。<br />
该方法内部的具体代码是怎样写得呢?用到了缓存机制来保存默认构造方法的实例对象<br />
<br />
<br />
</span>
<h2>
<span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:32px">Field类</span></span>
</h2>
<span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">------------------------------------------------------------------------------------------------------------------------------------------</span><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"></span></span></span><br />
一:Field类代表某个类中的一个成员变量<br />
二:用Eclipse自动生成Java类的构造方法《Alt + Shift + s》(Generate Constructor using Fields...)<br />
问题:得到的Field对象是对应到类上面的成员变量,还是对应到对象上的成员变量?类只有一个,而该类的实例对象有多个,如果是与对象关联,那关联的是哪个对象呢?所以字段fieldX代表的是X的定义,而 不是具体的X变量。<br />
三:作业:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的b改成a<br />
</span>
<p>
</p>
<h2>
<span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:32px">示例</span></span>
</h2>
<p>
<span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">------------------------------------------------------------------------------------------------------------------------------------------</span><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"></span></span></span></span></span><br />
</span>
</p>
<p>
</p>
<pre name="code" class="java">import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/*
* Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,
* 所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。
*/
public class ReflectTest {
public static void main(String[] args) throws Exception{
String str1 = "abc";
Class cls1 = str1.getClass();//返回:表示此对象运行时类的 Class 对象。
Class cls2 = String.class;//cls2代表String的class 字节码
Class cls3 = Class.forName("java.lang.String");//返回与带有给定字符串名的类或接口相关联的 Class 对象。获取java.lang.String的class对象
System.out.println(cls1 == cls2);//比较cls1是否与cls2代表相同的类 true
System.out.println(cls1 == cls3);//比较cls1是否与cls2代表相同的类 true
System.out.println(cls1.isPrimitive());//false
System.out.println(int.class.isPrimitive());//判断是不是基本类型的 ture
System.out.println(int.class == Integer.class);//false
System.out.println(int.class == Integer.TYPE);//它(Integer)所包装的基本类型(int)的class true
System.out.println(int[].class.isPrimitive());//数组也是一种类型,但不是基本类型 false
System.out.println(int[].class.isArray());//判断类型是否为Array类型,true
/*****************************反射**************************************/
//new String(new StringBuffer("abc"));
//Constructor<String> constructor1 = Class.forName("java.lang.String").getConstructor(StringBuffer.class);//本代码与下行代码相同!
Constructor<String> constructor1 = String.class.getConstructor(StringBuffer.class);//得到参数为StringBuffered的String构造方法的Class构造函数
String str2 = constructor1.newInstance(new StringBuffer("abc"));//用这个构造器的时候还需要传进来 一个StringBuffer类型的参数
System.out.println(str2.charAt(2));
/****************************Field**********************************/
System.out.println("*********************************");
ReflectPoint pt1 = new ReflectPoint(3,5);
Field fieldY = pt1.getClass().getField("y");//要得到某个类身上的字段(成员变量),先得到类的字节码,字节码身上有成员变量的信息。getField(String name)得到某个字段(成员变量),用变量名字来区分到底是要得到哪一个成员变量
//fieldY只是代表类字节码身上的变量,没有对应到对象身上,
//如下:pt1.getClass()==pt2.getClass()==pt3.getClass()
//fieldY的值是多少?是5?错!fieldY不是对象身上的变量,而是类上,要用它去取某个对象上对应的值
System.out.println(fieldY.get(pt1));//结果为5
ReflectPoint pt2 = new ReflectPoint(3,8);
fieldY = pt2.getClass().getField("y");//pt2.getClass():得到类ReflectPoint的字节码,getField("y"):得到类ReflectPoint字节码身上的成员变量y的信息
System.out.println(fieldY.get(pt1));//结果为5
ReflectPoint pt3 = new ReflectPoint(3,20);
fieldY = pt3.getClass().getField("y");//pt3.getClass():得到类ReflectPoint的字节码,getField("y"):得到类ReflectPoint字节码身上的成员变量y的信息
System.out.println(fieldY.get(pt1));//结果为5
System.out.println("*********************************");
Field fieldX = pt1.getClass().getDeclaredField("x");//因为变量x是私有的,外界不可见,所以用getDeclaredField来使其可见
fieldX.setAccessible(true);//暴力反射 x是私有的,外界不可用,所以用setAccessible(true)来使其可得到
System.out.println(fieldX.get(pt1));
/*****************************作业示例**********************************/
changeStringValue(pt1);
System.out.println(pt1);
}
private static void changeStringValue(Object obj) throws IllegalArgumentException, IllegalAccessException {
Field[] fields = obj.getClass().getFields();
for(Field field:fields){
//if(field.getType().equals(String.class)){
if(field.getType() == String.class){//都 是一份,所以用双等号比较好!
String oldValue = (String)field.get(obj);
String newValue = oldValue.replace('b', 'a');
field.set(obj, newValue);
}
}
}
}
class ReflectPoint {
private int x;
public int y;
public String str1 ="ball";
public String str2 = "basketball";
public String str3 = "itcasdt";
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
/*
* 返回一个描述此 Field 的字符串。格式是:该字段(如果存在的话)的访问修饰符,
* 后面跟着字段类型和一个空格,再后面是声明该字段的类的完全限定名,
* 后面跟着一个句点,最后是字段的名称。例如:
public static final int java.lang.Thread.MIN_PRIORITY
private int java.io.FileDescriptor.fd
(non-Javadoc)
* @see java.lang.Object#toString()
*
* 返回:该对象的字符串表示形式
*/
@Override
public String toString() {
//return super.toString();
return str1 + "::" + str2 + "::" +str3;
}
}</pre>
<br />
<br />
<p>
</p>
<br />
</p>
<h2>
<span style="font-family:Tahoma,Microsoft Yahei,Simsun; font-size:32px; color:#444444"><span style="line-height:21px">定义与解释</span></span>
</h2>
<p>
<br />
</p>
<p>
<span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"> 反射就是把Java为中的各种成分映射成相应的Java类,例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类表表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类,表示Java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。<br />
一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象后,得到这些实例对象后有什么用呢?怎么用呢?这正是学习和应用反射的要点。<br />
<br />
<br />
</span>
</p>
<h2>
<span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:32px">Constructor类</span></span>
</h2>
<span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">------------------------------------------------------------------------------------------------------------------------------------------</span><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"></span></span></span></span><br />
一:Constructor类代表某个类中的一个构造方法<br />
二:得到某个类所有的构造方法:<br />
例子:Constructor[] constructors = Class.forName("java.lang.String").getConstructors();<br />
三:得到某一个构造方法:<br />
例子:Constructor constructor = Class.forName("java.lang.String").getConstructor<br />
<br />
<br />
(StringBuffer.class);<br />
获得方法时要用到类型<br />
四:创建实例对象:<br />
通常方式:String str = new String(new StringBuffer("abc");<br />
反射方式:String str = (String)constructor.newInstance(new StringBuffer("abc"));<br />
调用获得的方法时要用到上面相同类型的实例对象<br />
五:Class.newInstance()方法:<br />
例子:String obj = (String)Class.forName("java.lang.String").newInstance();<br />
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。<br />
该方法内部的具体代码是怎样写得呢?用到了缓存机制来保存默认构造方法的实例对象<br />
<br />
<br />
</span>
<h2>
<span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:32px">Field类</span></span>
</h2>
<span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">------------------------------------------------------------------------------------------------------------------------------------------</span><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"></span></span></span><br />
一:Field类代表某个类中的一个成员变量<br />
二:用Eclipse自动生成Java类的构造方法《Alt + Shift + s》(Generate Constructor using Fields...)<br />
问题:得到的Field对象是对应到类上面的成员变量,还是对应到对象上的成员变量?类只有一个,而该类的实例对象有多个,如果是与对象关联,那关联的是哪个对象呢?所以字段fieldX代表的是X的定义,而 不是具体的X变量。<br />
三:作业:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的b改成a<br />
</span>
<p>
</p>
<h2>
<span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; line-height:21px"><span style="font-size:32px">示例</span></span>
</h2>
<p>
<span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">------------------------------------------------------------------------------------------------------------------------------------------</span><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"><span style="color:rgb(68,68,68); font-family:Tahoma,'Microsoft Yahei',Simsun; font-size:14px; line-height:21px"></span></span></span></span></span><br />
</span>
</p>
<p>
</p>
<pre name="code" class="java">import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/*
* Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,
* 所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。
*/
public class ReflectTest {
public static void main(String[] args) throws Exception{
String str1 = "abc";
Class cls1 = str1.getClass();//返回:表示此对象运行时类的 Class 对象。
Class cls2 = String.class;//cls2代表String的class 字节码
Class cls3 = Class.forName("java.lang.String");//返回与带有给定字符串名的类或接口相关联的 Class 对象。获取java.lang.String的class对象
System.out.println(cls1 == cls2);//比较cls1是否与cls2代表相同的类 true
System.out.println(cls1 == cls3);//比较cls1是否与cls2代表相同的类 true
System.out.println(cls1.isPrimitive());//false
System.out.println(int.class.isPrimitive());//判断是不是基本类型的 ture
System.out.println(int.class == Integer.class);//false
System.out.println(int.class == Integer.TYPE);//它(Integer)所包装的基本类型(int)的class true
System.out.println(int[].class.isPrimitive());//数组也是一种类型,但不是基本类型 false
System.out.println(int[].class.isArray());//判断类型是否为Array类型,true
/*****************************反射**************************************/
//new String(new StringBuffer("abc"));
//Constructor<String> constructor1 = Class.forName("java.lang.String").getConstructor(StringBuffer.class);//本代码与下行代码相同!
Constructor<String> constructor1 = String.class.getConstructor(StringBuffer.class);//得到参数为StringBuffered的String构造方法的Class构造函数
String str2 = constructor1.newInstance(new StringBuffer("abc"));//用这个构造器的时候还需要传进来 一个StringBuffer类型的参数
System.out.println(str2.charAt(2));
/****************************Field**********************************/
System.out.println("*********************************");
ReflectPoint pt1 = new ReflectPoint(3,5);
Field fieldY = pt1.getClass().getField("y");//要得到某个类身上的字段(成员变量),先得到类的字节码,字节码身上有成员变量的信息。getField(String name)得到某个字段(成员变量),用变量名字来区分到底是要得到哪一个成员变量
//fieldY只是代表类字节码身上的变量,没有对应到对象身上,
//如下:pt1.getClass()==pt2.getClass()==pt3.getClass()
//fieldY的值是多少?是5?错!fieldY不是对象身上的变量,而是类上,要用它去取某个对象上对应的值
System.out.println(fieldY.get(pt1));//结果为5
ReflectPoint pt2 = new ReflectPoint(3,8);
fieldY = pt2.getClass().getField("y");//pt2.getClass():得到类ReflectPoint的字节码,getField("y"):得到类ReflectPoint字节码身上的成员变量y的信息
System.out.println(fieldY.get(pt1));//结果为5
ReflectPoint pt3 = new ReflectPoint(3,20);
fieldY = pt3.getClass().getField("y");//pt3.getClass():得到类ReflectPoint的字节码,getField("y"):得到类ReflectPoint字节码身上的成员变量y的信息
System.out.println(fieldY.get(pt1));//结果为5
System.out.println("*********************************");
Field fieldX = pt1.getClass().getDeclaredField("x");//因为变量x是私有的,外界不可见,所以用getDeclaredField来使其可见
fieldX.setAccessible(true);//暴力反射 x是私有的,外界不可用,所以用setAccessible(true)来使其可得到
System.out.println(fieldX.get(pt1));
/*****************************作业示例**********************************/
changeStringValue(pt1);
System.out.println(pt1);
}
private static void changeStringValue(Object obj) throws IllegalArgumentException, IllegalAccessException {
Field[] fields = obj.getClass().getFields();
for(Field field:fields){
//if(field.getType().equals(String.class)){
if(field.getType() == String.class){//都 是一份,所以用双等号比较好!
String oldValue = (String)field.get(obj);
String newValue = oldValue.replace('b', 'a');
field.set(obj, newValue);
}
}
}
}
class ReflectPoint {
private int x;
public int y;
public String str1 ="ball";
public String str2 = "basketball";
public String str3 = "itcasdt";
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
/*
* 返回一个描述此 Field 的字符串。格式是:该字段(如果存在的话)的访问修饰符,
* 后面跟着字段类型和一个空格,再后面是声明该字段的类的完全限定名,
* 后面跟着一个句点,最后是字段的名称。例如:
public static final int java.lang.Thread.MIN_PRIORITY
private int java.io.FileDescriptor.fd
(non-Javadoc)
* @see java.lang.Object#toString()
*
* 返回:该对象的字符串表示形式
*/
@Override
public String toString() {
//return super.toString();
return str1 + "::" + str2 + "::" +str3;
}
}</pre>
<br />
<br />
<p>
</p>