反射Reflect

<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">&nbsp; &nbsp;反射就是把Java为中的各种成分映射成相应的Java类,例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类表表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类,表示Java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。<br />
&nbsp; 一个类中的每个成员都可以用相应的反射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 />
&nbsp; &nbsp;例子:Constructor[] &nbsp;constructors = Class.forName(&quot;java.lang.String&quot;).getConstructors();<br />
三:得到某一个构造方法:<br />
&nbsp; &nbsp;例子:Constructor constructor = Class.forName(&quot;java.lang.String&quot;).getConstructor<br />
<br />
<br />
(StringBuffer.class);<br />
&nbsp; &nbsp;获得方法时要用到类型<br />
四:创建实例对象:<br />
&nbsp; &nbsp;通常方式:String str = new String(new StringBuffer(&quot;abc&quot;);<br />
&nbsp; &nbsp;反射方式:String str = (String)constructor.newInstance(new StringBuffer(&quot;abc&quot;));<br />
&nbsp; &nbsp;调用获得的方法时要用到上面相同类型的实例对象<br />
五:Class.newInstance()方法:<br />
&nbsp; &nbsp;例子:String obj = (String)Class.forName(&quot;java.lang.String&quot;).newInstance();<br />
&nbsp; &nbsp;该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。<br />
&nbsp; &nbsp;该方法内部的具体代码是怎样写得呢?用到了缓存机制来保存默认构造方法的实例对象<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 &nbsp;Fields...)<br />
&nbsp; &nbsp; 问题:得到的Field对象是对应到类上面的成员变量,还是对应到对象上的成员变量?类只有一个,而该类的实例对象有多个,如果是与对象关联,那关联的是哪个对象呢?所以字段fieldX代表的是X的定义,而&nbsp; 不是具体的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 = &quot;abc&quot;;
Class cls1 = str1.getClass();//返回:表示此对象运行时类的 Class 对象。


Class cls2 = String.class;//cls2代表String的class 字节码
Class cls3 = Class.forName(&quot;java.lang.String&quot;);//返回与带有给定字符串名的类或接口相关联的 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(&quot;abc&quot;));
//Constructor&lt;String&gt;  constructor1 = Class.forName(&quot;java.lang.String&quot;).getConstructor(StringBuffer.class);//本代码与下行代码相同!
Constructor&lt;String&gt;  constructor1 = String.class.getConstructor(StringBuffer.class);//得到参数为StringBuffered的String构造方法的Class构造函数
String str2 = constructor1.newInstance(new StringBuffer(&quot;abc&quot;));//用这个构造器的时候还需要传进来 一个StringBuffer类型的参数
System.out.println(str2.charAt(2));


/****************************Field**********************************/
System.out.println(&quot;*********************************&quot;);
ReflectPoint pt1 = new ReflectPoint(3,5);
Field fieldY = pt1.getClass().getField(&quot;y&quot;);//要得到某个类身上的字段(成员变量),先得到类的字节码,字节码身上有成员变量的信息。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(&quot;y&quot;);//pt2.getClass():得到类ReflectPoint的字节码,getField(&quot;y&quot;):得到类ReflectPoint字节码身上的成员变量y的信息
System.out.println(fieldY.get(pt1));//结果为5


ReflectPoint pt3 = new ReflectPoint(3,20);
   fieldY = pt3.getClass().getField(&quot;y&quot;);//pt3.getClass():得到类ReflectPoint的字节码,getField(&quot;y&quot;):得到类ReflectPoint字节码身上的成员变量y的信息
System.out.println(fieldY.get(pt1));//结果为5
System.out.println(&quot;*********************************&quot;);


Field fieldX = pt1.getClass().getDeclaredField(&quot;x&quot;);//因为变量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 =&quot;ball&quot;;
public String str2 = &quot;basketball&quot;;
public String str3 = &quot;itcasdt&quot;;


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 + &quot;::&quot; + str2 + &quot;::&quot; +str3;
}




}</pre>
<br />
<br />


<p>
</p>
### Java 反射 Reflect 使用教程 #### 获取 `Class` 对象 在Java中,反射的核心是`Class`对象。可以通过三种方式获得: - **通过类名**:使用`.class`语法。 ```java Class<?> clazz = String.class; ``` - **通过实例**:调用对象的`.getClass()`方法。 ```java Object obj = new Integer(0); Class<?> clazz = obj.getClass(); ``` - **通过全限定名**:利用`Class.forName(String className)`静态方法。 ```java try { Class<?> clazz = Class.forName("java.lang.String"); } catch (ClassNotFoundException e) { // Handle exception } ``` 上述每种方法都可用于获取指定类型的`Class`对象[^1]。 #### 访问字段 (`Field`) 一旦有了`Class`对象,就可以访问其声明的成员变量(即字段)。这包括私有字段在内的所有字段。 ```java // 假设有一个Person类 public class Person { private String name; public void setName(String n){ this.name=n; } @Override public String toString(){ return "Name:"+this.name; } } try { Class<Person> personClass = Person.class; // 获取名为"name"的私有字段 Field field = personClass.getDeclaredField("name"); // 设置可访问标志位为true以便能够读写该字段 field.setAccessible(true); Person p = new Person(); // 向p设置值 field.set(p,"John Doe"); System.out.println(p.toString()); // 输出 Name:John Doe } catch (NoSuchFieldException | IllegalAccessException e) { // 处理异常... } ``` 这段代码展示了如何创建一个新的人(`Person`)对象并为其内部不可见的名字(`name`)属性赋值。 #### 调用方法 (`Method`) 除了可以操作字段外,还可以通过反射来执行某个特定的方法。 ```java try { Class<Person> personClass = Person.class; Method method = personClass.getMethod("setName",String.class); Person p = new Person(); // 执行setName()方法并将参数传递给它 method.invoke(p, "Jane Doe"); System.out.println(p.toString()); } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { // 处理异常... } ``` 这里说明了怎样找到公共方法`setName`并通过传入的对象实例去调用这个方法。 #### 构造器 (`Constructor`) 最后,也可以借助于反射机制来进行对象的构建工作。 ```java try { Class<Person> personClass = Person.class; Constructor<Person> constructor = personClass.getConstructor(); Person p = constructor.newInstance(); System.out.println(p.toString()); } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { // 处理异常... } ``` 此片段显示了一个无参构造函数是如何被用来生成新的`Person`实体的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值