Java Reflect反射

来源:互联网 发布:什么是数据票和进项票 编辑:程序博客网 时间:2024/05/23 20:37

1.Class类的使用

(1)面向对象世界中,万事万物皆对象

类也是对象,是java.lang.Class的实例对象。

(2)这个对象的表示方法3种

public class ClassDemo1 {public static void main(String[] args) {//Foo的实例对象如何表示Foo foo1 = new Foo();//foo1就表示出来了//第一种表示方式--->实际在告诉我们每个类都有一个隐含的静态成员变量Class class1 = Foo.class;//第二种表示方式--->已经知道该类的对象通过getClass()方法Class class2 = foo1.getClass();//第三种表示方式Class class3 = null;try {class3 = Class.forName("com.slj.reflect.Foo");} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}class Foo{}
(3)可以通过类的类类型来创建该类的实例对象

try {Foo foo = (Foo)class1.newInstance();//这里要强制类型转换} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}


2.Java动态加载类

(1)编译时加载类是静态加载,运行时加载类是动态加载

new 出来的都是静态加载类,一招出错,全盘皆输;

Class c = Class.forName("类的全称")是动态加载类,并不影响编译;

(2)如何用动态加载类来避免静态加载出现的情况

public class OfficeBetter {public static void main(String[] args) {try {Class class1 = Class.forName(args[0]);//args[0]参数代表一个类对象try {OfficeAble oaAble = (OfficeAble)class1.newInstance();//用接口来向上转型,实现多态oaAble.start();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}} catch (ClassNotFoundException e) {e.printStackTrace();}}}

写一个接口OfficeAble,将word 和 excel类分别实现该接口,这样不管word还是excel类自身有问题,都不会影响到整体程序的运行,当需要扩展该程序时,可以编写ppt类实现该接口即可。

3.Java获取方法信息

(1)打印各种类的类类型的名称

public class ClassDemo2 {public static void main(String[] args) {Class class1 = int.class;Class class2 = String.class;Class class3 = double.class;Class class4 = Double.class;Class class5 = Void.class;Class class6 = void.class;System.out.println(class1.getName());System.out.println(class2.getName());System.out.println(class3.getSimpleName());//不包含包名的名称System.out.println(class4.getName());System.out.println(class5.getName());System.out.println(class6.getName());}}
(2)打印类的成员方法信息

public static void printClassMethodsMessage(Object object) {Class c = object.getClass();System.out.println("类的名称是:"+c.getName());/* *Method类,方法对象 *一个成员方法就是一个Method对象 *getMethods()方法获取的是所有的public函数,包括从父类继承而来的 *getDeclaredMethods()获取的是所有该类自己声明的方法,不问访问权限 */Method []methods = c.getMethods();//c.getDeclaredMethods()for (int i = 0; i < methods.length; i++) {//得到方法的返回值类型Class returnType = methods[i].getReturnType();System.out.print(returnType.getName()+" ");//得到方法的名称System.out.print(methods[i].getName()+"(");//获取参数类型-->得到的是参数列表的类型的类类型Class []paramType = methods[i].getParameterTypes();for (Class class1 : paramType) {System.out.print(class1.getName()+",");}System.out.println(")");}}


4.Java获取成员变量和构造函数信息

(1)打印类成员变量的信息

public static void printClassFieldsMessage(Object object) {Class c = object.getClass();/* *成员变量也是对象 *java.lang.reflect.Field *Field类封装了关于成员变量的操作 *getFields()方法获取的是所有的public的成员变量的信息 *getDeclaredFields() *///Field [] fields = c.getFields();Field [] fields = c.getDeclaredFields();for (Field field : fields) {Class fieldType = field.getType();String fieldTypeName = fieldType.getName();String fieldName = field.getName();System.out.println(fieldTypeName +" "+ fieldName);}}

(2)打印类的构造方法信息

public static void printClassConMessage(Object object) {Class c = object.getClass();/* *构造函数也是对象 *java.lang.Constructor中封装了构造函数的信息 *getConstructor()获取所有的public的构造函数 *getDeclaredConstructors()的到所有的构造函数 *///Constructor []constructors = c.getConstructors(); Constructor []constructors = c.getDeclaredConstructors();for (Constructor constructor : constructors) {System.out.print(constructor.getName()+"(");//Class []paramTypes = constructor.getParameterTypes();for (Class class1 : paramTypes) {System.out.print(class1.getName()+",");}System.out.println(")");}}


5.Java方法反射的基本操作

import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class MethodDemo1 {public static void main(String[] args) {A a = new A();Class class1 = a.getClass();//首先获取类的类类型try {/* * 获取方法:名称和参数列表来决定 * getMethod()获取的是public的方法 * getDelcaredMethod()获取的是自己声明的方法 * *///Method method = class1.getMethod("print", int.class,int.class);Method method = class1.getMethod("print", new Class[]{int.class,int.class});//Method method = class1.getMethod("print",String.class,String.class);Method method2 = class1.getMethod("print", new Class[]{String.class,String.class});try {/* *方法的反射操作: *方法的反射操作使用method对象来进行方法的调用 和a.print()调用的效果完全相同  *///method.invoke(a, new Class[]{10,20});method.invoke(a, 10,20);//method.invoke(a, new Class[]{"hello","WORLD"});method2.invoke(a, "hello","WORLD");} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}} catch (NoSuchMethodException e) {e.printStackTrace();} catch (SecurityException e) {e.printStackTrace();}}}class A{public void print(int a ,int b) {System.out.println(a+b);}public void print(String a,String b) {System.out.println(a.toUpperCase()+","+b.toLowerCase());}}


6.Java通过反射了解集合泛型

反射的操作都是编译之后的操作;

Java中集合的泛型,是防止错误输入的,只在编译阶段有效,绕过编译阶段无效;

方法的反射可以绕过编译(呼应第一点一样),所以变异之后集合的泛型是去泛型化的;

import java.lang.reflect.Method;import java.util.ArrayList;public class MethodDemo4 {public static void main(String[] args) {ArrayList list = new ArrayList();ArrayList<String> list2 = new ArrayList<String>();list2.add("hello");//list2.add(20)是错误的Class class1 = list.getClass();Class class2 = list2.getClass();System.out.println(class1 == class2);//反射的操作都是编译之后的操作/* * class1 == class2的结果是true说明编译之后集合的泛型是去泛型化的 * Java中集合的泛型是防止错误输入的,只在编译阶段有效 * 绕过编译就无效了 * 验证:我们可以通过方法的反射来操作,绕过编译 */try {Method method = class2.getMethod("add", Object.class);method.invoke(list2, 100);//绕过编译操作就绕过了泛型System.out.println(list2.size());System.out.println(list2);} catch (Exception e) {e.printStackTrace();} }}
运行结果:

true
2
[hello, 100]

原创粉丝点击