黑马程序员——反——射
来源:互联网 发布:雅思网络课程百度云 编辑:程序博客网 时间:2024/05/17 02:33
---------------------- 黑马程序员 Android培训、期待与您交流! ----------------------
Class类
/*
* 对比提问:众多的人用一个什么类表示?众多的Java类用一个什么类表示?
* class
* Class-->代表一类什么样的事物?
*
* Person p1 = new Person();
* Person p2 = new Person();
*
* Date
*
* Math
*
*
* Class cls1 = Date.class//字节码1--->获取Date数据类的字节码
* Class cls2 = Person.class//字节码2--->获取Person类的字节码
*
* //获取p1这个对象的字节码
* p1.getClass();
*
* //通过指定路径获取字节码
* Class.forName("java.lang.String");
*
* 面试题:Class.forName的作用?
* 答:它的作用是返回字节码,返回的方式有两种:
* 1.第一种是这个字节码曾经被加载过,已经待在Java虚拟机里面了,直接返回
* 2.第二种是Java虚拟机里面还没有这份字节码,则用加载器加载,
* 把加载进来的代码缓存到虚拟机里面,以后要得到这份字节码就不用加载了
*
* 如何得到各个字节码对应的实例对象( Class类型)
* 类名.class,例如,System.class
* 对象.getClass(),例如,new Date().getClass()
* Class.forName("类名"),例如,Class.forName("java.util.Date");
*
* 总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int[],void…
* isPrimitive:判断数据是否为基本数据类型:大概自己的理解。例如:132,如果是基本数据类型,那就定义一个int接收它。
* 判断基本类型的字节码是否为同一基本类型
* 基本数据类型只有那么8种而已: byte,short,int,long,float,double,char,boolean
*/public class _05_Class类概述 { public static void main(String[]args)throws Exception{ String str = "abc"; //获取字节码 Class cls1 = str.getClass(); Class cls2 = String.class; Class cls3 = Class.forName("java.lang.String"); System.out.println("cls1与cls2的字节码相同吗?"+(cls1==cls2)); System.out.println("cls1与cls3的字节码相同吗?"+(cls1==cls3)); //总结:获取到的String类的字节码是相同的 //判断基本类型的字节码是否为同一基本类型 //基本数据类型只有那么8种而已: byte,short,int,long,float,double,char,boolean System.out.println("cls1获取的字节码是一个基本类型吗?"+cls1.isPrimitive()); System.out.println("int类型的字节码是一个基本类型吗?"+int.class.isPrimitive()); System.out.println("int类字节码和Integer类字节码是一个基本类型吗?"+(int.class == Integer.class)); System.out.println("int类字节码和Integer.TYPE包装类的基本类型字节码是一个基本类型吗?"+(int.class == Integer.TYPE)); System.out.println("int数组类型的字节码是一个基本类型吗?"+int[].class.isPrimitive()); System.out.println("一个int[]类型的数组,是一个数组文件吗?"+int[].class.isArray()); } }
反射
lConstructor类
* Constructor的两个步骤(记住)
* 1. 获取方法(获取参数类型的字节码) :指定参数类型
* Constructor constructor = String.class.getConstructor(StringBuffer.class);
* 2. 调用方法:newInstance实例化,并指定参数类型的具体参数:如向StringBuffer中添加参数
* String str = (String)constructor.newInstance(new StringBuffer("abc"));
* ----------------------------------------------------------------------------
* 记住::::反射会导致程序性能严重下降
* ----------------------------------------------------------------------------
* Class.newInstance方法与constructor.newInstance构造方法的区别?
* Class.newInstance方法并不影响Java开发和应用,但是为什么提供这个方法呢?
* 是提供一个便利,我们创建对象步骤是:class-->constructor--new Object
* Constructor constructor = String.class.getConstructor(StringBuffer.class);
*
* 它帮我们将中间的步骤省略了,直接帮我们在内部完成了new Object对象
* 举例:你想喝可乐,每天找我买,那么我就想我直接卖你可乐
*
* Class.newInstance()方法,它就是在找那个不带参数的构造方法。Instance-->实例、实体
* 然后用那个构造方法去创建实例对象(假如我们正好用那个不带参数的构造方法,
* 那么我就可以直接用class.newInstance()方法,这样可以省点事儿)
*
* 该方法内部的具体代码是怎样写的呢?
* 用到了缓存机制来保存默认构造方法的实例对象。
*/
public class _05_1Constructor构造方法 {public static void main(String[]args)throws Exception{//new String(new StringBuffer("abc"));//调取String类的哪个构造方法(参数类型...)JDK1.5新特性,可接受可变参数类型Constructor constructor = String.class.getConstructor(StringBuffer.class);//Constructor constructor = String.class.newInstance("这里放无参数构造方法");//传进去一个对象。//(上面的StringBuffer是调用哪个构造方法,下面的是往调用的对象里面传入一个对象,上下必须保持一致)//注意:需要对接收类型进行强转。因为newInstance的返回值类型是ObjectString str = (String)constructor.newInstance(new StringBuffer("abc"));//求String的第2个字符System.out.println(str.charAt(2));}}
Field类(成员变量)
/*
* 反射:解析
* 例如一个对象中,有很多String类型的成员变量。我们想对String类型变量进行某个字符替换(如将所有String类型的'b'字母替换成'a'),
* 那么我们就用反射,获取这个对象中Field类中的String成员变量,通过数组接收,得到类的字节码
* 然后进行遍历,先判断,获取到的field数组是否为String.class类型的,
* 如果是,通过(String)Sfield.get(obj)方法获取字节码,
* 然后,进行替换,再将替换后的,通过field.set方法进行更新
*
*
* Field类代表某个类中的一个成员变量
* getClass();得到类的字节码
* getField();得到类中的某个成员字段
* getDeclaredField();对私有的x变量,进行获取
* setAccessible(true);强行设置访问(这就叫做“暴力反射”)
*/
import java.lang.reflect.Field;import java.lang.reflect.Method;public class _06_Field反射 {private static Object str1;public static void main(String[]args)throws Exception{ReflectPoint p = new ReflectPoint(3,5);//获取Person类中的某个成员变量的字段//1.先得到类的字节码p.getClass()//2.然后再得到类中的某个成员字段.getField("y");Field fY = p.getClass().getField("y");//fY的值是多少?是5,错!!//fY获取的不是对象身上的变量,而是类上,要用它去取某个对象上对应的值//fY不代表具体变量的值,它只是获取到对象的字段//想要获取对象的具体值,System.out.println(fY.get(p));//通过get获取具体对象身上的值//Field fX = p.getClass().getField("x");//通过getDeclaredField()方法,对私有的x变量,进行获取Field fX = p.getClass().getDeclaredField("x");fX.setAccessible(true);//强行设置访问(这就叫做“暴力反射”)System.out.println(fX.get(p));/* ------------------------------------- * 通过反射,将字符串中所有的b 替换成 a * ------------------------------------- */changStringValue(p);//传进来一个对象System.out.println(p);}private static void changStringValue(Object obj) throws Exception{//通过成员变量数组,获取传入对象的变量 Field[] fields = obj.getClass().getFields();//进行迭代for(Field field : fields){//使用equals与==的区别//field.getType().equals(String.class)//通过字段本身类型与String类型相比较,因为都是字节码,所以使用==if(field.getType()==String.class){String oldValue = (String)field.get(obj); //获取对象中的字节码String newValue = oldValue.replace('b', 'a');//进行替换field.set(obj, newValue);//通过field进行更新}}}}
Method类(方法)
public class _07_反射Method {public static void main(String[]args) throws Exception{/* ------------------------------------- * 通过反射,获取方法Method * ------------------------------------- */String str = "abc";Method methodCharAt = String.class.getMethod("CharAt",int.class);System.out.println(methodCharAt.invoke(str, 1));//如果传递给Method对象的invoke()方法的第一个参数为null,这有着什么样的意义呢?// 说明该Method对象对应的是一个静态方法!System.out.println(methodCharAt.invoke(null, 1));//System.out.println(methodCharAt.invoke(str, new Object[](2)));}}
数组的反射
package cn.itcast.day1;import java.lang.*;import java.lang.reflect.Array;import java.util.Arrays;public class _09_Array数组 {public static void main(String[] args) throws Exception{int[] a1 = new int[]{1,2,3};int[] a2 = new int[4];int[][] a3 = new int[2][3];String []a4 = new String[]{"a","b","c"};System.out.println(a1.getClass()==a2.getClass());System.out.println(a1.getClass()==a2.getClass());//System.out.println(a1.getClass()==a3.getClass());System.out.println(a1.getClass().getName());//结果:[I [代表数组 I代表整数intSystem.out.println(a1.getClass().getSuperclass().getName());//父类名System.out.println(a4.getClass().getSuperclass().getName());Object o1 = a1;Object o2 = a4;//Object[] o3 = a1;错误Object[] o4 = a3;Object[] o5 = a4;System.out.println(a1);System.out.println(a4);//数组转成集合进行输出System.out.println(Arrays.asList(a1));System.out.println(Arrays.asList(a4));//数组的反射应用printObject(a4);printObject("ab");}private static void printObject(Object obj) {Class clazz = obj.getClass();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);}}}
内省
定义一个可以用JavaBean操作的类
public class ReflectPoint {private int x;public int y;private Date birthday = new Date();public int getX() {return x;}public void setX(int x) {this.x = x;}public int getY() {return y;}public void setY(int y) {this.y = y;}public String str1 = "basket";public String str2 = "badseber";public String str3 = "itcast";public ReflectPoint(int x, int y) {super();this.x = x;this.y = y;}//覆盖toString方法public String toString(){return str1+"::"+str2+"::"+str3;}}
JavaBean代码块
/* * 内省:IntroSpector --> JavaBean --> 特殊的Java类 * JavaBean的属性是根据其中的setter和getter方法来确定的, * 而不是根据其中的成员变量。如果方法名为setId,中文意思即为设置id * 去掉set前缀,剩余部分就是属性名,如果剩余部分的第二个字母是小写的, * 则把剩余部分的首字母改成小的。 * * class Person * { * private int x; * public int getAge(){return x;} * public void setAge(int age){return this.x = age} * } * setId 属性名 Id * setCPU 属性名 CPU * * PropertyDecriptor: 属性描述 * * 小技巧:使用重构 * * */public class _12_内省IntroSpector {public static void main(String[] args)throws Exception {// TODO Auto-generated method stubReflectPoint pt1 = new ReflectPoint(3,5);String propertyName = "x";//x-->X--getX--MethodGetX//使用内省方式获取,接收的参数为:属性名,获取某个类的属性信息xxx.getClass()PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass());//得到了JavaBeen属性信息,就可以得到getSet方法Method methodGetX = pd.getReadMethod();//只读方法//通过反射Method.invoke方法获取类型Object retValue = methodGetX.invoke(pt1);System.out.println(retValue);//Set方法,为X重新赋值Method methodSetX = pd.getWriteMethod();methodSetX.invoke(pt1,7);System.out.println(pt1.getX());}//内省复杂方法public static void JavaBean() throws IntrospectionException{ReflectPoint pt1 = new ReflectPoint(3,5);String str = "x";//1.获取Bean内省的所有字段信息BeanInfo info = Introspector.getBeanInfo(pt1.getClass());//2.接收所有信息的属性PropertyDescriptor[] pds = info.getPropertyDescriptors();//3.进行遍历for(PropertyDescriptor pd : pds){if(pd.getClass().equals(str.getClass())){Method m = pd.getReadMethod();Object obj = m.invoke(pt1);break;}}}
使用BeanUtils包
* Jar包为我们提供了方便,可以直接调用里面的功能。
* 怎么找工具包?
* 找到里面最大的Jar包就是我们需要的工具包。
*
* 如何导入Jar包?
* 最好将Jar包放到工程内部,以免发给其它人导致缺包的现象。
* 1.在工程项目上点击右键,选择Folder-->命名lib
* 2.将选中的Jar包粘贴到lib文件夹中
* 3.选中工具包创建Build Path路径(Add to Build Path)
*
* 4.将工具包日志也粘贴到lib文件夹中
public class _13_使用BeanUtils工具包操作JavaBean {public static void main(String[] args) throws Exception {// TODO Auto-generated method stubReflectPoint pt1 = new ReflectPoint(3,5);//参数解析(操作哪个对象,对象的某个属性,要替换的值)//注意:要替换的类型为String类型"9"//BeanUtils是将对象以字符串的形式操作的BeanUtils.setProperty(pt1, "x","9");/* * java7的新特性 Map集合可以这样定义 * Map map = {name :"zxx",age:18}; *///将Map集合中的name属性,替换为lhm//BeanUtils.setProperty(map,"name","lhm");//将对象中的生日的时间,替换为111毫秒//birthday.time;相当于人有脑袋,脑袋上有眼珠,眼珠的颜色是黄色BeanUtils.setProperty(pt1, "birthday.time", "111");//System.out.println(BeanUtils.getProperty(pt1,"birthday.time"));BeanUtils.getProperty(pt1, "x").getClass();//获取对象属性类型PropertyUtils.setProperty(pt1,"x",9);System.out.println(PropertyUtils.getProperty(pt1,"x").getClass());/* * 总结: * BeanUtils是将对象以字符串的形式操作的 * 而PropertyUtils是以对象本身属性形式操作 */}}
---------------------- 黑马程序员 Android培训、期待与您交流! ----------------------
- 黑马程序员——反——射
- 黑马程序员——Jquery的全选与反选
- 黑马程序员——把反斜杠转换为正斜杠的方法
- 黑马程序员—泛型
- 黑马程序员—多线程
- 黑马程序员—DOM
- 黑马程序员—javabean
- 黑马程序员—xml
- 黑马程序员—多线程
- 黑马程序员—反射
- 黑马程序员—多线程
- 黑马程序员—HTML
- 黑马程序员—反射
- 黑马程序员—泛型
- 黑马程序员—API
- 黑马程序员—代理
- 黑马程序员—多线程
- 黑马程序员—集合
- Java学习--单例设计模式
- C语言的代码内存布局
- 几类脚本的流程控制语句(shell,python,lua)
- 中国省份城市列表(汉字+拼音)
- 访问者模式
- 黑马程序员——反——射
- jquery在两个HTM页面之间跳转传递参数
- 来自西弗吉利亚大学li xin整理的CV代码合集
- linux下exit系统调用流程
- Android应用程序与SurfaceFlinger服务的关系概述和学习计划
- 多线程还是多进程的选择及区别
- Python爬虫之路——简单的网页抓图
- Tagsupport类生命周期
- Android应用程序与SurfaceFlinger服务的连接过程分析