黑马程序员——Java之反射
2015-04-13 01:03
344 查看
-------------------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ---------------------
总之反射就是把Java类中的各个成分映射成相应的类。例如一个Java类中用一个class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机,变速箱也是一个个的类。表示Java类的class类显然也要提供一系统的方法,来获取其中的变量,方法,构造方法,修饰符,包等信息。这些信息时就是用相应类的实例对象来表示,包括Field、Method、Contructor、Package等。(反射从1.2版本就存在)
Class类描述的信息有:类名、类访问属性、包名、字段,方法等。每一个字节码就是class的实例对象。
class的实例对象是什么呢?
Class对应各个类在内存中字节码,一个类被类加载器加载到内存中,占用一片存储空间,这个空间里的内容就是字节码,不同类的字节码是不同的,这一个个的空间可分别用一个个的对象来表示,这些对象显然具有相同类型这个类型就是Class类型。
注意:字节码就是当源程序中用到类时,jvm虚拟机会把Java程序编译成class字节码文件,再把字节码文件加载到内存中,再根据字节码在内存中创建对象。
类名.class
例如System.class,(返回类的字节码,虚拟机已经加载该类)
方式二:
对象.getClass()
例如:newPerson().getClass() (根据对象返回该对象所对应类的字节码,虚拟机已经加载该类)
方式三:
Class.forName("类名")
例如:Class.forName("java.util.Date")(类没有被加载到虚拟机,最常用的方法里面可以是变量,从文件中获取变量的值 )
注意:
TYPE是Integer类的一个常量,它代表此包装类型包装的基本类型的字节码,所以和int.class是相等的。基本数据类型的字节码都可以用与之对应的包装类中的TYPE常量表示
public boolean isPrimitive() 判定指定的 Class 对象是否表示一个基本类型。
public boolean isArray() 判定此 Class 对象是否表示一个数组类。
public boolean isInterface()判定指定的 Class 对象是否表示一个接口类型。
获取:
public static Class<?> forName(StringclassName)
返回与带有给定字符串名的类或接口相关联的Class 对象
public final
Class<?> getClass()
返回Class对象即字节码对象
public
Constructor<?>[]getConstructors()
返回Class对象的所有构造方法。
public Constructor<T>getConstructor(Class<?>... parameterTypes)
返回指定的构造方法。
public Field[] getFields()
返回包含某些Field对象的数组,表示所代表类中的成员字段。
public Field getField(String name)
返回一个Field对象,它表示此Class对象所代表的类或接口的指定公共成员字段。
public Method getMethod(Stringname,Class<?>... parameterTypes)
返回一个Method对象,表示的是此Class对象所代表的类的指定公共成员方法。
public Method[] getMethods()
返回一个包含某些Method对象的数组,是所代表的的类中的公共成员方法。
public String
getName()以String形式返回此Class对象所表示的实体名称。
public Class<? super
T> getSuperclass()返回此Class所表示的类的超类的名称
创建:
public T newInstance()
创建此Class对象所表示的类的一个新实例。
返回类中所有的public构造器集合,默认构造器的下标为0
public Constructor<T>getConstructor(Class<?>... parameterTypes)
返回指定public构造器,参数为构造器参数类型集合
public Constructor<?>[]getDeclaredConstructors()
返回类中所有的构造器,包括私有
public Constructor<T>getDeclaredConstructor(Class<?>... parameterTypes)
返回任意指定的构造器
从名字来看,还是很好懂的,带上Declared的都是获得所有的构造方法,包括私有。
反射方式:Stringstr=(String)Constructor.newInstance(new StringBuffer("abc"));
Class为什么也有newInstance()方法?
例如:Stringstr=(String)Class.forName("java.lang.String").newInstance();
原理:该方法的内部是先得到默认的构造方法,用缓存机制来保存得到的构造方法的实例对象,所以可以用该方法创建无参的实例对象。
public Field[] getDeclaredFields() 获取所有的成员变量
public Field getField(String name) 获取任意public成员变量
public Field[] getFields() 获取所有的public成员变量
public void setAccessible(boolean flag)
该方法表示如果是私有字段,要先将该私有字段进行取消权限检查的能力。也称暴力访问。
暴力反射代码示例:
练习:将字符串中的字母b替换成a;
public Method getMethod(Stringname,Class<?>... parameterTypes)
获取指定公有方法 参数1:方法名 参数2:参数类型集合
public Method[] getDeclaredMethods() 获取所有的方法
public Method getDeclaredMethod(Stringname,Class<?>... parameterTypes) 获取任意指定方法
反射方式:System.out.println(charAt.invoke(str,2 ));
注意:如果invoke方法参数1为null; 则代表Method对象对应的是静态方法。jdk1.4和jdk1.5区别;
jdk1.4: public Object invoke(Object obj,Object[ ]args)参数2列表需要存入到数组中。
jdk1.5: public Object invoke(Object obj,Object... args)参数2列表引入了可变参数。
实现代码:
代码示例:
代表数组的class实例对象的getSuperclass( )方法,返回父类为Object类对应的class。
基本类型的一维数组可以被当作Object类型使用,不能当作Object[ ]类型使用,非基本类型的一维数组,即可以当作Object类来使用,又可以当作Object[ ]类型使用。
例: int a = new int[3];Object[] obj=new Object[]{”ABC”,1};
注意:无法得到某个数组的具体类型,只能得到其中某个元素的类型,
如:Obj[0].getClass().getName()得到的是java.lang.String。
Array工具类用于完成对数组的反射操作。
Array.getLength(Objectobj);//获取数组的长度
Array.get(Objectobj,int x);//获取数组中的元素
练习:数组反射
i
注意:框架和工具类的区别:工具类被用户类调用,而框架是调用用户提供的类。
-------------------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ---------------------
一、反射
1、概念
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 -----百度百科总之反射就是把Java类中的各个成分映射成相应的类。例如一个Java类中用一个class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机,变速箱也是一个个的类。表示Java类的class类显然也要提供一系统的方法,来获取其中的变量,方法,构造方法,修饰符,包等信息。这些信息时就是用相应类的实例对象来表示,包括Field、Method、Contructor、Package等。(反射从1.2版本就存在)
2、反射的基石Class类
(1)概述
Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class,它是经过类的不同属性向上不断抽取出来类。Class类描述的信息有:类名、类访问属性、包名、字段,方法等。每一个字节码就是class的实例对象。
class的实例对象是什么呢?
Class对应各个类在内存中字节码,一个类被类加载器加载到内存中,占用一片存储空间,这个空间里的内容就是字节码,不同类的字节码是不同的,这一个个的空间可分别用一个个的对象来表示,这些对象显然具有相同类型这个类型就是Class类型。
注意:字节码就是当源程序中用到类时,jvm虚拟机会把Java程序编译成class字节码文件,再把字节码文件加载到内存中,再根据字节码在内存中创建对象。
(2)获得class的三种方法:
方式一:类名.class
例如System.class,(返回类的字节码,虚拟机已经加载该类)
方式二:
对象.getClass()
例如:newPerson().getClass() (根据对象返回该对象所对应类的字节码,虚拟机已经加载该类)
方式三:
Class.forName("类名")
例如:Class.forName("java.util.Date")(类没有被加载到虚拟机,最常用的方法里面可以是变量,从文件中获取变量的值 )
(3)Java预定义对象
Java有九种预定义的 Class 对象,表示八个基本类型和void。这些类对象由 Java 虚拟机创建,与其表示的基本类型同名,即 boolean、byte、char、short、int、long、float 和 double。注意:
TYPE是Integer类的一个常量,它代表此包装类型包装的基本类型的字节码,所以和int.class是相等的。基本数据类型的字节码都可以用与之对应的包装类中的TYPE常量表示
(4)Class常用方法
判断:public boolean isPrimitive() 判定指定的 Class 对象是否表示一个基本类型。
public boolean isArray() 判定此 Class 对象是否表示一个数组类。
public boolean isInterface()判定指定的 Class 对象是否表示一个接口类型。
获取:
public static Class<?> forName(StringclassName)
返回与带有给定字符串名的类或接口相关联的Class 对象
public final
Class<?> getClass()
返回Class对象即字节码对象
public
Constructor<?>[]getConstructors()
返回Class对象的所有构造方法。
public Constructor<T>getConstructor(Class<?>... parameterTypes)
返回指定的构造方法。
public Field[] getFields()
返回包含某些Field对象的数组,表示所代表类中的成员字段。
public Field getField(String name)
返回一个Field对象,它表示此Class对象所代表的类或接口的指定公共成员字段。
public Method getMethod(Stringname,Class<?>... parameterTypes)
返回一个Method对象,表示的是此Class对象所代表的类的指定公共成员方法。
public Method[] getMethods()
返回一个包含某些Method对象的数组,是所代表的的类中的公共成员方法。
public String
getName()以String形式返回此Class对象所表示的实体名称。
public Class<? super
T> getSuperclass()返回此Class所表示的类的超类的名称
创建:
public T newInstance()
创建此Class对象所表示的类的一个新实例。
3、Constructor类
(1)概述
Constructor类是Java所有类中的构造方法抽取而形成的类,这个类用来封装反射得到的构造器(2)获得Constructor四种方法
public Constructor<?>[]getConstructors()返回类中所有的public构造器集合,默认构造器的下标为0
public Constructor<T>getConstructor(Class<?>... parameterTypes)
返回指定public构造器,参数为构造器参数类型集合
public Constructor<?>[]getDeclaredConstructors()
返回类中所有的构造器,包括私有
public Constructor<T>getDeclaredConstructor(Class<?>... parameterTypes)
返回任意指定的构造器
从名字来看,还是很好懂的,带上Declared的都是获得所有的构造方法,包括私有。
(3)创建实例对象
通常方式:String str=new String(newStringBuffer("abc"))反射方式:Stringstr=(String)Constructor.newInstance(new StringBuffer("abc"));
Class为什么也有newInstance()方法?
例如:Stringstr=(String)Class.forName("java.lang.String").newInstance();
原理:该方法的内部是先得到默认的构造方法,用缓存机制来保存得到的构造方法的实例对象,所以可以用该方法创建无参的实例对象。
public class ClassDemo { publicstatic void main(String[] args){ Personperson=new Person("张三",30); try{ Constructorcon=person.getClass().getConstructor(String.class,int.class);//获取Person中参数为String和int的构造方法. Personp=(Person)con.newInstance("六六",88);//使用该构造方法,创建Person实例, System.out.println(p); } catch(Exceptione){ e.printStackTrace(); } } }
4、Field类
(1)概念
Field类是Java所有类中的变量抽取而形成的类,这个类用来封装反射得到的成员变量。(2)获得Field类的四种方法
public Field getDeclaredField(Stringname) 获取任意指定名字的成员public Field[] getDeclaredFields() 获取所有的成员变量
public Field getField(String name) 获取任意public成员变量
public Field[] getFields() 获取所有的public成员变量
(3)暴力反射
可以看出和Constructor的方法一样,带Declared可以获取到私有变量。可以获取到但是无法看到其中的内容是什么,要想看到需要暴力反射public void setAccessible(boolean flag)
该方法表示如果是私有字段,要先将该私有字段进行取消权限检查的能力。也称暴力访问。
暴力反射代码示例:
public class Person { private String name; public int age; public Person(String name,int age){ this.name=name; this.age=age; } }
public class ClassDemo { public static void main(String[] args){ Person person=new Person("张三",30); try{ Field[] field=person.getClass().getFields();//获取所有的成员变量 Field fieldN=person.getClass().getDeclaredField("name");//获取成员变量name,因为name是私有的所以需要 fieldN.setAccessible(true);//暴力反射 Field fieldA=person.getClass().getField("age");//获取成员编程age System.out.println("name值:"+fieldN.get(person));//获取ps对象的name变量的值。 System.out.println("age值:"+fieldA.get(person));//获取ps对象的age变量的值。 } catch(Exception e){ e.printStackTrace(); } } }
练习:将字符串中的字母b替换成a;
public class Person { public String str1; public String str2; public String str3; public Person(String str1,String str2,String str3){ this.str1=str1; this.str2=str2; this.str3=str3; } public String toString(){ return "str1值:"+str1+"str2值:"+str2+"str3值:"+str3; } }
public class ClassDemo { public static void changValue(Object obj){ try{ Field[]fields=obj.getClass().getFields();//获取obj对象类中的可见成员变量。 for(Field field:fields){ if(field.getType() ==String.class){//getType为获取本身类型,因为字节码只有一份,所以用==号比较,也可以用equals比较。 StringoldValue=(String)field.get(obj);//如果field为string类型则获取此类型的值。 StringnewValue=oldValue.replace('b','a');//将值的b字符替换成a字符,替换成新的值, field.set(obj,newValue);//将obj对象所表示的值,设置为改好后的值。 } } } catch(Exception e){ e.printStackTrace(); } } public static void main(String[] args){ Person person=newPerson("abc","abcd","abcde"); changValue(person); System.out.println(person); } }
5、Method类
(1)概念
Method类是Java所有类中的方法抽取而形成的类,这个类用来封装反射得到的方法。(2)获得Method的四种方法
public Method[] getMethods() 获取所有的共有方法的集合public Method getMethod(Stringname,Class<?>... parameterTypes)
获取指定公有方法 参数1:方法名 参数2:参数类型集合
public Method[] getDeclaredMethods() 获取所有的方法
public Method getDeclaredMethod(Stringname,Class<?>... parameterTypes) 获取任意指定方法
(3)调用获得的方法
通常方式:System.out.println(str.charAt(2 ));反射方式:System.out.println(charAt.invoke(str,2 ));
注意:如果invoke方法参数1为null; 则代表Method对象对应的是静态方法。jdk1.4和jdk1.5区别;
jdk1.4: public Object invoke(Object obj,Object[ ]args)参数2列表需要存入到数组中。
jdk1.5: public Object invoke(Object obj,Object... args)参数2列表引入了可变参数。
实现代码:
public class ClassDemo { public static void main(String[] args){ try{ String str="abcd"; Methodm=Class.forName("java.lang.String").getMethod("charAt",int.class);//获取String类中的charAt方法且方法中的形参为int类型。 System.out.println(m.invoke(str,1));//调用该方法,把1传值进去。 System.out.println(m.invoke(str,new Object[]{3}));//调用该方法 } catch(Exception e){ e.printStackTrace(); } } }
(4)反射其他类main方法
我们平常在写源程序时,并不知道使用者传入的类名是什么,但是虽然传入的类名不知道,而知道的是这个类中的方法有main这个方法。所以可以通过反射的方式,通过使用者传入的类名(可定义字符串型变量作为传入类名的入口,通过这个变量代表类名),内部通过传入的类名获取其main方法,然后执行相应的内容。代码示例:
class TestArguments { public static void main(String[] args){ for(String s:args){ System.out.println(s); } } }
public class ClassDemo { //练习:执行其他类中的main方法。 public static void main(String[] args){ try{ StringstrMainName=args[0];//args传值进来的就是其他类的名字。 Methodm=Class.forName(strMainName).getMethod("main",String[].class);//获取类的main方法,mian方法的参数是String数组。 m.invoke(null,new Object[]{newString[]{"111","222","333"}}); //第二种方法:m.invoke(null,(Object)newString[]{"111","222","333"}); /**参数1为null:因为main方法为静态方法。 参数2:传值进去一个数组,因为mian方法中只有一个数组参数,所以外面再包装成一个Object数组, mian方法就会把)newString[]{"111","222","333"}当作一个参数,否则的话会把它当作三个参数。 */ } catch(Exception e){ e.printStackTrace(); } } }
6、数组反射
(1)规则
具有相同维数和元素的类型的数组属于同一类型数组。即具有相同Class对象。代表数组的class实例对象的getSuperclass( )方法,返回父类为Object类对应的class。
基本类型的一维数组可以被当作Object类型使用,不能当作Object[ ]类型使用,非基本类型的一维数组,即可以当作Object类来使用,又可以当作Object[ ]类型使用。
(2)获得数组的元素
如何得到某个数组中的某个元素的类型,例: int a = new int[3];Object[] obj=new Object[]{”ABC”,1};
注意:无法得到某个数组的具体类型,只能得到其中某个元素的类型,
如:Obj[0].getClass().getName()得到的是java.lang.String。
Array工具类用于完成对数组的反射操作。
Array.getLength(Objectobj);//获取数组的长度
Array.get(Objectobj,int x);//获取数组中的元素
练习:数组反射
i
mport java.lang.reflect.*; public class ClassDemo { public static void printArray(Object obj){ try{ Class cl=obj.getClass();//获取该类型的字节码。 if(cl.isArray()){//判断是否为数组类型字节码。 int len=Array.getLength(obj);//是数组则获取数组的长度 for(int x=0;x<len;x++){//循环遍历数组 System.out.println(Array.get(obj,x));//通过Array的get方法获取某个对象的数组坐标元素。 } } else{ System.out.println(obj);//不是数组则直接输出。 } } catch(Exception e){ e.printStackTrace(); } } public static void main(String[] args){ String[] str={"a","b","c"}; printArray(str); printArray("ssss"); } }
7、用反射实现框架的功能
(1)什么是框架
房地产商造房子用户住,门窗和空调等等内部都是由用户自己安装,房子就是框架,用户需使用此框架,安好门窗等放入到房地产商提供的框架中。注意:框架和工具类的区别:工具类被用户类调用,而框架是调用用户提供的类。
(2)框架要解决的核心问题:
我们在写框架(造房子的过程)的时候,调用的类(安装的门窗等)还未出现,那么,框架无法知道要被调用的类名,所以在程序中无法直接new其某个类的实例对象,而要用反射来做。-------------------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ---------------------
相关文章推荐
- 黑马程序员_java基础自学反射
- 黑马程序员---------Java面向对象——反射
- 黑马程序员-java反射基础
- 黑马程序员-06-离你很近的java反射技术笔记总结
- 黑马程序员——Java基础-反射学习
- 黑马程序员——Java基础—反射机制
- 黑马程序员__java_反射
- 黑马程序员-JAVA学习之反射getDeclaredField()方法与getField()方法的区别
- 黑马程序员——java中的枚举和反射初探
- 黑马程序员--Java基础加强--07枚举、反射、注释
- 黑马程序员--反射机制和类加载器--java学习日记12(高新技术)
- 黑马程序员_java的反射机制
- 黑马程序员——JAVA学习笔记——反射机制(下)
- 黑马程序员---java反射详解
- 黑马程序员——Java 反射 (第十二篇)
- 黑马程序员——Java学习笔记之13——“反射”总结
- 黑马程序员---java基础加强_成员变量的反射
- 黑马程序员—java高新技术_枚举&反射&内省
- 黑马程序员——java反射
- 黑马程序员--java高新技术 25--枚举,反射