黑马程序员---自学随堂笔记----反射
2015-11-06 11:46
507 查看
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制,总而言之就是把java类中各种成分映射成相应的java类。
获取Class的方法:
有9个预定义的Class对象:
byte ,short,int,long,boolean,char,float,double,void
通过反射获取构造方法,并创建对象:
通过反射获取类中属性:
对应的类:Field Field[]
用反射获取类中的方法:
Method Methos[]
反射实例
获取Class的方法:
public static void getClassDemo() throws ClassNotFoundException { String s = "abcdefg"; "//通过对象的getClass()方法获取字类型的字节码文件" Class c1 = s.getClass(); "//通过类型获取字节码文件" Class c2 = String.class; "/*通过Class.forName()获取字节码文件,若字节码没有加载进内存,就把文件加载进内存,若已经在内存中 则直接取出字节码文件使用,内部是字符串,并且类所在的包也要写上*/" Class c3 = Class.forName("java.lang.String"); System.out.println(c1 == c2);"//true" System.out.println(c1 == c3);"//true" System.out.println(c3 == c2);"//true" System.out.println(c1.getName());"获取类的名称,包括包名" System.out.println(c1.getSuperclass());"直接获取到Object的类,不论它上面有其他什么父类" System.out.println(c1.getModifiers());"最后修改时间" System.out.println(c1.getPackage());"获取包名" System.out.println(c1.getMethods());"获取所有方法,返回Methods[],不包括私有方法" System.out.println(c1.getMethod("charAt", int.class));"获取其中一个方法,指定方法名称,指定方法中参数类型的字节码文件" System.out.println(c1.getFields());"获取所有属性,返回Filed[]" System.out.println(c1.getField("name"));"获取指定属性,并返回Field" System.out.println(c1.isPrimitive());"判断是不是基本数据类型" System.out.println(int.class == Integer.class);"false" System.out.println(int.class == Integer.TYPE);"true" System.out.println(c1.isArray());"判断是不是数组类型" }
有9个预定义的Class对象:
byte ,short,int,long,boolean,char,float,double,void
通过反射获取构造方法,并创建对象:
public static void getConstruct() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException { "//一般创建空参数的对象和有参数的对象" String str = "abc"; String str2 = new String(new StringBuffer("abc")); "/** * 反射创建对象 */ // 获取没有参数的构造方法,并创建对象,然后对对象进行强转" Class c1 = Class.forName("java.lang.String"); String s = (String) c1.newInstance(); "// 获取有参数的构造方法,并创建对象" Class c2 = Class.forName("java.lang.String"); "// 指定构造方法参数的字节码文件,可以通过参数的不同获取不同的构造方法" Constructor<String> con = c2.getConstructor(StringBuffer.class); "// 创建对象,并传入参数" StringBuffer sb = new StringBuffer("abc"); String s1 = (String) con.newInstance(sb); System.out.println(s.getClass() == s1.getClass());"// true是同一个字节码文件" System.out.println(s == s1);"// false不是一个对象" }
通过反射获取类中属性:
对应的类:Field Field[]
public static void getField() throws ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { Persion p = new Persion(10, "lisi"); Class c = Class.forName("Persion.Persion"); "// 获取的是Persion中num这个属性,不会获取他的值" Field f1 = c.getField("num"); "/** * 这里获取的是这个Persion类中num属性,而不是Persion对应的具体的某个对象中的num * 不同对象他们对应的值不同,所以获取值的时候要传入对象,表示要获取那个对象这个属性的值 */" System.out.println(f1.getInt(p)); "// 修改某一个对象这个属性的值" f1.setInt(p, 30); System.out.println(f1.getInt(p)); "// 获取所有的非私有属性,并返回Fiel[]" Field[] f2 = c.getFields(); for (Field f : f2) { System.out.println(f.getName()); } "/** * 获取所有属性,包括私有属性,并返回Fiel[] * c.getDeclaredFields();只是获取所有属性,但是并不能对私有属性进行操作 */" Field[] f3 = c.getDeclaredFields(); for (Field f : f3) { "//f.setAccessible(true);允许对某一个私有属性进行操作," f.setAccessible(true); "//获取属性名称" System.out.println(f.getName()); } }
用反射获取类中的方法:
Method Methos[]
public static void getMethos() throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { Persion p = new Persion(30, "lisi"); Class c = Class.forName("Persion.Persion"); "// 获取方法,传入要获取的方法名,方法中要传入的 参数类型 的字节码文件" Method m1 = c.getMethod("setName", String.class); " cec9 // p这个对象调用SetName这个方法,传入的参数是“张三”" m1.invoke(p, new Object[] { "zhangsan" });"// = p.setName("zhangsan");" "// p这个对象调用getName这个方法,传入的参数是null,不需要参数" Method m2 = c.getMethod("getName", null); System.out.println(m2.invoke(p, null));"// = p.getName();" "//当一个方法是静态方法的时候使用m.invoke(null,'a'),不许要传入对象,因为静态方法不需要对象就能直接调用" "/** * 获取所有的方法,除了私有方法 */" Method[] m3 = c.getMethods(); for (Method m : m3) { System.out.println(m.getName()); } "/** * 获取所有的方法,包括获取私有方法 * c.getDeclaredMethods();获取但不能操作 * m.setAccessible(true);允许操作 */" Method[] m4 = c.getDeclaredMethods(); for (Method m : m4) { m.setAccessible(true); System.out.println(m.getName()); } "/** * 当方法中要传入的参数是数组时,如何传入参数 * 参数类型是数组时候,一般我们会传入:m5.invoke(p,new String[] { "1", "2", "3", "4" }); * java 1.5之前传入的参数是数组类型,也就是把多个参数都封装到一个数组中传入,数组类型是Object[]类型 * 所以new String[]数组Java虚拟机会直接看成new Object[],这样他会进行对数组进行拆开,然后把里面的元素作为参数传入 * 而java1.5之后可以直接书写多参数,不用封装成new Object[],但是为了兼容1.5之前的版本,当传入的参数是数组类型的时候,会转换成Object[]类型(基本数据类型不能转换成Object[]类型),然后对数组进行拆开,然后把里面的元素当做参数传入,造成错误 * 解决方式: * 1、 (Object) new String[] { "1", "2", "3", "4" }强转 * 2、new Object[] { new String[] { "1", "2", "3", "4" } } * 把new String[]作为参数传入,这样就算拆开数组也不会有问题 * 参数是String[] 要传入String[].class,不能传String * 参数是String 要传入String.class */" Method m5 = c.getMethod("shuzu", String[].class); m5.invoke(p, new Object[] { new String[] { "1", "2", "3", "4" } }); } "/** * 数组的反射 * 具有相同的维度和元素类型相同的数组就是同一种类型,他们的字节码文件相同,Class对象相同 */" int[] a1 = new int[] { 1 }; int[] a2 = new int[2]; int[][] a3 = new int[1][]; String[] a4 = new String[] { "1", "2", "3", "4" }; System.out.println(a1.getClass() == a2.getClass());"// true" System.out.println(a1.getClass()==a3.getClass());"//false" System.out.println(a1.getClass() == a4.getClass());"//false" Object obj1 = a1; Object obj2 = a3; Object obj3 = a4; "// Object[] obj4 = a1;//基本数据类型数据不能用Object[]表示" Object[] obj5 = a3; Object[] obj6 = a4; "/** * 实例: * Arrays.aList(); * 在java1.5之前参数是new Object[] * 在java1.5之后参数是T...a */" System.out.println(Arrays.asList(a1));"// [[I@1acd47]" "// 在反射中,当获取的对象是一个数组时候,可以使用Array(不是Arrays),来操作数组" Class cla = a4.getClass(); if (cla.isArray()) { int len = Array.getLength(a4); System.out.println(Array.get(a4, 2)); }
反射实例
public static void demo() { "// 创建Properties 对象" Properties p = new Properties(); "// 声明FileInputStream对象" FileInputStream fis = null; try { "//读取properties文件" fis = new FileInputStream("c://demo//a.txt"); "//加载数据" p.load(fis); System.out.println(p.getProperty("demo") + " " + p.getProperty("http")); "//获取demo多对应的值,然后创建他类的对象" Class c1 = Class.forName(p.getProperty("demo")); System.out.println(c1.getName()); "//创建这个类的对象,这里使用的接口的类,因为传入的类实现了这个接口,就是这个接口的子类,多态的应用,提高扩展性" Rule r = (Rule) c1.newInstance(); "//获取指定的方法,传入参数类型的字节码文件" Method m = c1.getMethod("down", String[].class, int.class); "//调用类中方法" m.invoke(r, new Object[] { new String[] { p.getProperty("http") }, 1 }); } catch (Exception e) { e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } "//定义接口,其他类实现这个接口" package Persion; public interface Rule { public abstract void down(String[] s, int a); } "自定义类实现Rule 这个接口,利用传入的参数进行操作,可以利用传入的参数做任何操作,这里通过传入的参数获取网络资源,然后复制到指定位置" public class Down implements Rule { @Override public void down(String[] s, int a) { FileOutputStream fos = null; HttpURLConnection conn = null; try { URL url = new URL(s[0]); conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setReadTimeout(3000); conn.connect(); "把.之后的数据截取出来" String regex = "\\.\\w+"; "//创建pattern对象,关联正则表达式" Pattern p = Pattern.compile(regex); "//通过pattern对象和要匹配的字符串关联,返回匹配引擎" Matcher m = p.matcher(s[0]); String name = null; "//不断循环找数据" while (m.find()) { name = m.group(); } fos = new FileOutputStream("c://demo//a" + name); InputStream in = conn.getInputStream(); int len = 0; byte[] by = new byte[1024]; while ((len = in.read(by)) != -1) { fos.write(by, 0, len); fos.flush(); } System.out.println("OK"); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if (conn != null) { conn.disconnect(); } } } }
相关文章推荐
- Java反射随记
- AS3中的反射(速记) 分析
- C# 反射(Reflection)的用处分析
- C#通过反射创建自定义泛型
- 通俗易懂的C#之反射教程
- C#根据反射和特性实现ORM映射实例分析
- 深入反射生成数组的详解
- C#利用反射来判断对象是否包含某个属性的实现方法
- C#利用反射技术实现去掉按钮选中时的边框效果
- C#泛型和反射实例解析
- C# Dynamic关键字之:dynamic为什么比反射快的详解
- 传智播客学习之java 反射
- Java 反射之私有字段和方法详细介绍
- php使用反射插入对象示例分享
- java反射使用示例分享
- java利用反射实现动态代理示例
- 用户控件(ASCX)向网页(ASPX)传值使用反射实现
- 基于Java回顾之反射的使用分析
- c#反射调用方法示例
- C#通过反射获取当前工程中所有窗体并打开的方法