黑马程序员 反射
2015-08-29 17:01
597 查看
------- android培训、java培训、期待与您交流! ----------
反射:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
想要获取到一个类的字段,方法,构造函数等,首先要获取其字节码文件。
获取字节码的三种方式:
1、当获取一个对象时,想要获取其类的字节码,使用getClass()方法。
Class cl = p.getClass() //获取对象p的字节码文件
2、当获取一个指定类的字节码时,使用该类的class方法
Class cl = Student.class //获取Student类的字节码文件
3、获取一个类的的字节码,也可以通过Class类的forName()方法加上类的全限定名获取
Class cl = Class.forName("java.util.Arrays"); //获取Arrays类的字节码文件
九个预定义Class对象:8个基本数据类型,和void。
在Class类中有一些常用方法:
public static Class<?> forName(String className):通过类的名字获得该类的Class对象,这个方法是静态方法。在Class类中没有构造方法,要想获得Class对象只能通过静态方法返回。
Class getClass() :返回Class对象即字节码对象
public Field getField(String name):返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。name 参数是一个 String,用于指定所需字段的简称。
public Method getMethod(String name,Class<?>... parameterTypes):返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
public String getName():以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。 public boolean isArray():判定此 Class 对象是否表示一个数组类。
public boolean isPrimitive():判定指定的 Class 对象是否表示一个基本类型。
public boolean isInterface():判定指定的 Class 对象是否表示一个接口类型。
public T newInstance():创建此 Class 对象所表示的类的一个新实例。如同用一个带有一个空参数列表的 new 表达式实例化该类。
可以看到,反射就是将Java类中的各种成分映射成相应的java类。例如,类中的组成成分:成员变量、构造方法、方法、包信息等分别对应Field、Constructor、Method、Package等。
构造函数可能有多种重载方式,我们通过不同的参数列表来确定反射的是哪个构造函数。或者通过getConstructors方法得到其全部的构造函数。
Field fieldY = XXX.getClass().getField("Y");
获得了Field对象后可以再使用Field对象给指定对象上的成员变量设定指定的值,或者得到一个对象上这个字段的值
public void set(Object obj,Object value):将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
public Object get(Object obj):返回指定对象上此 Field 表示的字段的值。如果该值是一个基本类型值,则自动将其包装在一个对象中。
如果要访问私有的字段,要先设置其权限
public void setAccessible(boolean flag):将此对象的 accessible 标志设置为指示的布尔值。值为true时表示可以访问。
public Method getMethod(String name,Class<?>... parameterTypes):获得一个指定的Method对象,该方法的名字以传入的值确认,parameterTypes代表该方法的参数列表 ,无参数可以写null。
public Method[] getMethods():返回一个包含某些 Method 对象的数组
public Method getDeclaredMethod(String name,Class<?>... parameterTypes):获得本类私有方法
Method类中常用的方法有:
public Object invoke(Object obj,Object... args):对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。obj表示指定的对象,args表示参数列表当这个方法为静态方法时作用对象可以填null,无参方法时参数可以填null。
框架在开发时,无法知道后来开发要调用的类名,所以无法直接通过new某个对象,而是通过反射来创建对象。
反射:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
1.Class类
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。想要获取到一个类的字段,方法,构造函数等,首先要获取其字节码文件。
获取字节码的三种方式:
1、当获取一个对象时,想要获取其类的字节码,使用getClass()方法。
Class cl = p.getClass() //获取对象p的字节码文件
2、当获取一个指定类的字节码时,使用该类的class方法
Class cl = Student.class //获取Student类的字节码文件
3、获取一个类的的字节码,也可以通过Class类的forName()方法加上类的全限定名获取
Class cl = Class.forName("java.util.Arrays"); //获取Arrays类的字节码文件
九个预定义Class对象:8个基本数据类型,和void。
在Class类中有一些常用方法:
public static Class<?> forName(String className):通过类的名字获得该类的Class对象,这个方法是静态方法。在Class类中没有构造方法,要想获得Class对象只能通过静态方法返回。
Class getClass() :返回Class对象即字节码对象
public Field getField(String name):返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。name 参数是一个 String,用于指定所需字段的简称。
public Method getMethod(String name,Class<?>... parameterTypes):返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
public String getName():以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。 public boolean isArray():判定此 Class 对象是否表示一个数组类。
public boolean isPrimitive():判定指定的 Class 对象是否表示一个基本类型。
public boolean isInterface():判定指定的 Class 对象是否表示一个接口类型。
public T newInstance():创建此 Class 对象所表示的类的一个新实例。如同用一个带有一个空参数列表的 new 表达式实例化该类。
可以看到,反射就是将Java类中的各种成分映射成相应的java类。例如,类中的组成成分:成员变量、构造方法、方法、包信息等分别对应Field、Constructor、Method、Package等。
2.构造函数的反射
当一个类不存在空参数的构造函数时,就不能通过newInstance方法获得其对象,所以必须先要通过反射获得其构造函数。构造函数可能有多种重载方式,我们通过不同的参数列表来确定反射的是哪个构造函数。或者通过getConstructors方法得到其全部的构造函数。
Constructor cons = String.class.getConstructor(StringBuffer.class); String str2 = (String)cons.newInstance(new StringBuffer("abc"));
3.成员变量的反射
使用getField方法获得成员变量的字段。Field fieldY = XXX.getClass().getField("Y");
获得了Field对象后可以再使用Field对象给指定对象上的成员变量设定指定的值,或者得到一个对象上这个字段的值
public void set(Object obj,Object value):将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
public Object get(Object obj):返回指定对象上此 Field 表示的字段的值。如果该值是一个基本类型值,则自动将其包装在一个对象中。
如果要访问私有的字段,要先设置其权限
public void setAccessible(boolean flag):将此对象的 accessible 标志设置为指示的布尔值。值为true时表示可以访问。
public class ReflactTest2 { public static void main(String[] args)throws Exception { Class c =Class.forName("Person"); //调用默认的构造函数 Person p = (Person)c.newInstance(); //获得Field对象,是属于字节码的。对于private的属性要使用getDeclaredFile才可以看见。 Field age = c.getDeclaredField("age"); //对于private的变量,要通过下面的方法设置权限 age.setAccessible(true); //调用Field对象的set方法设置具体person对象的age age.set(p, 10); Field name = c.getDeclaredField("name"); name.setAccessible(true); name.set(p, "zhangsan"); //不是private的属性使用getField就可以拿到。 Field address = c.getField("address"); address.set(p, "beijing"); System.out.println(p.toString()); } } class Person{ private int age ; private String name ; public String address; public Person(){ System.out.println("Person run.."+this.name+":"+this.age); } public void show(){ System.out.println("Pserson show ..."); } public void show(String p){ System.out.println("Pserson show ..."+"String:"+p); } private void show(int i){ System.out.println("private method show ..."+"String:"+i); } }
4.方法的反射
通过Class类中的getMethod方法来获得指定的Method对象public Method getMethod(String name,Class<?>... parameterTypes):获得一个指定的Method对象,该方法的名字以传入的值确认,parameterTypes代表该方法的参数列表 ,无参数可以写null。
public Method[] getMethods():返回一个包含某些 Method 对象的数组
public Method getDeclaredMethod(String name,Class<?>... parameterTypes):获得本类私有方法
Method类中常用的方法有:
public Object invoke(Object obj,Object... args):对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。obj表示指定的对象,args表示参数列表当这个方法为静态方法时作用对象可以填null,无参方法时参数可以填null。
public static void getPersonMethod() throws Exception{ //如果想要获取方法,必须先要有对象。 Class clazz=Class.forName("cn.itheima.Person"); Person p=(Person)clazz.newInstance(); Method[] mes=clazz.getMethods();//只获取所有方法 for(Method me:mes){ System.out.println(me); } //获取单个方法 Method me=clazz.getMethod("toString", null); Object returnVaule=me.invoke(p, null); System.out.println(returnVaule); }
5.反射在框架中的作用
java框架就是一些类和接口的集合,通过这些类和接口协调来完成一系列的程序实现。框架在开发时,无法知道后来开发要调用的类名,所以无法直接通过new某个对象,而是通过反射来创建对象。
public class ReflactTest { public static void main(String[] args)throws Exception { //加载配置文件 Properties proper = new Properties(); InputStream is = new FileInputStream("G:\\eclipse\\Reflect\\src\\init.property"); proper.load(is); //拿到配置文件中,对应的类名 String soundcard = proper.getProperty("soundCard"); String netcard = proper.getProperty("netCard") ; //根据上面的类名,通过反射获得类的对象 pci p1 = (pci)Class.forName(soundcard).newInstance(); pci p2 = (pci)Class.forName(netcard).newInstance() ; //调用对象的方法 p1.run(); p2.run(); } } class SoundCart implements pci{ public void start(){ System.out.println("Sound is start"); } public void close(){ System.out.println("Sound is close"); } public void run(){ start(); close(); } } class netCard implements pci{ public void start() { System.out.println("netCard is start"); } @Override public void close() { System.out.println("netCard is start"); } public void run(){ start(); close(); } }
6.一个反射应用实例
可以看到,泛型的出现让程序变得更安全,但是反射可以绕过泛型,让程序又出现了安全隐患。。/** * * 3、 ArrayList<Integer> list = new ArrayList<Integer>(); * 在这个泛型为Integer的ArrayList中存放一个String类型的对象。 */ import java.lang.reflect.*; import java.util.*; public class pritice03 { public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<Integer>(); //@SuppressWarnings("rawtypes") Class<?> listcls = list.getClass(); try { Method me = listcls.getMethod("add", Object.class);//获得ArrayList中的add方法 me.invoke(list,"哥就是要存字符串"); //调用该方法存入字符串到泛型为Integer的ArrayList中 System.out.println(list); } catch (Exception e) { e.printStackTrace(); } } }
相关文章推荐
- 程序员面试中常见10大算法汇总
- 程序员面试中常见10大算法汇总
- 教你如何迅速秒杀掉:99%的海量数据处理面试题
- 黑马程序员——Java之内部类
- 黑马程序员--Java_IO流(二)
- C#程序员开发WinForm必须知道的 Window 消息大全(转)
- 2015/8/28的面试题
- 剑指Offer面试题:14.链表的倒数第k个节点
- 程序员面试金典1.8:判断翻转子串
- 黑马程序员——java基础——反射的定义及用法
- 程序员面试金典1.7:若M*N矩阵中某个元素为0,则将其所在的行与列清零
- 程序员面试金典1.6:将图像旋转90度。不占用额外内存空间
- 剑指Offer面试题:13.调整数组顺序使奇数位于偶数前面
- 面试题:乱序字符串
- 2014腾讯、百度、阿里面试经验
- 黑马程序员 File&Properties&URL
- 黑马程序员 --- NSString和NSMutableString的用法
- mybatis常见的面试题
- 关于线程的面试题
- 剑指offer-第六章面试中的各项能力(数字在排序数组中出现的次数)