Java反射

来源:互联网 发布:linux创建db2数据库 编辑:程序博客网 时间:2024/06/05 01:52

万事万物皆对象,类也是对象,类是java.lang.Class类的对象

当然  java中静态的成员,普通数据类型不是对象

获取类对象的三种方式:

package Refection1;public class Test1 {    public static void main(String[] args) {    //1Class c1=Person.class;//2Person p=new Person();Class c2=p.getClass();Class c3=null;try {//3c3=Class.forName("Refection1.Person");} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println((c1==c2)+","+(c2==c3));try {//获取类的实例 newInstance:必须要有无参构造方法Person p2=(Person)c3.newInstance();} catch (Exception e) {}}     }class Person{}

动态加载类

①:new出来的对象属于静态加载,需要在编译期间就要加载所有可能用到的资源

(如果有100个功能的话,需要把100个功能需要的资源加载才能运行这段程序而且不能出错一个,而你却只用1个功能)

package Refection2;public class Excel { public void start(){    System.out.println("excel.start");    }}

package Refection2;public class Word {    public void start(){    System.out.println("word.start");    }}

package Refection2;public class Office {       public static void main(String[] args) {       args=new String[1];       //args[0]="Word";       args[0]="Excel";       if("word".equals(args[0])){       //new 对象是静态加载的 编译时刻需要加载所有可能需要用到的资源       Word w=new Word();       w.start();       }       if("Excel".equals(args[0])){       Excel e=new Excel();       e.start();       }}}

②:动态加载类:运行时期加载,需要什么资源加载什么资源

(100个功能的话,需要用到一个功能,也就只需要在运行期间加载该功能所需要的资源,其他功能如果出错也不影响自己的使用)

需要制定一个规范(接口)

package Refection2;public class Word implements OfficeAble{    public void start(){    System.out.println("word.start");    }}
package Refection2;public class Excel implements OfficeAble{ public void start(){    System.out.println("excel.start");    }}

package Refection2;public interface OfficeAble {    public void start();}

package Refection2;public class OfficeBetter {   public static void main(String[] args) {      args=new String[1];      //args[0]="Refection2.Word";      args[0]="Refection2.Excel";   try{   //动态加载类  在运行时刻加载   Class c=Class.forName(args[0]);   //创建该类的实例   OfficeAble oa=(OfficeAble) c.newInstance();   oa.start();   }catch(Exception ex){      }}}

获取对象的类信息:

package Refection3;public class Test {public static void main(String[] args) {// TODO Auto-generated method stubString s="hello world";    //   ClassUtil.printClassMethodMessage(s);     //  ClassUtil.printFieldMessage(s);       ClassUtil.printConMessage(s);}}

package Refection3;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;public class ClassUtil {/** * 获取对象的方法信息 *  一个成员方法就是一个Method对象 *  getMethods()方法获取的是所有的public的函数,包括父类继承而来的 *   getDeclaredMethods()获取的是所有该类自己声明的方法,不问访问权限 * @param obj */public static void printClassMethodMessage(Object obj) {Class c = obj.getClass();System.out.println("Class Name: " + c.getName());Method[] ms = c.getMethods();//c.getDeclaredMethods()for (int i = 0; i < ms.length; i++) {//返回值类型Class returnType = ms[i].getReturnType();System.out.print("返回值类型:"+returnType.getName() + " ");System.out.print("方法名:"+ms[i].getName()+" ");//参数类型System.out.print("参数类型:");Class[] paramTypes = ms[i].getParameterTypes();for (Class class1 : paramTypes) {System.out.print(class1.getName());}System.out.println(")");}}/** * 获取成员变量的信息 */public static void printFieldMessage(Object obj){Class c=obj.getClass();/* * 成员变量也是对象 * java.lang.reflect.Field * Field类封装了关于成员变量的操作 * getFields()方法获取的是所有的public的成员变量的信息 * getDeclaredFields获取的是该类自己声明的成员变量的信息 *///Field[] fs = c.getFields();Field [] fs=c.getDeclaredFields();for(Field field : fs){//得到成员变量的类型的类类型Class fieldType=field.getType();String typeName=fieldType.getName();//得到成员变量的名称String fieldName=field.getName();System.out.println(typeName+" "+fieldName);}}/** * 打印构造函数的信息 */public static void printConMessage(Object obj){Class c=obj.getClass();/* * 构造函数也是对象 * java.lang. Constructor中封装了构造函数的信息 * getConstructors获取所有的public的构造函数 * getDeclaredConstructors得到所有的构造函数 *///Constructor[] cs = c.getConstructors();Constructor[] cs=c.getDeclaredConstructors();for(Constructor constructor:cs){    System.out.print("构造器名称:"+constructor.getName());    Class[] paramTypes=constructor.getParameterTypes();    System.out.print(" 参数列表:");    for(Class class1:paramTypes){    System.out.print(class1.getName()+",");    }    System.out.println(")");}}}

方法反射的基本操作

方法的名称和方法的参数列表才能唯一决定某个方法

package Refection4;import java.lang.reflect.Method;public class MethodDemo1 {public static void main(String[] args) {   //要获取print(int ,int )方法  1.要获取一个方法就是获取类的信息,获取类的信息首先要获取类的类类型A a1 = new A();Class c = a1.getClass();/* * 2.获取方法 名称和参数列表来决定   * getMethod获取的是public的方法 * getDelcaredMethod自己声明的方法 */    try {//Method m =  c.getMethod("print", new Class[]{int.class,int.class});    Method m = c.getMethod("print", int.class,int.class);        //方法的反射操作      //a1.print(10, 20);方法的反射操作是用m对象来进行方法调用 和a1.print调用的效果完全相同        //方法如果没有返回值返回null,有返回值返回具体的返回值    //Object o = m.invoke(a1,new Object[]{10,20});    Object o = m.invoke(a1, 10,20);    System.out.println("==================");    //获取方法print(String,String)             Method m1 = c.getMethod("print",String.class,String.class);             //用方法进行反射操作             //a1.print("hello", "WORLD");             o = m1.invoke(a1, "hello","WORLD");             System.out.println("===================");           //  Method m2 = c.getMethod("print", new Class[]{});                Method m2 = c.getMethod("print");               // m2.invoke(a1, new Object[]{});                m2.invoke(a1);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}      }}class A{public void print(){System.out.println("helloworld");}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());}}

=============================================================================

package com.imooc.reflect;import java.io.BufferedReader;import java.io.InputStreamReader;import java.lang.reflect.Method;public class MethodDemo2 {public static void main(String[] args) {UserService us = new UserService();/* * 通过键盘输入命令执行操作 * 输入update命令就调用update方法 * 输入delete命令就调用delete方法 * ... */try {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));System.out.println("请输入命令:");String action = br.readLine();/*if("update".equals(action)){us.update();}if("delete".equals(action)){us.delete();}if("find".equals(action)){us.find();}*//* * action就是方法名称, 都没有参数--->通过方法的反射操作就会简单很多 * 通过方法对象然后进行反射操作 */Class c = us.getClass();Method m = c.getMethod(action);m.invoke(us);} catch (Exception e) {e.printStackTrace();}}}

package com.imooc.reflect;public class UserService {public void delete(){System.out.println("删除用户");}public void update(){System.out.println("修改用户");}public void find(){System.out.println("查找用户");}}

package com.imooc.reflect;//标准的JavaBean类有私有属性都对应有get/set方法,有无参数的构造方法public class User {private String username;private String userpass;private int age;public User(){}public User(String username, String userpass, int age) {super();this.username = username;this.userpass = userpass;this.age = age;}//get和set方法


请输入命令:
update
修改用户
==============================================================================

package Refection4;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List;public class MethodDemo4 {public static void main(String[] args) {// TODO Auto-generated method stubArrayList list =new ArrayList();      List<String> lists =new ArrayList<>();       lists.add("hello");       Class c1=list.getClass();       Class c2=lists.getClass();       System.out.println(c1==c2);     //反射的操作都是编译之后的操作       /* * c1==c2结果返回true说明编译之后集合的泛型是去泛型化的 * Java中集合的泛型,是防止错误输入的,只在编译阶段有效, * 绕过编译就无效了 * 验证:我们可以通过方法的反射来操作,绕过编译 */       try{       Method m=c2.getMethod("add", Object.class);       m.invoke(lists, 20);       System.out.println(lists.size());       //这时就不能用加强for循环去遍历了       System.out.println(lists);       }catch(Exception ex){              }}}

true
2
[hello, 20]

原创粉丝点击