黑马程序员——反射
来源:互联网 发布:阿里云邮企业版下载 编辑:程序博客网 时间:2024/04/30 07:27
------- android培训、java培训、期待与您交流! ----------
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
动态获取类中信息,就是java反射 。可以理解为对类的解剖。
Class类
如果要完成反射,那么必须了解Class类
实例1:通过对象取得包名和类名
package org.siu; class Test { } public class Demo { public static void main(String[]args) { Testt = new Test(); System.out.println(t.getClass()); System.out.println(t.getClass().getName()); }}
在java中,Object类是所有类的父类,同样,所有类的实例化对象也都是Class类的实例
因此,这样一来就会牵扯到向上转型和向下转型的概念
由于向下转型的不安全因素,在这里泛型也会接踵而来
实例2:Class类的实例化
由于Class类没有构造方法,所以实例化Class类的方式有点特殊,有三种方式:
对象.getClass( )
类.Class
forName( )
class Test { } public class Demo { public static void main(String[]args) { //方式一: Testt = new Test(); Class<? extends Test>c1 = t.getClass(); System.out.println(c1); //方式二: //为了避免特殊性,这里不用Test类,而用java库中的String类 Class<String>c2 = String.class; System.out.println(c2); //方式三: //forName()方法会抛出异常 Class<?>c3 = null; try { c3= Class.forName("Test"); } catch (ClassNotFoundExceptione) { e.printStackTrace(); } System.out.println(c3); }}
其中,forName( )方法需要重点掌握,因为它可以在类不确定的情况下实例化Class,更具灵活性
Class类的应用
Class类中有一个方法叫做newInstance(),它可以用来创建一个Class类对象的新实例
怎么说呢?Class对象包含的内容就是反射好的那个类,我们要构造那个类的新实例(新对象)
实例3:Class类的无参构造对象
public class Demo { public static void main(String[]args) { //实例化Class对象,forName()方法会抛异常 Class<?>c = null; try { //这里需要完整的包名和类名 c= Class.forName("java.lang.String"); } catch (ClassNotFoundExceptione) { e.printStackTrace(); } //生成一个字符串的引用 Strings = null; try { //将构造好的对象向下转型为String类 //newInstance()方法会抛异常 s= (String) c.newInstance(); } catch (InstantiationExceptione) { e.printStackTrace(); } catch (IllegalAccessExceptione) { e.printStackTrace(); } System.out.println("字符串长度: " + s.length()); }}
这样就通过无参数的形式构造了一个新的对象,如同正常模式中
通过无参构造方法来构造新对象一样
我们知道,类中除了有无参构造方法,还会存在有参数的构造方法
那在反射中如何通过有参数的形式构造对象呢?接着看
实例4:Class类的有参构造对象
import java.lang.reflect.Constructor; public class Demo { //下面的几个方法抛出来的异常太多,为了代码的紧凑性,这里就直接抛给虚拟机了 public static void main(String[]args) throws Exception { Class<?>c = null; try { c= Class.forName("java.lang.String"); } catch (ClassNotFoundExceptione) { e.printStackTrace(); } char[]ch = {'h','e','l','l','o'}; Strings = null; //获得Class类对象的有参构造方法,括号里面参数的写法是:类型.class Constructor<?>con = c.getConstructor(char[].class); //用此构造方法构造一个新的字符串对象,参数为一个char数组 s= (String) con.newInstance(ch); System.out.println("构造的字符串:" + s); }}
我们还是使用String类做例,因为String类用的比较多,便于理解
这里需要注意的是,构造方法需要使用getConstructor()方法获得
至于参数类型则是:原有类型.class
还有一点,无论是有参还是无参,这里所使用的构造方法,原本的类里面必须对应存在
那么,如何才能知道原有类里面的构造方法,普通方法,继承的父类等详细信息呢?接着看
实例5:取得类的构造方法
获取类的结构
要通过反射获取类的结构我们这里要导入一个新的包java.lang.reflect
import java.lang.reflect.Constructor;import java.util.Arrays; public class Demo { //下面的几个方法抛出来的异常太多,为了代码的紧凑性,这里就直接抛给虚拟机了 public static void main(String[]args) throws Exception { Class<?>c = null; try { c= Class.forName("java.lang.Boolean"); } catch (ClassNotFoundExceptione) { e.printStackTrace(); } //这里的getConstructors()方法返回的是一个Constructor数组 Constructor<?>[]cons = c.getConstructors(); //打印的方式你可以自己写,为了方便我用Arrays.toString(),凑合着看 System.out.println(Arrays.toString(cons)); }}
实例6:取得类所实现的接口
import java.util.Arrays; public class Demo { public static void main(String[]args) throws Exception { Class<?>c = null; try { c= Class.forName("java.lang.Boolean"); } catch (ClassNotFoundExceptione) { e.printStackTrace(); } Class<?>[]in = c.getInterfaces(); System.out.println(Arrays.toString(in)); }}
实例7:取得父类
public class Demo { public static void main(String[]args) throws Exception { Class<?>c = null; try { c= Class.forName("java.lang.Boolean"); } catch (ClassNotFoundExceptione) { e.printStackTrace(); } //注意了,这里不会是数组,why? Class<?>su = c.getSuperclass(); System.out.println(su); }}
实例8:取得类的全部方法
import java.lang.reflect.Method; public class Demo { public static void main(String[]args) throws Exception { Class<?>c = null; try { c= Class.forName("java.lang.Boolean"); } catch (ClassNotFoundExceptione) { e.printStackTrace(); } Method[]m = c.getMethods(); for (int i= 0; i < m.length; i++) { System.out.println(m[i]); } }}
实例9:取得本类的全部属性
import java.lang.reflect.Field; class Person { private Stringname; private int age;} public class Demo { public static void main(String[]args) throws Exception { Class<?>c = null; try { c= Class.forName("Person"); } catch (ClassNotFoundExceptione) { e.printStackTrace(); } Field[]f = c.getDeclaredFields(); for (int i= 0; i < f.length; i++) { System.out.println(f[i]); } }}
实例10:获取本类中属性的值
import java.lang.reflect.Field; class Person { public Stringname; private int age; public Person(Stringname, int age) { this.name= name; this.age= age; }} public class Demo { public static void main(String[]args) throws Exception { Personp = new Person("zhangsan",12); Class<?>c = p.getClass(); //获取公共属性的值 Fieldf1 = c.getField("name"); //get(p)表明要获取是哪个对象的值 Stringstr = (String) f1.get(p); System.out.println("姓名: " + str); //获取私有属性的值 Fieldf2 = c.getDeclaredField("age"); //age是私有属性,所以要设置安全检查为true f2.setAccessible(true); int age= (int) f2.get(p); System.out.println("年龄: " + age); }}
反射的应用
实例11:通过反射修改属性
import java.lang.reflect.Field; class Person { private Stringname; public Person(Stringname) { this.name= name; } public StringtoString() { return "姓名: " + this.name; }} public class Demo { public static void main(String[]args) throws Exception { Personp = new Person("王二狗"); System.out.println(p); Class<?>c = p.getClass(); //定义要修改的属性 Fieldf = c.getDeclaredField("name"); f.setAccessible(true); //修改属性,传入要设置的对象和值 f.set(p, "张二蛋"); System.out.println(p); }}
实例12:通过反射调用方法
import java.lang.reflect.Method; class Person { public void print(int i){ System.out.println("我在写数字: " + i); } public static void say(Stringstr) { System.out.println("我在说: " + str); }} public class Demo { public static void main(String[]args) throws Exception { Personp = new Person(); Class<?>c = p.getClass(); //getMethod()方法需要传入方法名,和参数类型 Methodm1 = c.getMethod("print", int.class); //invoke()表示调用的意思,需要传入对象和参数 m1.invoke(p, 10); Methodm2 = c.getMethod("say", String.class); //这里的null表示不由对象调用,也就是静态方法 m2.invoke(null, "你妹"); }}
实例13:通过反射操作数组
import java.lang.reflect.Array; public class Demo { public static void main(String[]args) throws Exception { int[]arr = {1,2,3,4,5}; Class<?>c = arr.getClass().getComponentType(); System.out.println("数组类型: " + c.getName()); int len= Array.getLength(arr); System.out.println("数组长度: " + len); System.out.print("遍历数组: "); for (int i= 0; i < len; i++) { System.out.print(Array.get(arr,i) + " "); } System.out.println(); //修改数组 System.out.println("修改前的第一个元素: " + Array.get(arr, 0)); Array.set(arr, 0, 3); System.out.println("修改后的第一个元素: " + Array.get(arr, 0)); }}
- 黑马程序员—反射
- 黑马程序员—反射
- 黑马程序员—反射
- 黑马程序员—反射
- 黑马程序员—反射
- 黑马程序员—反射
- 黑马程序员—反射
- 黑马程序员—反射
- 黑马程序员——反射
- 黑马程序员——反射
- 黑马程序员——反射
- 黑马程序员——反射
- 黑马程序员——反射
- 黑马程序员——反射
- 黑马程序员——反射
- 黑马程序员——反射
- 黑马程序员——反射
- 黑马程序员——反射
- 大数据平台搭建之components版本选择
- SpringMVC返回类型
- 如何在一个辅助中修改游戏的可视距离
- .NET陷阱之奇怪的OutOfMemoryException
- Shell脚本基本命令
- 黑马程序员——反射
- git使用时遭遇the authenticity of host can't be established
- Android之异步线程原理
- MATLAB中去掉字符串中的空格,num2str引发的问题
- 大数据平台搭建之nexus私服
- java中long和double类型操作的非原子性探究
- QT5-TableWidget字符串显示
- 分享:“延迟加载与预加载”使用体会
- javascript 语法基础 想学习js的朋友可以看看