Java Hour 63 反射
首先要感谢下这位可爱的作者:
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 反射的更多相关文章
- Java中的反射和注解
前言 在Java中,反射机制和注解机制一直是一个很重要的概念,那么他们其中的原理是怎么样呢,我们不仅仅需要会使用,更要知其然而之所以然. 目录 反射机制 反射如何使用 注解定义 注解机制原理 注解如何 ...
- java中的反射机制在Android开发中的用处
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反 ...
- Java里面,反射父类里面数字类型字段,怎么set值
Java里面,反射父类里面数字类型字段,怎么set值,我的做法是这样: /** * TODO 直接设置对象属性值, 忽略private/protected 修饰符, 也不经过setter * @aut ...
- java 27 - 2 反射之 反射的概述以及获取Class文件对象的方式
反射: JAVA语言的反射机制: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法: 对于任意一个对象,都能够调用它的任意一个方法和属性: 这种动态获取的信息以及动态调 ...
- 黑马程序员——【Java高新技术】——反射机制
---------- android培训.java培训.期待与您交流! ---------- 一.概述 1.Java反射机制:是指“在运行状态中”,对于任意一个类,都能够知道这个类中的所有属性和方法: ...
- Java 中的反射机制
JAVA反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为ja ...
- Java学习笔记--反射
什么是Java反射 概念 java反射是指java能够在运行时确定类的类型信息,包括其方法.字段.构造函数等,并能够通过反射调用类或者类对象的方法.在Java中,java.lang.Class类与ja ...
- JAVA类型信息——反射机制
JAVA类型信息——反射机制 一.反射机制概述 1.反射机制:就是java语言在运行时拥有的一项自我观察的能力,java通过这种能力彻底了解程序自身的情况,并为下一步的动作做准备. 2.反射机制的功能 ...
- 浅说Java中的反射机制(二)
写过一篇Java中的反射机制,不算是写,应该是抄了,因为那是别人写的,这一篇也是别人写的,摘抄如下: 引自于Java基础--反射机制的知识点梳理,作者醉眼识朦胧.(()为我手记) 什么是反射? 正常编 ...
随机推荐
- 一个完整的Http请求
一个完整的http请求,通常有以下7点: 1.建立tcp连接 2.web浏览器web服务器发送请求命令 3.web浏览器发送请求头信息 4.web服务器应答 5.web服务器发送应答信息 6.web服 ...
- Linux下端口被占用解决
有时候关闭软件后,后台进程死掉,导致端口被占用.下面以JBoss端口8083被占用为例,列出详细解决过程. 解决方法: 1.查找被占用的端口 netstat -tln netstat -tln | ...
- win7下配置Apache本地虚拟主机
我们有时候从网上下载下来的php源码很多都是应用在网站根目录下的,而我们又想在本地先测试一遍确定没有问题了再上传空间,但一换到子目录下的时候因为路径问题,使得许多图片.内容都无法显示. 这个时候我们就 ...
- AutoMapper Getting started
AutoMapper 是什么? 为什么要用AutoMapper? 如何使用AutoMapper? 在什么地方配置AutoMapper? 如何测试my mappings? AutoMapper 是什么? ...
- SSRS报表参数设置
一.日期时间类型的参数注意事项: 关于数据类型的选择:(只有数据类型设置为日期/时间格式,在查询的时候才会显示日期控件,提示信息一般改成汉字) 指定默认值:指定开始日期为前10天,
- 学 Redux (转)
0.官方文档:http://redux.js.org/ 中文版本 : http://cn.redux.js.org/ 中文版本(好!): http://www.css88.com/react/d ...
- C#跨线程操作控件
1.首先通过按键创建子线程: 创建子线程,子线程调用changeText方法. private void btnOK_Click(object sender, EventArgs e) { Threa ...
- NGUI 图片变灰
效果图 1.先准备好一个变灰shader.代码如下 Shader "Custom/Gray" { Properties { _MainTex ("Base (RGB), ...
- 初识 MySQL 5.6 新功能、参数
摘要: 继上一篇的文章 初识 MySQL 5.5 新功能.参数 之后,现在MySQL5.6 针对 MySQL5.5 各个方面又提升了很多,特别在性能和一些新参数上面,现在看看大致提升了哪些方面(后续不 ...
- hdu 1972.Printer Queue 解题报告
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1972 题目意思:需要模拟打印机打印.打印机里面有一些 job,每个job被赋予1-9的其中一个值,越大 ...