黑马程序员——java —反射知识总结
2015-04-13 21:17
369 查看
——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
(一)反射的基础
(1)、什么是反射?
反射就是把java类中的各个成分映射成相应的java类。通过java的Class类的方法来获得其中的方法、变量、构造方法、修饰符、包等等信息。
百度百科解释:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
(2)、反射的基石——Class类
1、什么是java的Class类?
java程序中各个java类属于同一类事物,描述这类事物的java类名就是Class。
2、什么是字节码?
当源程序中用到类时,首先要从硬盘把这个类的那些二进制代码,一个类编译成class放在硬盘上以后,就是一些二进制代码,要把这些二进制代码加载到内存中里面来,再用这些字节码去复制出一个一个对象来。
3、如何获得各个字节码对应的实例对象(Class对象)?
三种方法:
第一种:类名.class 例如:Person.class
第二种:对象.getClass 例如:new Person( ).getClass
第三种:Class.forName(“类名”) 例如:Class.forName(“java.util.Date”)
第三种方法里面有两种情况,一种是类已经加载完成,一种是类还没有加载完成。如果类还没有加载完成,用第三种方法,会自动把类通过虚拟机加载完成。(反射中主要是用第三种方法)
4、有九个预定义的Class实例对象:8个基本类型和void
例子程序:
注意:
①Class的首字母要大些;
②Class类描述的信息:类的名字,类的访问属性,类所属于的包名,字段名称的列表,方法名称的列表等。
③Class不能通过new来构造对象,每一个字节码就是Class的实例对象。
构造对象的方法:Class a = Person.class
④只要是在源程序中出现的类型都有各自的Class实例对象,如int[].class。数组类型的Class实例对象,可以用Class.isArray()方法判断是否为数组类型的。
(三)构造方法的反射constructor类
(1)、constructor类就是代表某个类的一个构造方法
(2)、怎么得到某个类的构造方法?
①得到某类所有的构造方法
Constructor [ ] constructors =
Class.forName(“java.lang.String”).getconstructors();
②得到某个类的一个构造方法
Constructor constructor =
Class.forName(“java.lang.String”).getconstructor();
(3)、怎么创建实例对象?
①通常方法(非反射时)
例子:String str = new String(new StringBuffer( “abc”));
②用反射的构造方法时
例子:Constructor s = String.class.getConstructor(StringBuffer.class);
String str =(String)s.newInstance(new StringBuffer(“abc”));
注意:获得方法和调用方法要是相同的类型
③注意Class也有newInstance的方法
例如:Class obj = Class.forName(“java.lang.String”).newInstance();
注意:Class的newInstance方法,只能够调用无参的构造器
(四)成员变量的反射Field类
(1)、Field代表某个类中的成员变量
(2)、通过例子知道Field类的方法怎么用:
(3)总结:
Field getField(String s);//只能获取公有和父类中公有
Field getDeclaredField(String s);//获取该类中任意成员变量,包括私有
setAccessible(ture);
//如果是私有字段,要先将该私有字段进行取消权限检查的能力。也称暴力访问。
set(Object obj, Object value);//将指定对象变量上此Field对象表示的字段设置为指定的新值。
Object get(Object obj);//返回指定对象上Field表示的字段的值。
(4)练习题
将任意一个对象中所有的String类型的成员变量所对应的字符串内容的“b”改成“a”?
(五)反射的成员方法Mathod类
(1)、Mathod类代表的是某个类中的一个成员方法
(2)、得到一个类的方法:
例子:Mathod charAt
=Class.forName(“java.lang.String”).getMathod(“charAt”,int.class);
(3)、调用方法
例子:
①普通方式:System.out.println(str.charAt(1));
②反射方法:System.out.println(charAt.invoke(str,1));
注意:如果传给invoke方法的参数是null,Mathod对象对应的是一个静态方法。
例子程序:
(4)、用反射方法执行某个类的main方法
(六)、数组的反射
(1)、数组反射的基础知识
具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
注意:
①基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。
(2)数组反射的应用
1、小知识点
①Arrays.asList()方法处理int[]和String[]的差异
当处理int[]的时候返回的是数组的内容,当处理String[]的时候返回的是数字的名字
② 无法得到某个数组的具体类型,只能得到其中某个元素的类型
例子: Obj[2].getClass().getName() 得到的是数组第三个元素的的类型
2、反射怎么获取数组的值、长度、以及某个位置的值
Array工具类用于完成对数组的反射操作。
Array.getLength(Object obj);//获取数组的长度
Array.get(Object obj,int x);//获取数组中的元素
(六)、反射的深入
(1)、首先解释一下ArrayList和HashSet的区别
ArrayList:对象有序可以重复
HashSet:对象无序而且不可重复
(2)、Hashcode
①作用:
要想HashCode方法有价值的话,前提是对象存入的是hash算法这种类型的集合当中才有价值。如果不存入是hashCode算法的集合中,则不用复写此方法。
②什么是哈希算法?
若在一个集合中查找是否含有某个对象,通常是一个个的去比较,找到后还要进行equals的比较,对象特别多时,效率很低。有这么一种HashCode算法,有一个集合,把这个集合分成若干个区域,每个存进来的对象,可以算出一个hashCode值,根据算出来的值,就放到相应的区域中去。当要查找某一个对象,只要算出这个对象的hashCode值,看属于第几个区域,然后到相应的区域中去寻找,看是否有与此对象相等的对象。这样查找的性能就提高了。
③老师的总结:(面试经常遇到的问题)
当一个对象存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则对象修改后的哈希值与最初存储进HashSet集合中的哈希值就不同了。在这种情况下,调用contains方法或者remove方法来寻找或者删除这个对象的引用,就会找不到这个对象。从而导致无法从HashSet集合中单独删除当前对象,从而造成内存泄露。(程序中某一些对象不再被使用,以为被删掉了,但是没有,还一直在占用内存中,当这样的对象慢慢增加时,就会造成内存泄露。)
原因:
内存泄露:某些对象不再使用了,占用着内存空间,并未被释放,就会导致内存泄露;也就是说当程序不断增加对象,修改对象,删除对象,日积月累,内存就会用光了,就导致内存溢出。
(3)、反射的作用之——实现框架的功能
①当我们在写程序时无法知道被调用的类名,所以在程序中无法new这个类的实例对象,而要用反射的方法来做。
例子程序:
(一)反射的基础
(1)、什么是反射?
反射就是把java类中的各个成分映射成相应的java类。通过java的Class类的方法来获得其中的方法、变量、构造方法、修饰符、包等等信息。
百度百科解释:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
(2)、反射的基石——Class类
1、什么是java的Class类?
java程序中各个java类属于同一类事物,描述这类事物的java类名就是Class。
2、什么是字节码?
当源程序中用到类时,首先要从硬盘把这个类的那些二进制代码,一个类编译成class放在硬盘上以后,就是一些二进制代码,要把这些二进制代码加载到内存中里面来,再用这些字节码去复制出一个一个对象来。
3、如何获得各个字节码对应的实例对象(Class对象)?
三种方法:
第一种:类名.class 例如:Person.class
第二种:对象.getClass 例如:new Person( ).getClass
第三种:Class.forName(“类名”) 例如:Class.forName(“java.util.Date”)
第三种方法里面有两种情况,一种是类已经加载完成,一种是类还没有加载完成。如果类还没有加载完成,用第三种方法,会自动把类通过虚拟机加载完成。(反射中主要是用第三种方法)
4、有九个预定义的Class实例对象:8个基本类型和void
例子程序:
public class reflectTest{ public static void main (String[] args){ String s = "abc"; Class cls1 = s.class; Class cls2 = String.class Class cls3 = Class.forName("java.lang.String); System.out.println(int.class.isPrimitive()); //判断字节码是不是基础类型 System.out.println(int.class==integer.TYPE); //Integer.TYPE是Integer类的一个常量,它代表此包装类型包装的基本类型的字节码,所以和int.class是相等的 } }
注意:
①Class的首字母要大些;
②Class类描述的信息:类的名字,类的访问属性,类所属于的包名,字段名称的列表,方法名称的列表等。
③Class不能通过new来构造对象,每一个字节码就是Class的实例对象。
构造对象的方法:Class a = Person.class
④只要是在源程序中出现的类型都有各自的Class实例对象,如int[].class。数组类型的Class实例对象,可以用Class.isArray()方法判断是否为数组类型的。
(三)构造方法的反射constructor类
(1)、constructor类就是代表某个类的一个构造方法
(2)、怎么得到某个类的构造方法?
①得到某类所有的构造方法
Constructor [ ] constructors =
Class.forName(“java.lang.String”).getconstructors();
②得到某个类的一个构造方法
Constructor constructor =
Class.forName(“java.lang.String”).getconstructor();
(3)、怎么创建实例对象?
①通常方法(非反射时)
例子:String str = new String(new StringBuffer( “abc”));
②用反射的构造方法时
例子:Constructor s = String.class.getConstructor(StringBuffer.class);
String str =(String)s.newInstance(new StringBuffer(“abc”));
注意:获得方法和调用方法要是相同的类型
③注意Class也有newInstance的方法
例如:Class obj = Class.forName(“java.lang.String”).newInstance();
注意:Class的newInstance方法,只能够调用无参的构造器
(四)成员变量的反射Field类
(1)、Field代表某个类中的成员变量
(2)、通过例子知道Field类的方法怎么用:
public class ReflectPoint{ private int x; public int y; public ReflectPoint(int x,int y){ Super(); this.x=x; this.y=y; } public static void main(String[] args){ ReflectPoint p1 = new ReflectPoint(3,5); Field fieldy = p1.getClass().getField("y"); //注意fieldy不是变量上的值,而是指整个类中的变量 System.out.println(fieldy.get(p1)); //注意:要想得到field的值还要传一个具体的对象进去 /* 对私有的成员变量怎么访问它的值 */ Field fieldx = p1.getClass().getDeclaredField("x"); fieldx.setAccessible(true); System.out.println(fieldx.get(p1)); //又叫做暴力访问 } }
(3)总结:
Field getField(String s);//只能获取公有和父类中公有
Field getDeclaredField(String s);//获取该类中任意成员变量,包括私有
setAccessible(ture);
//如果是私有字段,要先将该私有字段进行取消权限检查的能力。也称暴力访问。
set(Object obj, Object value);//将指定对象变量上此Field对象表示的字段设置为指定的新值。
Object get(Object obj);//返回指定对象上Field表示的字段的值。
(4)练习题
将任意一个对象中所有的String类型的成员变量所对应的字符串内容的“b”改成“a”?
package cn.dhj; import java.lang.reflect.Field; public class ReflectText { public String str1 = "ball"; public String str2 = "basketball"; public String str3 = "case"; public static void changeString(Object obj) throws Exception{ Field[] fields = obj.getClass().getFields(); for(Field field : fields){ if(field.getType()==String.class){ String oldValue = (String)field.get(obj); String newValue = oldValue.replace("b", "a"); field.set(obj,newValue); } } } public String toString(){ return str1+":"+str2+":"+str3; } public static void main (String[] args) throws Exception{ ReflectText p1 = new ReflectText(); changeString(p1); System.out.println(p1); } }
(五)反射的成员方法Mathod类
(1)、Mathod类代表的是某个类中的一个成员方法
(2)、得到一个类的方法:
例子:Mathod charAt
=Class.forName(“java.lang.String”).getMathod(“charAt”,int.class);
(3)、调用方法
例子:
①普通方式:System.out.println(str.charAt(1));
②反射方法:System.out.println(charAt.invoke(str,1));
注意:如果传给invoke方法的参数是null,Mathod对象对应的是一个静态方法。
例子程序:
System.out.println("--------3. 方法反射-------"); // Method也是属于Class所有 Method charAtMethod = String.class.getMethod("charAt", int.class); // Method的调用必须属于某个对象:invoke(对象,参数...) // invoke(null, 参数...)表示调用的静态方法 String s = new String("abc"); System.out.println(charAtMethod.invoke(s, 2)); // 静态调用 TestArguments.main(new String[] { "111", "222", "333" }); // 类名由main(String[] args)方法中的第一个参数指定 if (args.length > 0) { String startingClassName = args[0]; Method startdMainMethod = Class.forName(startingClassName) .getMethod("main", String[].class); // main为静态方法 startdMainMethod.invoke(null, (Object) new String[] { "aaa", "bbb", "ccc" }); // 或 startdMainMethod.invoke(null, new Object[] { new String[] { "aaa", "bbb", "ccc" } }); }
(4)、用反射方法执行某个类的main方法
package cn.itheima; //定义一个测试类 class Test{ public static void main(String[] args){ for(String arg : args){ System.out.println(arg); } } } //用反射方式根据用户提供的类名,去执行该类中的main方法。 import java.lang.reflect.Method; public class PerformedMain{ public static void main(String[] args) throws Exception { //普通方式 Test.main(new String[]{"111","222","333"}); System.out.println("-----------------------------"); //反射方式 String className=args[0]; Method mainMethod= Class.forName(className).getMethod("main",String[].class); //方式一:强制转换为超类Object,不用拆包 mainMethod.invoke(null, (Object)new String[]{"111","222","333"}); //方式二:将数组打包,编译器拆包后就是一个String[]类型的整体 mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}}); }
(六)、数组的反射
(1)、数组反射的基础知识
具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
/* 举例 */ int[] a1 = new int[3]; int[] a2 = new int[4]; int[][] a3 = new int[3][4]; String[] a4 = new String[3]; System.out.println(a1.getClass()=a2.getClass());//true System.out.println(a1.getClass()=a3.getClass());//false System.out.println(a3.getClass()=a4.getClass());//false System.out.println(a2.getClass()=a4.getClass());//false System.out.println(a1.getClass.getName()); //数组字节码的名字:有[和数组对应类型的缩写,如int[]数组的名称为:[I
注意:
①基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。
(2)数组反射的应用
1、小知识点
①Arrays.asList()方法处理int[]和String[]的差异
当处理int[]的时候返回的是数组的内容,当处理String[]的时候返回的是数字的名字
② 无法得到某个数组的具体类型,只能得到其中某个元素的类型
例子: Obj[2].getClass().getName() 得到的是数组第三个元素的的类型
2、反射怎么获取数组的值、长度、以及某个位置的值
Array工具类用于完成对数组的反射操作。
Array.getLength(Object obj);//获取数组的长度
Array.get(Object obj,int x);//获取数组中的元素
(六)、反射的深入
(1)、首先解释一下ArrayList和HashSet的区别
ArrayList:对象有序可以重复
HashSet:对象无序而且不可重复
(2)、Hashcode
①作用:
要想HashCode方法有价值的话,前提是对象存入的是hash算法这种类型的集合当中才有价值。如果不存入是hashCode算法的集合中,则不用复写此方法。
②什么是哈希算法?
若在一个集合中查找是否含有某个对象,通常是一个个的去比较,找到后还要进行equals的比较,对象特别多时,效率很低。有这么一种HashCode算法,有一个集合,把这个集合分成若干个区域,每个存进来的对象,可以算出一个hashCode值,根据算出来的值,就放到相应的区域中去。当要查找某一个对象,只要算出这个对象的hashCode值,看属于第几个区域,然后到相应的区域中去寻找,看是否有与此对象相等的对象。这样查找的性能就提高了。
③老师的总结:(面试经常遇到的问题)
当一个对象存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则对象修改后的哈希值与最初存储进HashSet集合中的哈希值就不同了。在这种情况下,调用contains方法或者remove方法来寻找或者删除这个对象的引用,就会找不到这个对象。从而导致无法从HashSet集合中单独删除当前对象,从而造成内存泄露。(程序中某一些对象不再被使用,以为被删掉了,但是没有,还一直在占用内存中,当这样的对象慢慢增加时,就会造成内存泄露。)
原因:
内存泄露:某些对象不再使用了,占用着内存空间,并未被释放,就会导致内存泄露;也就是说当程序不断增加对象,修改对象,删除对象,日积月累,内存就会用光了,就导致内存溢出。
(3)、反射的作用之——实现框架的功能
①当我们在写程序时无法知道被调用的类名,所以在程序中无法new这个类的实例对象,而要用反射的方法来做。
例子程序:
/* 代码实现,一般步骤: ①将文件读取到读取流中,要写出配置文件的绝对路径。 如:InputStream is=new FileInputStream(“配置文件”); ②用Properties类的load()方法将流中的数据存入集合。 ③关闭流:关闭的是读取流,因为流中的数据已经加载进内存。 */ 例子: public static void main(String[] args){ InputStream ps = new FileInputStream("配置文件"); Propertise props = new Propertise(); props.load(ps); ps.close(); String className = props.getProperty("className"); collection collections=Class.forName(className).newInstance(); ........ }
相关文章推荐
- 黑马程序员学习log第九篇基础知识:JAVA的面向对象之正则表达式及反射总结
- 黑马程序员_java反射知识总结
- 黑马程序员_09Java反射知识总结
- 黑马程序员_Java Script简单知识总结(JS特有的)
- 黑马程序员 Java基础知识总结-面向对象三大特征
- 黑马程序员_java基础知识学习总结四
- 黑马程序员——java复习总结——反射
- JAVA_SE ----- 基础知识总结-----反射
- 黑马程序员_Java反射技术学习总结
- 黑马程序员_Java第15天知识总结_TreeSet_泛型
- 黑马程序员—反射知识总结
- 黑马程序员 Java基础知识总结-网络编程
- 黑马程序员_反射知识总结
- 黑马程序员+对Java中反射技术的总结
- 黑马程序员_Java第14天知识总结_集合类(集合框架)_Collection_迭代器_List_Set_HashSet
- 黑马程序员--Java基础知识总结
- 黑马程序员:Java基础总结----反射
- 黑马程序员---Java高新技术反射知识点总结
- 黑马程序员--java基础总结--基本知识
- 黑马程序员_JAVA_枚举和反射总结