漫谈反射

反射

理解反射的概念

反射就是把Java类中的各种成分映射相成Java类。

比如:众多的人用一个Person类来表示,那么众多的Java类就用一个Class类来表示。

反射也称为对类的解剖。把类的各个组成部分映射成一个个对应的Java类。

比如:一个类有:成员变量,方法,构造方法,包等等信息。

利用反射技术能够对一个类进行解剖。

事实上仅仅要拿到Java类的字节码相应的Class对象,就等于拿到了Java类中的各个成分。

反射的基石就是Class。

Class类

Class类用于表示.class文件,是全部载入进内存的字节码对象的父类。所以能够通过Class得到执行时的类。

怎样得到某个class文件相应的class对象呢?

方法有3种:

1)类名.class 比如,Person.class。

2)对象.getClass() 比如。new Data().getClass()。

3)Class.forName("包名.类名");
比如,Class.forName("java.lang.String");

代码演示样例:

public class ClassTest{

public static void main(String...args)throws Exception{

String str = "abc";

Class cls1 =String.class;

Class cls2 = str.getClass();

Class cls3 = Class.forName("java.lang.String");

System.out.println(cls1 == cls2);//true

System.out.println(cls2 == cls3);//true

}

}

注意:字节码文件是唯一的,所以不管怎么获取。都是同一份字节码文件。

九个提前定义Class实例对象(八大原始类型+void)

Class 类的实例表示正在执行的 Java 应用程序中的类和接口。

枚举是一种类,凝视是一种接口。

每一个数组属于被映射为 Class 对象的一个类,全部具有同样元素类型和维数的数组都共享该Class 对象。

主要的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和keyword void也表示为 Class 对象。

注意:

1、int.class == Integer.TYPE。

2、数组类型的Class实例对象Class.isArray()为true。

3、反射并非Java 5.0的新特性。

Java 5.0 代码演示样例:

package com.itheima.day01;

public class ReflectTest {

public static void main(String[] args) {

System.out.println("推断int基本数据类型和Integer的基本数据类型"

+ "是不是同一个Class对象 结果为:"+(int.class == Integer.TYPE));

System.out.println("推断int.class是不是基本数据类型 结果为:"+int.class.isPrimitive());

System.out.println("推断是不是数组类型 结果为:"+int[].class.isArray());

}

}

总之,仅仅要是在源程序中出现的类型,都有各自的Class实例对象,比如。int.class,int[].class。

一个类中的每一个成员都能够用对应的反射API类的一个实例对象来表示。通过调用Class类的方法能够得到这些实例对象后。得到这些实例对象后有什么用呢?怎么用呢?这正是学习和应用反射的要点。

构造方法的反射应用(Coustructor类)

Constructor类的实例对象代表类的一个构造方法。

反射公共。私有和保护的构造方法:

反射公共的须要的方法是:getConstructor();

反射私有的须要的方法是:getDeclaredConstructor();

Constructor对象代表一个构造方法。Constructor对象有的方法:得到构造方法名字。得到所属于的类,产生实例对象。

得到某个类空參数构造方法。例:

Constructor constructor = Class.forName("java.lang.String").getConstructor();

得到某个类全部的构造方法,例:

Constructor [] constructors= Class.forName("java.lang.String").getConstructors();

得到某一个带參数的构造方法,例:

Constructor constructor =Class.forName("java.lang.String").getConstructor(StringBuffer.class);

注意:一个类有多个构造方法,用什么方式能够区分清楚想得到当中的哪个方法呢?依据參数的个数和类型,比如,Class.getMethod(name,Class... args)中的args參数就代表所要获取的那个方法的各个參数的类型的列表。重点:參数类型用什么方式表示?用Class实例对象。

利用构造方法创建实例对象:

通常方式:String instance = new String(new StringBuffer("黑马程序猿"));

反射方式:String instance = (String)constructor.newInstance("黑马程序猿");

//调用获得的方法时要用到上面同样类型的实例对象

通过Class类中的newInstance()方法也可创建类的实例,其内部工作原理是先得无參的构造方法,再用构造方法创建实例对象。

