zoukankan      html  css  js  c++  java
  • 反射

    基础概念


    什么是反射

    运行时动态获取类的内部信息的一种方式。

    反射的作用

    1. 可以通过反射机制发现对象的类型,发现类型的方法/属性/构造器

    2. 可以创建对象并访问任意对象方法和属性等

    Class类加载

    类加载到内存:Java将磁盘类文件加载到内存中为一个对象(实例),这个对象是Class类的实例

    Class实例代表Java中的类型

    1. 获得基本类型实例

        int.class

        long.class ....

    2. 获得类类型(Class)实例

        Class cls = String.class;

        Class cls = Class.forName(“java.lang.String”);

        Class cls = “abc”.getClass();

        以上方法获得cls是同一个对象,就是Sting类内存加载的结果

    典型应用

    IDE的提示、JavaBean的拷贝、简单工厂

    通过反射创建对象实例


     案例

    public static Object create(String classname) {
            try{
                // 1、加载类
                Class cls = Class.forName(classname);
                // 2、创建类实例
                Object obj = cls.newInstance();
                return obj;
            }
            catch(Exception e){
                throw new RuntimeException("创建对象失败", e);
            }
    }

    class.forName作用

    要求JVM查找并加载指定的类(加载dao方法区中),也就是说JVM会执行该类的静态代码段。

    当直接new对象实例化后该类的静态代码块也会被执行,但是这样不利于动态读取配置文件创建连接,因此一般都使用Class.forName的形式。

    JDBC加载驱动类

    常见的是JDBC连接数据库的时候加载驱动类。注册一个数据库驱动。class.forname(“oracle.jdbc.driver.OracleDriver”);该代码是加载oracle驱动类,完成驱动的注册。执行驱动类的一些静态代码块。

    静态代码块的主要内容是:

    DriverManager.registerDriver(new OracleDriver());向DriverManager注册自己。(所谓注册就是创建Driver实例,添加到驱动列表中)。

    注册成功后,就可以与数据库进行连接。

    DriverManager.getConnection(url, user, password);

    这个方法主要实现的是找到注册时创建的oracleDriver对象,调用OracleDriver的connect(url)来实现数据库的连接。对数据库操作时,OracleDriver调用Oracle对Connection,Statement,ResultSet几个接口的实现类来完成功能。

    OracleDriver这个类是用来管理Connection,Statement,ResultSet这几个接口的

    DriverManger是用来管理OracleDrier类的。

    Class类的相关方法


    Calss(类类型):用于存储类的信息,诸如类名、有哪些属性,方法,构造器,父类型

    Class类的实例表示正在运行的Java类或者接口。任何Java的类或者接口都是Class类的一个实例。

    Class clazz=String.class;

    clazz.getName()  类名:java.lang.String

    clazz.getSimpleName()  简单类名:String

    clazz.getSuperclass().getName()  父类型名称:java.lang.Object

    Class[] classes=clazz.getInterfaces();  获取所实现的接口信息,返回值是数组类型

    Method[] methods=clazz.getMethods();  获取该类拥有的public方法信息

    clazz.getDeclaredMethod(方法名,参数类型);  获取某个具体的方法

    Field[] fields=clazz.getFields();  获取public属性信息

    Field[] fields=clazz.getDeclaredFields();  获取所有属性

    Field field=clazz.getDeclaredField("name");  获取一个具体的属性

    public class BaseClass {
        int id;
        private String name;
        public double grade;
    
        public BaseClass() {
        }
    
        public BaseClass(int id, String name, double grade) {
            super();
            this.id = id;
            this.name = name;
            this.grade = grade;
        }
    
        public void fun1() {
            System.out.println("无返回值,无参数的方法");
        }
    
        public String fun2(int a) {
            return this.name + "," + a;
        }
    }

    Filed类的相关方法


    field.getModifiers()  返回该属性的修饰符信息(private static final...),返回是整数

    Modifier.toString(field.getModifiers())  把整数转换成相应的private public..

    field.getType().getSimpleName()  属性类型

    field.getName()  属性名

    Field field=clazz.getDeclaredField(属性名");  获得某一个具体的属性值

    field.setAccessible(true);  允许访问私有属性

    Object value=field.get(具体的对象引用obj);  获取具体对象obj中该属性值

    field.set(obj, "李四");  对具体对象object的属性设置值”张三”,该属性就是field对应的属性

    public static void main(String[] args) throws Exception {
    
            Class clazz = Class.forName("com.org.qin.test.BaseClass");
            Field[] fields = clazz.getDeclaredFields();
            // 访问BaseClass的属性信息,修饰符 类型 属性名
            for(Field field : fields){
                System.out.print(Modifier.toString(field.getModifiers()) + "  " + field.getType().getSimpleName() + "  "
                        + field.getName());
                System.out.println();
            }
            BaseClass obj = new BaseClass(1, "张三", 2);
    
            // 获取某一个具体的属性
            Field field = clazz.getDeclaredField("name");
            // 允许访问私有属性
            field.setAccessible(true);
            // 获取属性中的值
            Object value = field.get(obj);
            System.out.println(value);
    
            // 为对象的属性赋值
            field.set(obj, "李四");
            System.out.println(field.get(obj));
    }

    Method类的相关方法


    method.getReturnType()  方法返回值类型

    method.getName()   方法名

    Class[] pTypes=method.getParameterTypes();   方法参数类型

    method.invoke(obj, new Class[]{});  调用某个具体的方法

    public static void main(String[] args) throws Exception {
    
            Class clazz = BaseClass.class;
            Method[] methods = clazz.getDeclaredMethods();
    
            // 获取类中所有方法信息 返回值类型 方法名 参数类型
            for(Method method : methods){
                System.out.print(method.getReturnType().getSimpleName() + "  " + method.getName());
                Class[] pTypes = method.getParameterTypes();
                System.out.print("(");
                for(Class t : pTypes){
                    System.out.print(t.getSimpleName());
                }
                System.out.println(")");
            }
    
            // 获取类中的某个指定方法
            Method method = clazz.getDeclaredMethod("fun1", new Class[]{});// 没有参数,放入一个空数组就行
    
            // 调用方法
            BaseClass obj = new BaseClass(1, "张三", 2);
    
            // method.invoke(obj,null);//无参数可以写null或者new Object[]{}
            method.invoke(obj, new Object[]{});
    
            // 获取有参数方法,并且调用
            Method method2 = clazz.getDeclaredMethod("fun2", new Class[]{int.class});
            System.out.println(method2.invoke(obj, new Object[]{3}));
    }

    constructor类的相关方法


    constructor.getParameterTypes();  获得构造器参数类型

    constructor.getModifiers();  获得构造器修饰符信息

    constructor.getName();  构造器名称

    clazz.getConstructor(new Class[]{...});  获得指定构造器(根据类型)

    BaseClass obj=(BaseClass) constructor.newInstance(new Object[]{....});//使用构造器创建对象

    案例

    public static void main(String[] args) throws Exception {

             Class clazz=BaseClass.class;

             Constructor[] constructors=clazz.getConstructors();

             for(Constructor constructor:constructors){

                      Class[] types=constructor.getParameterTypes();

                      System.out.print(Modifier.toString(constructor.getModifiers()) +"  "+constructor.getName());

                      System.out.print("(");

                      for(Class t:types){

                               System.out.print(t.getSimpleName()+" ");

                      }

                      System.out.println(")");

             }

             /获得指定的构造器

             Constructor constructor=clazz.getConstructor(

    new Class[]{int.class,String.class,double.class,double.class});

             //用构造器创建对象

             BaseClass obj=(BaseClass) constructor.newInstance(new Object[]{1,"张三",20,2});

             System.out.println(obj.getName());

    }

    7、JavaBean拷贝

    1)什么是JavaBean

       一种Java类,重用的组件,符合一定设计规范的

    2)符合规范如下

            a、公共且完整的类

            b、所有属性需要隐藏

            c、提供公共的可访问私有属性的途径(getXXX,setXXX)

            d、布尔类型的属性命名时把get/set换成is

            e、一定要提供一个无参的构造器

  • 相关阅读:
    关于命题“网络规划中一个VLAN要对应一个网段”的证明
    详谈为何两台主机网络掩码不一致可能导致ping不通
    为什么电脑的ip地址要和网关的ip同一个子网才可以上网?
    快速理解VirtualBox的四种网络连接方式(最详细)
    Ubuntu 16.04下安装OpenStack(juno)之add the compute service报错分析
    Ubuntu 16.04下安装OpenStack(juno) 之add the image service报错分析
    曲线
    Best Cow Fences
    愤怒的牛
    斐波那契数
  • 原文地址:https://www.cnblogs.com/qin-derella/p/6669638.html
Copyright © 2011-2022 走看看