反射访问类的私有属性对象的私有方法

一、什么是反射机制 
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为 动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
二、反射机制的优点与缺点  
    静态编译:在编译时确定类型,绑定对象,即通过。 
    动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多 态的应用,有以降低类之间的藕合性。一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中它的灵活性就表现的十分明显。比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。 
     缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。

三、利用反射机制能获得什么信息 
         一句话,类中有什么信息,它就可以获得什么信息,不过前提是得知道类的名字,要不就没有后文了 
    首先得根据传入的类的全名来创建Class对象。 
    Class c=Class.forName("className");注明:className必须为全名,也就是得包含包名,比如,cn.netjava.pojo.UserInfo; 
    Object obj=c.newInstance();//创建对象的实例 。OK,有了对象就什么都好办了,想要什么信息就有什么信息了。   
    获得构造函数的方法 
    Constructor getConstructor(Class[] params)//根据指定参数获得public构造器

    Constructor[] getConstructors()//获得public的所有构造器

    Constructor getDeclaredConstructor(Class[] params)//根据指定参数获得public和非public的构造器

    Constructor[] getDeclaredConstructors()//获得public的所有构造器 

    获得类方法的方法 
    Method getMethod(String name, Class[] params),根据方法名,参数类型获得方法

    Method[] getMethods()//获得所有的public方法

    Method getDeclaredMethod(String name, Class[] params)//根据方法名和参数类型,获得public和非public的方法

    Method[] getDeclaredMethods()//获得所以的public和非public方法 
    获得类中属性的方法 
    Field getField(String name)//根据变量名得到相应的public变量

    Field[] getFields()//获得类中所以public的方法

    Field getDeclaredField(String name)//根据方法名获得public和非public变量

    Field[] getDeclaredFields()//获得类中所有的public和非public方法 