代码演示样例:

package com.itheima.day01;

import java.lang.reflect.Constructor;

public class ReflectTest {

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

Class clszz = Class.forName("java.lang.String");

Constructor constructor = clszz.getConstructor(StringBuffer.class);

String str = (String) constructor.newInstance(new StringBuffer("黑马程序猿"));

char [] chs = str.toCharArray();

for(int x = 0; x<chs.length;x++){

System.out.println(chs[x]);

}

}

}

成员变量的反射(Field类)

Field类代表反射某个类中的一个成员变量。

问题:得到的Field对象是相应到类上面的成员变量。还是相应到对象上的成员变量?类仅仅有一个。而该类的实例对象有多个,假设是与对象关联,那关联的是哪个对象呢?所以字段fieldAge 代表的是Age的定义,而不是详细的Age变量。

(注意訪问权限的问题)也就是说,定义的是类对象,而非对象的对象。

当我们须要对其操作的时候。须要确定是那个详细的对象。

代码演示样例:

package com.itheima.study;

public class Person {

public int age;

private int height;

public Person(int age,int height){

this.age=age;

this.height=height;

}

}

package com.itheima.study;

import java.lang.reflect.Field;

public class ReflectTest{

public static void main(String...args) throws Exception{

Person p = new Person(20,30);

Field fieldAge = p.getClass().getField("age");

System.out.println(fieldAge.get(p));

}

}

练习:将随意一个对象中的全部String类型的成员变量所相应的字符串内容中的“b"改为"a"。

public class ReflectPoint

{

private int x;

public int y;

public String str1="blue";

private String str2="bubble";

public String str3="soso";

public ReflectPoint(int x, int y)

{

super();

this.x = x;

this.y = y;

}

public String toString()

{

return str1+" "+str2+" "+str3;

}

}

public class Reflect {

/**

* 练习:将随意一个对象中的全部String类型的成员变量所相应的字符串内容中的“b"改为"a"。

*

*/

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

Constructor[]  constructors=String.class.getConstructors();//得到String类的全部公共构造方法

Constructor constructor=String.class.getConstructor(StringBuffer.class);//得到指定參数的构造方法

//用构造方法创建实例

String s=(String)constructor.newInstance(new StringBuffer("黑马"));

System.out.println(s);

//Class类里面的无參构造方法

Date date=(Date)Class.forName("java.util.Date").newInstance();

System.out.println(date);

ReflectPoint rp=new ReflectPoint(3,3);

Field fieldY=rp.getClass().getField("y");//注意fieldY不是对象的变量,是所在类的变量

int rpY=(Integer) fieldY.get(rp);//依据对象取得变量的值

System.out.println(rpY);

Field fieldX=rp.getClass().getDeclaredField("x");//由于x被private修饰

fieldX.setAccessible(true);//把私有的变量设置成能够訪问

System.out.println(fieldX.get(rp));

value(rp);

System.out.println(rp);

}

private static void value(Object  obj) throws Exception {

Field[]  fields=obj.getClass().getFields();

for (Field field : fields) {

if (field.getType()==String.class) {//getType()返回一个 Class 对象。它标识了此 Field 对象所表示字段的声明类型

String  oldvalue=(String) field.get(obj);// 返回指定对象上此 Field 表示的字段的值

String  newvalue=oldvalue.replace(‘b‘,‘a‘);//把b变成a

field.set(obj, newvalue);//将指定对象变量上此 Field 对象表示的字段设置为指定的新值。

}

}

}

}

时间: 2024-10-27 00:59:42

漫谈反射的相关文章

漫谈反射在业务代码中的应用

很多人都觉得写业务代码很枯燥,没有什么技术含量,大部分就是if-else逻辑的叠加.写业务代码确实没有写中间件来的高大上,但是我觉得不管是写什么代码,想要写出好的代码都不是一件容易的事情.这不,最近我们生产系统的版本迭代过程中一个需求就让我思考了很多,并且在实现方式上做得更加的优雅. 场景如下:我们在生产系统中需要维护各个游戏的状态,当需要上线一个游戏时,需要对该游戏的各方面的信息做一遍检查,当检查所有的字段都达到要求之后,再切换该游戏的状态为已上线.首先,针对安卓游戏,我们需要检查该游戏的资质

