黑马程序员——高薪技术——反射
2015-11-03 21:55
120 查看
------- android培训、java培训、期待与您交流!
----------
第一部分 Java反射基础
1.1 如何得到字节码
1、类名.class ,列入System.class
2、对象.getClasss(),得到对象所属的字节码
3、Class.forName("类名")(面试题)
Class.forName("java.lang.String"),
加载字节码方式:
(1)这份字节码曾经被加载过,已经存在于JDK(JAVA 虚拟机)中,可以直接返回
(2)JDK还没有这份字节码,用类加载器加载,加载后缓存在虚拟机,
1.2 八个基本类型加上void.class构成九个预定义Class对象
只要是在源程序中出现的类型,都有自己的Class实例对象,例如,int[], void...
1.3 反射就是把java中的各种成分映射成响相应的java类
1.4 反射会导致性能下降
代码示例:
运行结果:
true
true
false
true
false
true
false
true
第二部分 Java反射的基本应用
2.1 构造方法的反射
代码示例:
c
2.2 成员变量的反射
经典比喻;人在黑板上画圆(圆的动作);司机刹车(车的动作);人关门(门的动作)
静态方法调用不需要对象,因此看到不需要对象调用的方法(第一个参数为null,method为静态方法),为静态方法
注意:jdk1.4 需要没有可变参数方法,需要将参数打包成参数数组
代码示例:
运行结果:
5
3
2.3 成员方法的反射
代码示例:
运行结果:
2.4 对接受数组参数的成员方法进行反射
自己写程序,调用封装的main方法
代码示例:
2.5 数组与Object的关系及其反射类型
代码示例:
[I
java.lang.Object
java.lang.Object
[I@7852e922
[Ljava.lang.String;@4e25154f
[[I@7852e922]
[a, b, c]
第九讲 数组的反射应用
要求:将数拆分打印
代码示例:
a
b
c
xyz
第三部分 反射的其他应用
3.1 ArrayList_HashSet的比较以及Hastcode分析
***面试题:hashCode方法的作用 (java中有内存泄露么,有)
泄露,例如某对象没有在被使用,但是却一直占用内存
注意:
(1)通常来说,一个类的两个实例对象用equals()方法比较的结果相等时,它们的哈希码也必须相等,但反之
则 不成立,即equals方法比较结果不相等的对象可以有相同的哈希码,或者说哈希码相同的两个对象的equals方法比较
结果可以不等,例如,字符串“BB”和"Aa"的equals方法比较结果肯定不相等,但它们的hashCode方法返回值却相等。
(2)当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,
对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,这种情况下,即使在contains方法使用该对象的
当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HasheSet集合中单独删除当前对象,
从而造成内存泄露。
3.2 框架的概念及用反射技术开发框架的原理
框架已经建好,需要调用别人写的类,如何实现:
1、自己去调用别人的类2、别人的类来调用你举例:(1)我盖房子卖给用户住,由用户自己安装门窗和空调,
我做的房子就是框架,用户需要使用我的框架,把门窗插入我提供的框架中。框架与工具类有区别,工具类被用户的类
调用,而框架则是调用用户提供的类。
2、我在写框架(房子)时,你这个用户可能还在上小学,还不会写程序呢?我写的框架程序怎样能调用到
你以后写的类(门窗)呢?因为在写程序是无法知道要被调用的类名,所以,在程序中无法直接new某个类的石磊对象了,
而要用反射方式来做。
综合案列:
先直接用new语句创建ArrayList和HashSet的实例对象,演示用eclipse自动生成ReflecPoint类的equals和
hashcode方法,比较两个集合的运行结果差异。然后改用采用配置文件夹反射的方式创建ArrayList和HashSet的实例对象,
比较观察结果差异。引入eclipse对资源文件的管理方式的讲解即不要出现具体的类的名字HashSet框架一:
将程序要调用的类,放到配置文件中去
运行结果:
2
在Package Explorer——config.properties添加className= java.util.ArrayList,运行结果为4
附录 程序完整代码
----------
第一部分 Java反射基础
1.1 如何得到字节码
1、类名.class ,列入System.class
2、对象.getClasss(),得到对象所属的字节码
3、Class.forName("类名")(面试题)
Class.forName("java.lang.String"),
加载字节码方式:
(1)这份字节码曾经被加载过,已经存在于JDK(JAVA 虚拟机)中,可以直接返回
(2)JDK还没有这份字节码,用类加载器加载,加载后缓存在虚拟机,
1.2 八个基本类型加上void.class构成九个预定义Class对象
只要是在源程序中出现的类型,都有自己的Class实例对象,例如,int[], void...
1.3 反射就是把java中的各种成分映射成响相应的java类
1.4 反射会导致性能下降
代码示例:
<span style="font-size:18px;"> String str1="abc"; Class cls1 = str1.getClass(); Class cls2 = String.class; Class cls3 = Class.forName("java.lang.String"); //字节码相同为真 System.out.println(cls1 == cls2); System.out.println(cls1 == cls3); System.out.println(cls1.isPrimitive()); //是否为基本原始字节码 System.out.println(int.class.isPrimitive()); System.out.println(int.class ==Integer.class); System.out.println(int.class == Integer.TYPE); //数组是否为基本类型 System.out.println(int[].class.isPrimitive()); //是否为数组 System.out.println(int[].class.isArray());</span>
运行结果:
true
true
false
true
false
true
false
true
第二部分 Java反射的基本应用
2.1 构造方法的反射
代码示例:
<span style="font-size:18px;"> //用反射方式实现,new Strig(new StingBuffer("abc")) //注意:编译的时候只是翻译成二进制代码,只看代码的定义,不看代码的执行 Constructor constructor1 = String.class.getConstructor(StringBuffer.class); //注意:得到方法时需要类型 //以下代码错误,因为会导致argument type mismatch,因为constructor1接受的是StringBuffer类型的变量 //String str2 = (String)constructor1.newInstance("abc"); String str2 = (String)constructor1.newInstance(/*"abc"*/new StringBuffer("abc"));//注意:调用方法,需要传递同样类型的对象 System.out.println(str2.charAt(2));</span>运行结果:
c
2.2 成员变量的反射
经典比喻;人在黑板上画圆(圆的动作);司机刹车(车的动作);人关门(门的动作)
静态方法调用不需要对象,因此看到不需要对象调用的方法(第一个参数为null,method为静态方法),为静态方法
注意:jdk1.4 需要没有可变参数方法,需要将参数打包成参数数组
代码示例:
<span style="font-size:18px;"><span style="font-size:18px;"> ReflectPoint pt1 = new ReflectPoint(3,5); //只能获取共有变量 Field fieldY = pt1.getClass().getField("y"); //fieldY的值是多少?是5,错!fieldY不是对象身上的变量,而是类上, //要用他去取某个对象上对应的值 System.out.println(fieldY.get(pt1)); //可以获取共有和私有变量 Field fieldX = pt1.getClass().getDeclaredField("x"); //暴力反射, fieldX.setAccessible(true); System.out.println(fieldX.get(pt1));</span></span>
运行结果:
5
3
2.3 成员方法的反射
代码示例:
<span style="font-size:18px;"><pre name="code" class="java" style="font-size:18px;"> changeStringValue(pt1); System.out.println(pt1);</span>
<span style="font-size:18px;"><pre name="code" class="java"> Method methodCharAt = String.class.getMethod("charAt", int.class); System.out.println(methodCharAt.invoke(str1,1)); //jdk1.4版本写法 System.out.println(methodCharAt.invoke(str1,new Object[]{2}));</span>
<span style="font-size:18px;">//应用反射,替换字符串中的某个字符</span>
<span style="font-size:18px;">private static void changeStringValue(Object obj) throws Exception{ Field[] fields = obj.getClass().getFields(); for(Field field : fields){ //如果使用equals,则语意上不准确 //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); } } }<pre name="code" class="java"> </span>
运行结果:
<span style="font-size:18px;"><pre name="code" class="java">aall:aasketaall:itcast b c</span>
2.4 对接受数组参数的成员方法进行反射
自己写程序,调用封装的main方法
代码示例:
<span style="font-family:SimSun;"> //使用静态代码调用静态方法 //TestArguments.main(new String[] {"111","222","333"}); String startingClassName = args[0];</span>
<span style="font-family:SimSun;"> <span style="color:#ff0000;">//反射方法调用,右键—Run As—Run Configuration—Arguments,添加类的完整名称,此处为TestArguments</span> Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class); //下面这句话错误,JDK1.5,为了兼容1.4,将数组看成是三个参数 //mainMethod.invoke(null, new String[] {"111","222","333"}); //第一种解决方案 // mainMethod.invoke(null, new Object[] {new String[] {"111","222","333"}}); //第二种解决方案,不要拆包 mainMethod.invoke(null,(Object)new String[] {"111","222","333"}); </span>
<span style="font-size:18px;"><span style="font-family:SimSun;">class TestArguments{ public static void main(String[] args){ for (String arg : args){ System.out.println(arg); } }</span><span style="font-family:FangSong_GB2312;"> }</span></span>运行结果:
111 222 333
2.5 数组与Object的关系及其反射类型
代码示例:
int [] a1 = new int[3]; int [] a2 = new int[4]; int [][] a3 = new int[2][4]; String [] a4 = new String[] {"a","b","c"}; //System.out.println(a1.getClass() == a2.getClass()); //System.out.println(a1.getClass() == a4.getClass()); //System.out.println(a1.getClass() == a3.getClass()); System.out.println(a1.getClass().getName()); System.out.println(a1.getClass().getSuperclass().getName()); System.out.println(a4.getClass().getSuperclass().getName()); Object aObj1 = a1; Object aObj2 = a4; //编译不能通过 //Object[] aObj3 = a1; Object[] aObj4 = a3; Object[] aObj5 = a4; System.out.println(a1); System.out.println(a4); System.out.println(Arrays.asList(a1)); System.out.println(Arrays.asList(a4));运行结果:
[I
java.lang.Object
java.lang.Object
[I@7852e922
[Ljava.lang.String;@4e25154f
[[I@7852e922]
[a, b, c]
第九讲 数组的反射应用
要求:将数拆分打印
代码示例:
printObject(a4); printObject("xyz");
private static void printObject(Object obj){ Class clazz = obj.getClass(); //Array为数组反射类 if(clazz.isArray()){ int len = Array.getLength(obj); for(int i=0;i<len;i++){ System.out.println(Array.get(obj,i)); } }else{ System.out.println(obj); } }运行结果:
a
b
c
xyz
第三部分 反射的其他应用
3.1 ArrayList_HashSet的比较以及Hastcode分析
***面试题:hashCode方法的作用 (java中有内存泄露么,有)
泄露,例如某对象没有在被使用,但是却一直占用内存
注意:
(1)通常来说,一个类的两个实例对象用equals()方法比较的结果相等时,它们的哈希码也必须相等,但反之
则 不成立,即equals方法比较结果不相等的对象可以有相同的哈希码,或者说哈希码相同的两个对象的equals方法比较
结果可以不等,例如,字符串“BB”和"Aa"的equals方法比较结果肯定不相等,但它们的hashCode方法返回值却相等。
(2)当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,
对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,这种情况下,即使在contains方法使用该对象的
当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HasheSet集合中单独删除当前对象,
从而造成内存泄露。
3.2 框架的概念及用反射技术开发框架的原理
框架已经建好,需要调用别人写的类,如何实现:
1、自己去调用别人的类2、别人的类来调用你举例:(1)我盖房子卖给用户住,由用户自己安装门窗和空调,
我做的房子就是框架,用户需要使用我的框架,把门窗插入我提供的框架中。框架与工具类有区别,工具类被用户的类
调用,而框架则是调用用户提供的类。
2、我在写框架(房子)时,你这个用户可能还在上小学,还不会写程序呢?我写的框架程序怎样能调用到
你以后写的类(门窗)呢?因为在写程序是无法知道要被调用的类名,所以,在程序中无法直接new某个类的石磊对象了,
而要用反射方式来做。
综合案列:
先直接用new语句创建ArrayList和HashSet的实例对象,演示用eclipse自动生成ReflecPoint类的equals和
hashcode方法,比较两个集合的运行结果差异。然后改用采用配置文件夹反射的方式创建ArrayList和HashSet的实例对象,
比较观察结果差异。引入eclipse对资源文件的管理方式的讲解即不要出现具体的类的名字HashSet框架一:
将程序要调用的类,放到配置文件中去
<span style="font-size:18px;">import java.util.Collection; import java.util.HashSet; import java.util.Properties; </span>
<span style="font-size:18px;">public class ReflectTest2 { /** * @param args */ public static void main(String[] args) throws Exception{ // TODO Auto-generated method stub //加载操作文件 InputStream ips = new FileInputStream("config.properties"); //在Package Explorer——config.properties添加className= java.util.HashSet Properties props = new Properties(); props.load(ips); //关闭对象关联的系统资源,而不是关闭对象,对象是由垃圾回收机管理 ips.close(); String className = props.getProperty("className"); Collection collections = (Collection)Class.forName(className).newInstance(); //ArrayList打印结果为4 //Collection collections = new ArrayList(); //Collection collections = new HashSet();; ReflectPoint pt1 = new ReflectPoint(3,3); ReflectPoint pt2 = new ReflectPoint(5,5); ReflectPoint pt3 = new ReflectPoint(3,3); collections.add(pt1); collections.add(pt2); collections.add(pt3); collections.add(pt1); //修改hashCode值,无法删除,程序运行结果 //pt1.y = 7; //collections.remove(pt1); System.out.println(collections.size()); } } </span>
运行结果:
2
在Package Explorer——config.properties添加className= java.util.ArrayList,运行结果为4
附录 程序完整代码
</pre><pre name="code" class="java"><span style="font-size:18px;"><strong>ReflectTest.java</strong></span>
<pre name="code" class="java"><span style="font-size:18px;">import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; public class ReflectTest { /** * @param args */ public static void main(String[] args) throws Exception{ // TODO Auto-generated method stub String str1="abc"; Class cls1 = str1.getClass(); Class cls2 = String.class; Class cls3 = Class.forName("java.lang.String"); //字节码相同为真 System.out.println(cls1 == cls2); System.out.println(cls1 == cls3); System.out.println(cls1.isPrimitive()); //是否为基本原始字节码 System.out.println(int.class.isPrimitive()); System.out.println(int.class ==Integer.class); System.out.println(int.class == Integer.TYPE); //数组是否为基本类型 System.out.println(int[].class.isPrimitive()); //是否为数组 System.out.println(int[].class.isArray()); //用反射方式实现,new Strig(new StingBuffer("abc")) //编译的时候只是翻译成二进制代码,只看代码的定义,不看代码的执行 Constructor constructor1 = String.class.getConstructor(StringBuffer.class);//注意:得到方法时需要类型 //以下代码会导致argument type mismatch,因为constructor1接受的是StringBuffer类型的变量 //String str2 = (String)constructor1.newInstance("abc"); String str2 = (String)constructor1.newInstance(/*"abc"*/new StringBuffer("abc"));//注意:调用方法,需要传递同样类型的对象 System.out.println(str2.charAt(2)); ReflectPoint pt1 = new ReflectPoint(3,5); //只能获取共有变量 Field fieldY = pt1.getClass().getField("y"); //fieldY的值是多少?是5,错!fieldY不是对象身上的变量,而是类上, //要用他去取某个对象上对应的值 System.out.println(fieldY.get(pt1)); //可以获取共有和私有变量 Field fieldX = pt1.getClass().getDeclaredField("x"); //暴力反射, fieldX.setAccessible(true); System.out.println(fieldX.get(pt1)); changeStringValue(pt1); System.out.println(pt1); Method methodCharAt = String.class.getMethod("charAt", int.class); System.out.println(methodCharAt.invoke(str1,1)); //jdk1.4版本写法 System.out.println(methodCharAt.invoke(str1,new Object[]{2})); //使用静态代码调用静态方法 //TestArguments.main(new String[] {"111","222","333"}); String startingClassName = args[0]; Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class); //下面这句话错误,JDK1.5,为了兼容1.4,将数组看成是三个参数 //mainMethod.invoke(null, new String[] {"111","222","333"}); //第一种解决方案 // mainMethod.invoke(null, new Object[] {new String[] {"111","222","333"}}); //第二种解决方案,不要拆包 mainMethod.invoke(null,(Object)new String[] {"111","222","333"}); //第八讲 数组与Object的关系及其反射类型 int [] a1 = new int[3]; int [] a2 = new int[4]; int [][] a3 = new int[2][4]; String [] a4 = new String[] {"a","b","c"}; //System.out.println(a1.getClass() == a2.getClass()); //System.out.println(a1.getClass() == a4.getClass()); //System.out.println(a1.getClass() == a3.getClass()); System.out.println(a1.getClass().getName()); System.out.println(a1.getClass().getSuperclass().getName()); System.out.println(a4.getClass().getSuperclass().getName()); Object aObj1 = a1; Object aObj2 = a4; //编译不能通过 //Object[] aObj3 = a1; Object[] aObj4 = a3; Object[] aObj5 = a4; System.out.println(a1); System.out.println(a4); System.out.println(Arrays.asList(a1)); System.out.println(Arrays.asList(a4)); printObject(a4); printObject("xyz"); } //数组反射,如何得数组中元素的类型,(目前没有办法),但可以得到某一个元素的类型 //做框架时,可以引用到以上知识 private static void printObject(Object obj){ Class clazz = obj.getClass(); //Array为对数组反射类 if(clazz.isArray()){ int len = Array.getLength(obj); for(int i=0;i<len;i++){ System.out.println(Array.get(obj,i)); } }else{ System.out.println(obj); } } private static void changeStringValue(Object obj) throws Exception{ Field[] fields = obj.getClass().getFields(); for(Field field : fields){ //如果使用equals,则语意上不准确 //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 TestArguments{ public static void main(String[] args){ for (String arg : args){ System.out.println(arg); } } } </span>
<pre name="code" class="java"><span style="font-size:18px;"><strong>ReflectPoint.java</strong></span>
<span style="font-size:18px;">public class ReflectPoint { private int x; public int y; public String str1 = "ball"; public String str2 = "basketball"; public String str3 = "itcast"; public ReflectPoint(int x, int y) { super(); this.x = x; this.y = y; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + x; result = prime * result + y; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ReflectPoint other = (ReflectPoint) obj; if (x != other.x) return false; if (y != other.y) return false; return true; } @Override public String toString(){ return str1 + ":" + str2 + ":" + str3; } } </span>
<span style="font-size:18px;"></span><pre name="code" class="java"><strong>ReflectText2.java</strong>
import java.io.*; import java.util.Collection; import java.util.HashSet; import java.util.Properties; public class ReflectTest2 { /** * @param args */ public static void main(String[] args) throws Exception{ // TODO Auto-generated method stub //加载操作文件 InputStream ips = new FileInputStream("config.properties"); Properties props = new Properties(); props.load(ips); //关闭对象关联的系统资源,而不是关闭对象,对象是由垃圾回收机管理 ips.close(); String className = props.getProperty("className"); Collection collections = (Collection)Class.forName(className).newInstance(); //ArrayList打印结果为4 //Collection collections = new ArrayList(); //Collection collections = new HashSet();; ReflectPoint pt1 = new ReflectPoint(3,3); ReflectPoint pt2 = new ReflectPoint(5,5); ReflectPoint pt3 = new ReflectPoint(3,3); collections.add(pt1); collections.add(pt2); collections.add(pt3); collections.add(pt1); //修改hashCode值,无法删除 pt1.y = 7; collections.remove(pt1); System.out.println(collections.size()); } }
相关文章推荐
- Java基础面试题笔记(1)
- java面试题和答案
- 【转】 一个fork的面试题
- 最近面试的总结与准备
- 面试题10:二进制中1的个数(转载)P81
- Android面试总结2
- 黑马程序员——Java语言--集合框架
- 自己动手丰衣足食之完数_黑马程序员
- zjtd 2016面试
- 从程序员到CTO的Java技术路线图 (转自安卓巴士)
- Android面试题总结
- 这些幽默只有程序员才懂?
- 面试感悟——dmall
- Android 面试题目01
- 乱序不重复整数数组求中位数
- 搜狐面试心得
- 有人认为,“中文编程”, 是解决中国程序员编程效率一个秘密武器,请问它是一个 “银弹” 么?
- 有人认为,“中文编程”是解决中国程序员编程效率的秘密武器,请问它是一个“银弹”么?
- Hibernate面试题及答案
- P117、面试题18:树的子结构