首先要感谢下这位可爱的作者:

http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html

本文是基于其模板的模仿实验。

获得Class 对象

public class Hello {

    public static void main(String[] args) {
        Weatherinfo weatherinfo = new Weatherinfo();
        System.out.println(weatherinfo.getClass());
    }
}

在JVM 的某一节中我们已经有讲述,这里实际上得到的是这个类型的Class 类型的实例。

而Class 类型实例拥有读取Method Area 的能力。

获得实例化的Class对象的方式

public static void main(String[] args) {
        Class<?> demo1 = null;
        Class<?> demo2 = null;
        Class<?> demo3 = null;
        try {
            demo1 = Class.forName("mike.weather.model.Weatherinfo");
        } catch (Exception e) {
            e.printStackTrace();
        }
        demo2 = new Weatherinfo().getClass();
        demo3 = Weatherinfo.class;

        System.out.println("class name: " + demo1);
        System.out.println("class name: " + demo2);
        System.out.println("class name: " + demo3);

    }

这里我们可以看到三种不同的方式:

1 直接按类的全限定名

2 类的实例

3 .class 其实是一种原始表达式的方式

通过Class获得实例化的能力

public static void main(String[] args) {
        Class<?> demo1 = null;
        try {
            demo1 = Class.forName("org.mike.reflect.Person");
        } catch (Exception e) {
            e.printStackTrace();
        }

        Person per = null;
        try {
            per = (Person) demo1.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        per.setName("Mike");
        per.setAge(20);
        System.out.println(per);
    }

当去掉Person 类的默认无参构造函数之后,该代码就会报错。

java.lang.InstantiationException: org.mike.reflect.Person
    at java.lang.Class.newInstance(Unknown Source)
    at org.mike.reflect.Hello.main(Hello.java:17)
Exception in thread "main" java.lang.NullPointerException
    at org.mike.reflect.Hello.main(Hello.java:24)

自带构造函数的实例化

public static void main(String[] args) {
        Class<?> demo = null;
        try {
            demo = Class.forName("org.mike.reflect.Person");
        } catch (Exception e) {
            e.printStackTrace();
        }
        Person per1 = null;
        Person per2 = null;
        Person per3 = null;
        Person per4 = null;

        Constructor<?> cons[] = demo.getConstructors();
        try {
            per1 = (Person) cons[0].newInstance("Mike", 20);

        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(per1);
    }

这个Constructor<?> 泛型数组里面的东东顺序是变动的。

返回某个类实现的接口

public static void main(String[] args) {
        Class<?> demo = null;
        try {
            demo = Class.forName("org.mike.reflect.Person");
        } catch (Exception e) {
            e.printStackTrace();
        }
        Class<?> intes[] = demo.getInterfaces();
        for (int i = 0; i < intes.length; i++) {
            System.out.println("implements interface:   " + intes[i]);
        }
    }

获取大集合

public static void main(String[] args) {
      Class<?> demo = null;
      try {
          demo = Class.forName("org.mike.reflect.Person");
      } catch (Exception e) {
          e.printStackTrace();
      }
      System.out.println("current class: ");
      Field[] field = demo.getDeclaredFields();
      for (int i = 0; i < field.length; i++) {
          int mo = field[i].getModifiers();
          String priv = Modifier.toString(mo);
          Class<?> type = field[i].getType();
          System.out.println(priv + " " + type.getName() + " " + field[i].getName() + ";");
      }
      System.out.println("interface or more: ");
      Field[] filed1 = demo.getFields();
      for (int j = 0; j < filed1.length; j++) {
          int mo = filed1[j].getModifiers();
          String priv = Modifier.toString(mo);
          Class<?> type = filed1[j].getType();
          System.out.println(priv + " " + type.getName() + " " + filed1[j].getName() + ";");
      }
  }

原文已经足够的详细,这里就不一一复制了。

接下去是,动态代理

先获得类型加载器:

package org.mike.reflect;

public class Hello {
    public static void main(String[] args) {
        Person t = new Person();
        System.out.println("current class loader:  " + t.getClass().getClassLoader().getClass().getName());
    }
}

在JVM 的章节里面我们讲到有好几种类型加载器:

1 Bootstrap ClassLoader 引导用的

2 Extension ClassLoader  加载Applet 之类中的扩展用的

3 AppClassLoader 加载指定的Class, 比较常用

后面的几种其实都统称为用户自定义类型加载器。

package org.mike.reflect;

public class Hello {
    public static void main(String[] args) {
        MyInvocationHandler demo = new MyInvocationHandler();
        Subject sub = (Subject) demo.bind(new RealSubject());
        String info = sub.say("Mike", 20);
        System.out.println(info);
    }
}

这个据说是动态代理的实现,这个干嘛用啊,动态代理如雷贯耳,但是这里干嘛用啊不清楚。

类的生命周期

JVM 通过类型装载器加载类,将.class 文件中的二进制文件装入method area, 并在Heap 中创建这个java.lang.Class 对象的实例。

链接就是让二进制数据组装为可以运行的状态。

链接分为校验,准备和解析3个阶段。

校验一般验证是否适合当前JVM 版本。

准备就是为静态成员分配内存空间,和设置默认值。

解析就是转换常量池中的代码为直接引用的过程。

初始化完成后,类的对象就可以正常使用了。

当没有任何引用指向Class 对象时就会被卸载,结束类的生命周期。

动态代理

关于动态代理,要感谢另外的这个小伙伴:

http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html

首先代理模式这个东东不用多说了,按照代理的创建过程,分为静态代理和动态代理。

首先静态代理很简单,基本就是我原来对于代理模式的理解。

代理类和被代理类实现同样的接口,我们发现这样重复代码太多。

将所有的公共代码提取出来以后,我们只关心我们这么调用即可。

public Object bind(Object obj) {
      this.obj = obj;
      return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
  }
public static void main(String[] args) {
      MyInvocationHandler demo = new MyInvocationHandler();
      Subject sub = (Subject) demo.bind(new RealSubject());
      String info = sub.say("Mike", 20);
      System.out.println(info);
  }

省下了很多公共的代码。

这个方法的取点是必须要实现一样的接口。

那没有接口怎么办呢?

cglib 对指定的目标生成子类,并覆盖其中的方法实现来实现动态代理。

public Object getInstance(Object target) {
    this.target = target;
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(this.target.getClass());
    enhancer.setCallback(this);
    return enhancer.create();
}

@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    System.out.println("事物开始");
    proxy.invokeSuper(obj, args);
    System.out.println("事物结束");
    return null;
}

具体的例子我没写,估计差不多理解这个原理就够忽悠人了,当真正遇到需要用的时候自然就会了。

Java Hour 63 反射的更多相关文章

  1. Java中的反射和注解

    前言 在Java中,反射机制和注解机制一直是一个很重要的概念,那么他们其中的原理是怎么样呢,我们不仅仅需要会使用,更要知其然而之所以然. 目录 反射机制 反射如何使用 注解定义 注解机制原理 注解如何 ...

  2. java中的反射机制在Android开发中的用处

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反 ...

  3. Java里面,反射父类里面数字类型字段,怎么set值

    Java里面,反射父类里面数字类型字段,怎么set值,我的做法是这样: /** * TODO 直接设置对象属性值, 忽略private/protected 修饰符, 也不经过setter * @aut ...

  4. java 27 - 2 反射之 反射的概述以及获取Class文件对象的方式

    反射: JAVA语言的反射机制: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法: 对于任意一个对象,都能够调用它的任意一个方法和属性: 这种动态获取的信息以及动态调 ...

  5. 黑马程序员——【Java高新技术】——反射机制

    ---------- android培训.java培训.期待与您交流! ---------- 一.概述 1.Java反射机制:是指“在运行状态中”,对于任意一个类,都能够知道这个类中的所有属性和方法: ...

  6. Java 中的反射机制

    JAVA反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为ja ...

  7. Java学习笔记--反射

    什么是Java反射 概念 java反射是指java能够在运行时确定类的类型信息,包括其方法.字段.构造函数等,并能够通过反射调用类或者类对象的方法.在Java中,java.lang.Class类与ja ...

  8. JAVA类型信息——反射机制

    JAVA类型信息——反射机制 一.反射机制概述 1.反射机制:就是java语言在运行时拥有的一项自我观察的能力,java通过这种能力彻底了解程序自身的情况,并为下一步的动作做准备. 2.反射机制的功能 ...

  9. 浅说Java中的反射机制(二)

    写过一篇Java中的反射机制,不算是写,应该是抄了,因为那是别人写的,这一篇也是别人写的,摘抄如下: 引自于Java基础--反射机制的知识点梳理,作者醉眼识朦胧.(()为我手记) 什么是反射? 正常编 ...

随机推荐

  1. python md5加密中文

    import md5 md5.new(u'中文').hexdigest() 会失败,报告ascii码不能解码0x.... 原因是md5会自动将被加密的数据转成字节码,如果没有详细制定编码,则可能采用了 ...

  2. phpcmsV9.5.8整合百度编辑器Ueditor1.4.3教程

    最近在搞phpcms视频功能,官方的视频功能实在是坑,刚开始是想将优酷的上传功能集成到ckeditor,在coding上有个项目,上传已经集成好了,还没有做上传后视频的获取和显示 项目地址:https ...

  3. Bootstrap之表格checkbox复选框全选

    效果图: HTML中无需添加额外的一列来表示复选框,而是由JS完成,所以正常的表格布局就行了: <table class="table table-bordered table-hov ...

  4. 介绍 .Net工具Code Snippet 与 Sql Server2008工具SSMS Tools Pack

    不久前,某某在微软写了一个很酷的工具:Visual Stuido2008可视化代码片断工具,这个工具可以在http://www.codeplex.com/SnippetDesigner上免费下载,用它 ...

  5. ubuntu update dns server

    edit:  /etc/resolvconf/resolv.conf.d/base nameserver 114.114.114.114 execute this: $ resolvconf -u f ...

  6. 【GoLang】golang HTTP GET/POST JSON的服务端、客户端示例,包含序列化、反序列化

    服务端代码示例: package main import ( "encoding/json" "fmt" "io/ioutil" " ...

  7. Mathematics:Find a multiple(POJ 2356)

    找组合 题目大意:给你N个自然数,请你求出若干个数的组合的和为N的整数倍的数 经典鸽巢原理题目,鸽巢原理的意思是,有N个物品,放在N-1个集合中,则一定存在一个集合有2个元素或以上. 这一题是说有找出 ...

  8. 经典排序算法 - 冒泡排序Bubble sort

    原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换, 这样一趟过去后,最大或最小的数字被交换到了最后一位, 然后再从头开始进行两两比较交换,直到倒数第二位时结束,其余类似看例子 例子 ...

  9. Gson简要使用笔记

    最近在做一个java web service项目,需要用到jason,本人对java不是特别精通,于是开始搜索一些java平台的json类库. 发现了google的gson,因为之前对于protoco ...

  10. express响应前端ajax请求

    后端其实并不需要知道前端发起的请求是不是ajax,后端只需要响应请求即可.例子: 前端这样写: $('button').on('click', function(event) { event.prev ...