射频识别技术漫谈(28)——基于MF1射频卡的酒店门锁设计

电子门锁是现代星级酒店管理电子化.智能化的重要电子设备.相较于传统的机械锁,基于RFID技术的电子门锁使用方便,易于管理,安全性高,可实现对开锁用户的分优先级自动管理,对房间入住信息实现自动统计与报表输出. 1  系统整体分析 MF1 S50和S70卡是遵守ISO14443A国际标准的非接触式逻辑加密卡,S50卡内共有1024字节非易失性存储空间,分为16个扇区,每个扇区包含4个数据块,每个扇区都有一组独立的密码A和B,扇区内的每个数据块都可单独设置存取条件.S70存储结构与S50类似,存储空间

iOS 组件化架构漫谈

组件化架构漫谈 前段时间公司项目打算重构,准确来说应该是按之前的产品逻辑重写一个项目.在重构项目之前涉及到架构选型的问题,我和组里小伙伴一起研究了一下组件化架构,打算将项目重构为组件化架构.当然不是直接拿来照搬,还是要根据公司具体的业务需求设计架构. 在学习组件化架构的过程中,从很多高质量的博客中学到不少东西,例如蘑菇街李忠.casatwy.bang的博客.在学习过程中也遇到一些问题,在微博和QQ上和一些做iOS的朋友进行了交流,非常感谢这些朋友的帮助. 本篇文章主要针对于之前蘑菇街提出的组件化

Android小例子:使用反射机制来读取图片制作一个图片浏览器

效果图: 工程文件夹: 该例子可供于新手参考练习,如果有哪里不对的地方,望指正>-< <黑幕下的人> java代码(MainActivity.java): package com.example.imageswitchtest; import java.lang.reflect.Field; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.v

.Net 反射

反射是.NET中的重要机制,通过反射,可以在运行时获得程序或程序集中每一个类型(包括类.结构.委托.接口和枚举等)的成员和成员的信息.有了反射,即可对每一个类型了如指掌.另外我还可以直接创建对象,即使这个对象的类型在编译时还不知道.     反射的用途:    (1)使用Assembly定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例.     (2)使用Module了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全

C#图解教程 第二十四章 反射和特性

反射和特性元数据和反射Type 类获取Type对象什么是特性应用特性预定义的保留的特性Obsolete(废弃)特性Conditional特性调用者信息特性DebuggerStepThrough 特性其他预定义特性有关应用特性的更多内容多个特性其他类型的目标全局特性自定义特性声明自定义特性使用特性的构造函数指定构造函数使用构造函数构造函数中的位置参数和命名参数限制特性的使用自定义特性的最佳实践访问特性使用IsDefined方法使用GetCustomAttributes方法 Note 类的元数据包含

Java反射

1. 介绍 反射是一种能够在程序运行时动态访问.修改某个类中任意属性和方法的机制. 具体:对于任意一个类,都能够知道这个类的所有属性和方法对于任意一个对象,都能够调用它的任意一个方法和属性 在运行时,当加载完类之后,JVM在堆内存中会自动产生一个Class类型的对象,这个对象包含了完整的类的结构信息 这个Class对象就像一面镜子,透过这个镜子看到类的结构 那么,如何得到这个Class对象呢?以下可否 Class c = new Class(); 答案是不行的,因为Class的构造函数定义为私有

深入理解Java:类加载机制及反射

一.Java类加载机制 1.概述 Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允许用户借由这个Class相关的元信息对象间接调用Class对象的功能. 虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 2.工作机制 类装载器就是寻找类的字节码文件,并构造出类在JVM内部表示

通过反射了解集合泛型的本质

通过反射了解集合泛型的本质 import java.lang.reflect.Method; import java.util.ArrayList; /** * 通过反射了解集合泛型的本质 * @author shm * */ public class MethodDemo02 { public static void main(String[] args) { ArrayList list = new ArrayList(); list.add("hello"); list.add(