17.Java 反射机制
1.反射的定义
反射之中包含了一个“反”的概念,所以要想解释反射就必须先从“正”开始解释,一般而言,当用户使用一个类的时候,应该先知道这个类,而后通过这个类产生实例化对象,但是“反”指的是通过对象找到类。
2.Class对象
2.1 概述
Class对象是反射的起点,可以利用类的Class对象创建类的实例(newInstance),同时提供了操作类的工具,可以获取类的详细信息,并且使用特殊的技术实现类的加载(运行时加载,在编译的时候还没有该类的class文件)。
2.2 Class对象的获取方式
- a.使用类的字面常量
- Class<Integer> c=Integer.class; 备注:编译时会进行检查,不需要捕获ClassNotFoundException,Class对象的类型也是明确的。
- b.使用forName函数
- Class<?> c=Class.forName("Integer"); 备注:需要捕获异常,而且Class对象的类型是Class<?>,类型不明确,可以使用asSubClass进行转换,但是只能转换到Class<? extends Integer>。
- Class<? extends Integer> u=c.asSubClass(Integer.class);
- Class<? exnteds Integer> u1=c.getClass(new Integer(10).getClass());
- c.使用getClass()函数
- Integer integer=new Integer(10);
- Class<? extends Integer> c=intger.getClass(); 备注:使用对象实例获取Class对象。
3.类型检查
3.1概述
Class对象提供了很多获取类信息的工具,可以获取类的方法,属性,进行类型判断,创建类的对象实例等等。
3.2 相关API介绍
- a.获取类的构造函数
public class Main {
public static void main(String[] atgs) throws ClassNotFoundException {
printTypeInfo("MyClass");
}
/**
获取类的构造函数
*/
public static void printTypeInfo(String className){
try {
Class<?> c = Class.forName(className);
Constructor<?>[] constructors=c.getConstructors();
for(Constructor<?> constructor:constructors){
System.out.println(constructor);
}
}catch(ClassNotFoundException e){
e.printStackTrace();
}
}
} class MyClass {
private int num=10;
public MyClass(int num){
this.num=num;
} public MyClass(){
} @Override
public String toString(){
return String.format("%d",num);
}
}备注:1.使用反射创建类的实例,Class.newInstance(),类中必须又一个无参数的构造函数,否则会报错。
- 2.输出:public MyClass(int)
public MyClass()
- 利用构造函数获取相关的对象
- 用带参数构造函数,创建实例
Constructor<?> constructor=c.getConstructor(int.class);
MyClass myClass=(MyClass)constructor.newInstance(5);
System.out.println(myClass);
- 备注:1.上述的代码没有捕获异常,不能直接执行
- 2.Class.newInstance()其实也就是获取类的无参构造函数,然后创建对象。
- b.获取类的一般函数
public static void printTypeInfo(String className) {
try {
Class<?> c=Class.forName(className);
for(Method method:c.getMethods()){
System.out.println(method);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}- 备注:
- 只能获取构造函数之外的函数,但是还包括从父类中继承来的函数
- 获取特定的函数
- getMethod(String methodName,Class<?> ...);
- 例子:获取特定函数并执行Method.invoke(Obj,Class<?>...)---------动态执行Java的函数
public static void main(String[] args){
Class<?> c=Class.forName(className);
Method method=c.getMethod("getInfo",String.class);
System.out.println(method.invoke(c.newInstance(),new String("123")));
} class MyClass {
private int num=10;
public MyClass(int num){
this.num=num;
} public MyClass(){
} public String getInfo(String string){
return String.format("get : %s",string);
} @Override
public String toString(){
return String.format("%d",num);
}
}
- 备注:不能直接执行,没有捕获异常,为了看一来比较清楚
- c.获取类的属性
public static void printTypeInfo(String className) {
try {
Class<?> c=Class.forName(className);
Field[] fields=c.getDeclaredFields();
for(Field field:fields){
System.out.println(field);
} } catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}- 备注:还可以获取制定的属性 :field = c.getDeclaredField("num");
- 操作类的属性,赋值-取值
- 可能会有访问权限的问题,比如private的属性就不能进行操作,此时可以使用field.setAccessible(true)进行“破坏”面向对象的封装。
field.setAccessible(true);
field.set(myClass,123);
- d.备注
- 反射还有很所用处,例如获取泛型的参数化类型,操作注解等等。
4.代理
- a.一般的代理设计模式
public class Main {
public static void main(String[] atgs) {
proxy proxy=new ProxyServer(new RealServer());
proxy.doSomthing();
}
} interface proxy{
void doSomthing();
} class RealServer implements proxy{
@Override
public void doSomthing(){
System.out.println("doSomething from RealServer");
}
} class ProxyServer implements proxy{
private proxy realServer;
public ProxyServer(proxy realServer){
this.realServer=realServer;
} @Override
public void doSomthing(){
realServer.doSomthing();
}
}
- b.利用反射的动态代理设计模式
import java.lang.reflect.*; /**
* Created by yangyun on 2016/11/30.
*/
public class Main {
public static void main(String[] atgs) {
myProxy myProxyInterface=(myProxy) Proxy.newProxyInstance(
RealServer.class.getClassLoader(),
RealServer.class.getInterfaces(),
new ProxyHandler(new RealServer())
);
myProxyInterface.doSomthing();
}
} interface myProxy{
void doSomthing();
} class RealServer implements myProxy{ public RealServer(){
} @Override
public void doSomthing(){
System.out.println("from RealServer doSomething()");
}
} class ProxyHandler implements InvocationHandler{
private Object realProxy;
public ProxyHandler(Object realProxy){
this.realProxy=realProxy;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before invoke()");
Object result=method.invoke(realProxy,args);
System.out.println("after invoke()");
return result;
}
}有什么意义?
- 1.如果需要在调用代理服务器的函数之前或者之后做一些别的工作,可以不修改服务器端的代码,只需要修改InvocationHandler的invloke()函数就可以。
- 2.动态代理还是AOP(Spring 面向切面编程的基础)
- 3.静态代理每增加一个服务类就应该添加一个代理类,动态代理的话只需要一个InvokationHandler就可以了
- 备注:
- System.out.println(myProxyInterface.getClass().getName());//$Proxy0
- 通过 Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,以$开头,proxy为中,最后一个数字表示对象的标号。
- 我自己的理解可能会有错
- proxy.newProxyInstance()产生的其实是代理对象,这个代理对象会实现被“代理类RealServer”的所有接口,这里我们把它转型为proxy接口。
- 当我通过代理对象来调用方法的时候,起实际就是委托由其关联到的 handler 对象的invoke方法中来调用,并不是自己来真实调用,而是通过代理的方式来调用的,输出method可以看到其实就是doSomething函数。
- 这就是我们的java动态代理机制,代理对象执行函数全部都通过InvokationHandler的invoke()函数。
参考文献
https://www.zhihu.com/question/24304289
http://blog.csdn.net/xu__cg/article/details/52882023
http://blog.csdn.net/liujiahan629629/articzle/details/18013523
http://www.cnblogs.com/xiaoluo501395377/p/3383130.html
17.Java 反射机制的更多相关文章
- java反射机制深入详解
java反射机制深入详解 转自:http://www.cnblogs.com/hxsyl/archive/2013/03/23/2977593.html 一.概念 反射就是把Java的各种成分映射成 ...
- [转]java反射机制
原文地址:http://www.cnblogs.com/jqyp/archive/2012/03/29/2423112.html 一.什么是反射机制 简单的来说,反射机制指的是程序在运 ...
- java 反射机制01
// */ // ]]> java反射机制01 Table of Contents 1 反射机制 2 反射成员 2.1 java.lang.Class 2.2 Constructor 2.3 ...
- Java 反射机制浅析
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反 ...
- 5. Java反射机制
Java反射机制 问题: 在运行时,对一个JAVA类,能否知道属性和方法:能否调用它的任意方法? 答案是可以的,JAVA提供一种反射机制可以实现. 目录 什么是JAVA的反射机制 JDK中提供的R ...
- Java反射机制能够获取的信息,与应用
一.什么是Java反射机制? [1]反射机制是在运行状态中,对于任何一个类,都能够知道这个类的所有属性和方法: [2]对于任意一个对象,都能够调用它的任意一个属性和方法: 像这种动态获取类的信息以及动 ...
- Java进阶(六)Java反射机制可恶问题NoSuchFieldException
作为一种重要特性,Java反射机制在很多地方会用到.在此做一小结,供朋友们参考. 首先从一个问题开始着手. 可恶的问题又来了,NoSuchFieldException,如下图所示: 完全不知道这个qu ...
- [转]Java反射机制详解
目录 1反射机制是什么 2反射机制能做什么 3反射机制的相关API ·通过一个对象获得完整的包名和类名 ·实例化Class类对象 ·获取一个对象的父类与实现的接口 ·获取某个类中的全部构造函数 - 详 ...
- 谈谈Java反射机制
原文出处: locality 写在前面:什么是java反射机制?我们又为什么要学它?当程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言.我们认为java并不是动态语言,但是它却有一个非常突 ...
随机推荐
- docker run elasticsearch
docker run -d --name=esNode1 -p 9200:9200 -p 9300:9300 elasticsearch:2.3 -Des.network.publish_host=& ...
- django创建新项目anministrator问题
1.app中models的class可以通过migrations命令生成相应的数据表 2.此时并未写入数据库,migrate命令可以把相应的改动更新到数据库中 3.createsuperuser命令创 ...
- [Unreal]学习笔记之材质说明
取消蓝图中的连接线:Alt+鼠标左键 在蓝图中,通过按住1,2,3,4加鼠标左键,可以快速生成1,2,3,4维的向量 材质和材质实例的区别:使用一个母材质,可以创建出多种场景中的材质实例:每次修改母材 ...
- 常用的数据统计Sql 总结
最近刚在搞一个BI的项目,里面需要大量的sql 数据统计相关运用,加深了我又对SQL的理解与使用. 所以,分享几个数据统计时常用的sql 语句总结: 1. 统计各个条件下的数据 select Batc ...
- Django基础,Day4 - views 详解
在Django中,网页和其他内容是通过视图传递的.每个视图由一个简单的Python函数表示,Django将通过检查请求的URL(准确地说,是域名后面的部分URL)来选择一个视图. 例如,用户在浏览器中 ...
- git rebase
git rebase -i HEAD~[number_of_commits] git rebase -i HEAD~2
- HTML中的SVG
HTML5中的SVG是Scalable Vector Graphic的简称,是一种用来绘制矢量图的HTML5标签,由万维网联盟定制,是一个基于可扩展标记语言,用于绘制二维可缩放矢量图形. 是一种使用X ...
- spring拦截器排除 静态资源
拦截器需要排除静态资源,不然会造成资源浪费 <!-- 拦截器 --> <mvc:interceptors> <!-- 使用bean定义一个Interceptor,直接定义 ...
- javac编译不同目录的源码提示找不到符号
对于单个文件的且不引用其他类文件的java源码用javac编译大家都很熟悉即 javac mycode.java 但是如果这个文件引用到了其他的类文件,在进行编译的时候就会提示找不到符号,这时我们需要 ...
- 键盘按钮keyCode大全
字母和数字键的键码值(keyCode) 按键 键码 按键 键码 按键 键码 按键 键码 A 65 J 74 S 83 1 49 B 66 K 75 T 84 2 50 C 67 L 76 U 85 3 ...