四、用反射机制反射访问类的私有属性对象的私有方法
public class Student {
    private String name;
    private int age;
    private String address;
    public Student() {
        this("张三", 21, "湖北随州");
    }
    public Student(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
    private String getStudentInfo() {
        return "studentInfo: {name:" + name + 
        ", age:" + age + 
        ", address:" + address + "}";
    }
    private void setName(String name) {
        this.name = name;
    }
}
测试代码:
public class ReflectionDemo {
    private Student student;
    public ReflectionDemo() {
        student = new Student();
    }
    public static void main(String[] args) {
        try {
            Class<?> clazz = Class.forName("com.lenovo.dovext.ReflectionDemo");
            // 根据属性名称获取属性的类对象
            Field field = clazz.getDeclaredField("student"); 
            field.setAccessible(true);
            ReflectionDemo reflaction = (ReflectionDemo) clazz.newInstance();
            // 返回reflaction对象上此 Field 表示的字段的值
            Student student = (Student) field.get(reflaction);
            clazz = student.getClass();
            // 根据指定类中的方法名称获取方法的类对象
            Method getMethod = clazz.getDeclaredMethod("getStudentInfo", null);
            getMethod.setAccessible(true);
            // 调用指定对象上此 Method 表示的方法
            String result = (String) getMethod.invoke(student, null);
            System.out.println(result);

            Method setMethod = clazz.getDeclaredMethod("setName", new Class[]{String.class});
            setMethod.setAccessible(true);
            // 调用指定对象上此 Method 对象表示的方法
            setMethod.invoke(student, "联想利泰");

            result = (String) getMethod.invoke(student, null);
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
五、用反射机制实现对数据库数据的增、查例子 

基本原理;保存数据时,把需要保存的对象的属性值全部取出来再拼凑sql语句 
                 查询时,将查询到的数据全部包装成一个java对象。 
    游戏规则:俗话说的好,无规矩不成方圆,特别是程序来说,它只能做有规则的事情,没有规则的它干不了,好,那就 
              先定规则 
              1)数据库的每一个表对象一个pojo类,表中的每一个字段对应pojo类的中的一个属性。 
                 并且pojo类的名字和表的名字相同,属性名和字段名相同,大小写没有关系,因为数据库一般不区分大小写  
              2)为pojo类中的每一个属性添加标准的set和get方法。 
    有了游戏规则,那么开始游戏吧。

1、首先数据库的有一个表,假设数据库名称为:blogsystem,里面的一个表名userinfo。如图:

2、创建对应的pojo类:

package cn.netjava.pojo;
 
public class  UserInfo {
private int  id ;
private String name;
private String pwd;
private int  age;
 
@Override
public String toString() {
     return  "UserInfo [id="  +  id  +  ", name="  +  name +  ", pwd="  +  pwd +  ", age="
             +  age +  "]" ;
}
public int  getId() {
     return  id ;
}
public void setId( int  id ) {
    this. id  =  id ;
}
public String getName() {
     return  name;
}
public void setName(String name) {
    this.name =  name;
}
public String getPwd() {
     return  pwd;
}
public void setPwd(String pwd) {
    this.pwd =  pwd;
}
public int  getAge() {
     return  age;
}
public void setAge( int  age) {
    this.age =  age;
}
 
}

2、编写获得数据库连接的工厂类:
public class  Connect2DBFactory {
    public static Connection getDBConnection() {
        Connection conn =  null;
         try  {
            Class.forName( "com.mysql.jdbc.Driver" );
            String url =  "jdbc: mysql://localhost:3306/blogsystem" ;
            String user =  "root" ;
            String password =  "netjava" ;
            conn =  DriverManager.getConnection(url, user, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
 
         return  conn;
    }
} 

3、好戏开始啦,编写操作数据库的dao类

public class  NetJavaSession {
     /**
      *  解析出保存对象的sql语句
      *
      *  @param object :需要保存的对象
      *  @ return :保存对象的sql语句
      */
    public static String getSaveObjectSql( Object  object ) {
         //  定义一个sql字符串
        String sql =  "insert into " ;
         //  得到对象的类
        Class c =  object .getClass();
         //  得到对象中所有的方法
        Method[] methods =  c.getMethods();
         //  得到对象中所有的属性
        Field[] fields =  c.getFields();
         //  得到对象类的名字
        String cName =  c.getName();
         //  从类的名字中解析出表名
        String tableName =  cName.substring(cName.lastIndexOf( "." ) +  1 ,
                cName.length());
        sql +=  tableName +  "(" ;
         List <String> mList =  new ArrayList<String>();
         List  vList =  new ArrayList();
         for  (Method method : methods) {
            String mName =  method.getName();
             if  (mName.startsWith( "get" ) && !mName.startsWith( "getClass" )) {
                String fieldName =  mName.substring( 3 , mName.length());
                mList.add(fieldName);
                System.out.println( "字段名字----->"  +  fieldName);
                 try  {
                     Object  value =  method.invoke( object , null);
                    System.out.println( "执行方法返回的值:"  +  value);
                     if  (value instanceof String) {
                        vList.add( "\""  +  value +  "\"" );
                        System.out.println( "字段值------>"  +  value);
                    } else  {
                        vList.add(value);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
         for  ( int  i =  0 ; i < mList.size(); i ++ ) {
             if  (i < mList.size() -  1 ) {
                sql +=  mList.get(i) +  "," ;
            } else  {
                sql +=  mList.get(i) +  ") values(" ;
            }
        }
         for  ( int  i =  0 ; i < vList.size(); i ++ ) {
             if  (i < vList.size() -  1 ) {
                sql +=  vList.get(i) +  "," ;
            } else  {
                sql +=  vList.get(i) +  ")" ;
            }
        }
 
         return  sql;
    }
 
    public static List  getDatasFromDB(String tableName, int  Id ) {
 
         return  null;
    }
 
     /**
      *  将对象保存到数据库中
      *
      *  @param object:需要保存的对象
      *  @ return :方法执行的结果; 1 :表示成功, 0 :表示失败
      */
    public int  saveObject( Object  object ) {
        Connection con =  Connect2DBFactory.getDBConnection();
        String sql =  getSaveObjectSql( object );
         try  {
             //  Statement statement = (Statement) con.createStatement();
            PreparedStatement psmt =  con.prepareStatement(sql);
            psmt.executeUpdate();
             return  1 ;
        } catch (SQLException e) {
            e.printStackTrace();
             return  0 ;
        }
    }
 
     /**
      *  从数据库中取得对象
      *
      *  @param arg0:对象所属的类
      *  @param id :对象的 id
      *  @ return :需要查找的对象
      */
    public Object  getObject(String className, int  Id ) {
         //  得到表名字
        String tableName =  className.substring(className.lastIndexOf( "." ) +  1 ,
                className.length());
         //  根据类名来创建Class对象
        Class c =  null;
         try  {
            c =  Class.forName(className);
 
        } catch (ClassNotFoundException e1) {
 
            e1.printStackTrace();
        }
         //  拼凑查询sql语句
        String sql =  "select * from "  +  tableName +  " where Id="  +  Id ;
        System.out.println( "查找sql语句:"  +  sql);
         //  获得数据库链接
        Connection con =  Connect2DBFactory.getDBConnection();
         //  创建类的实例
         Object  obj =  null;
         try  {
 
            Statement stm =  con.createStatement();
             //  得到执行查寻语句返回的结果集
            ResultSet set  =  stm.executeQuery(sql);
             //  得到对象的方法数组
            Method[] methods =  c.getMethods();
             //  遍历结果集
             while  ( set . next ()) {
                obj =  c.newInstance();
                 //  遍历对象的方法
                 for  (Method method : methods) {
                    String methodName =  method.getName();
                     //  如果对象的方法以 set 开头
                     if  (methodName.startsWith( "set" )) {
                         //  根据方法名字得到数据表格中字段的名字
                        String columnName =  methodName.substring( 3 ,
                                methodName.length());
                         //  得到方法的参数类型
                        Class[] parmts =  method.getParameterTypes();
                         if  (parmts[ 0 ] ==  String. class ) {
                             //  如果参数为String类型,则从结果集中按照列名取得对应的值,并且执行改 set 方法
                            method.invoke(obj, set .getString(columnName));
                        }
                         if  (parmts[ 0 ] ==  int . class ) {
                            method.invoke(obj, set .getInt(columnName));
                        }
                    }
 
                }
            }
 
        } catch (Exception e) {
            e.printStackTrace();
        }
         return  obj;
    }
}

4、开始测试效果怎么样:

public class  Tester {
    public static void main(String args[]) {
         // 获得NetJavaSession对象
        NetJavaSession session =  new NetJavaSession();
         // 创建一个UserInfo对象
        UserInfo user =  new UserInfo();
         // 设置对象的属性
        user.setId( 6988 );
        user.setAge( 44 );
        user.setPwd( "pwd" );
        user.setName( "champion" );
         // 将对象保存到数据库中
        String sql =  session.getSaveObjectSql(user);
        System.out.println( "保存对象的sql语句:"  +  sql);
         // 查找对象
        UserInfo userInfo =  (UserInfo) session.getObject(
                 "cn.netjava.pojo.UserInfo" , 6988 );
        System.out.println( "获取到的信息:"  +  userInfo);
 
    }
} 

5、打印出来的结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值