Java多态与反射
多态通过分离做什么和怎么做,从另一个角度将接口与实现分离开来;通过多态来消除类型之间的耦合关系,在Java中,多态也叫动态绑定,后期绑定或运行时绑定,那么什么是方法绑定?
方法调用绑定:
将一个方法与调用同一个方法的主体关联起来被称为绑定;若在程序执行前进行绑定(由编译器和连接程序实现),叫做前期绑定;还有一种叫后期绑定,就是在运行时根据对象的类型进行绑定,也叫动态绑定或运行时绑定,也就是说,编译器不知道对象的类型,但是方法调用机制能找到正确的方法体;在Java中除了static
方法和final
方法之外,所有的其他方法都是后期绑定;
因此,Java中所有的方法都是通过动态绑定来实现多态的,但如果直接访问某个域,则这个访问就会在编译其进行解析;一般我们都通过将子类向上转型为父类来实现多态,父类可以是抽象类,只要子类实现到父类的所有抽象方法,就可以将子类转型为抽象的父类;Java里的抽象类本身是不能被实例化,但可以将子类的引用向上转型为抽象的父类。
如:
abstract class Jack{
public abstract void doSomething();
}
class Product extends Jack{
@Override
public void doSomething() {
System.out.println("Product");
}
}
public static void main(String[] args) {
//声明一个抽象类Jack的变量,并指向其子类的实例化对象,合法的,Java的多态性会保证在运行时可以得到其正确的类型;
Jack jack=new Product();
//Jack jack=new Jack();//非法,不能实例化抽象类对象
jack.doSomething();
}
Java反射
Java反射机制是指在运行状态时,可以知道任意一个类的的所有属性和方法,对任意一个对象都可以调用它的任意一个方法;通过反射,可以在运行时实例化对象
Java反射提供的功能包括:
- 在运行时判断一个对象所属的类;
- 运行时构造任意一个类的对象;
- 运行时判断任意一个类的成员变量与方法;
- 运行时调用任意一个对象的方法;
- 生成动态代理;
我们想得到一个类的所有信息,第一步就是要得到类的Class对象,如果知道了一个对象或类的名字,就可以通过简单的:
Class<?> clz=对象.getClass();
Class<?> clz=类的名字.class
得到,但如果在编译期得不到具体类型,则可以通过Class.forName()
来得到,但这个方法生成的结果在编译时是不可知的,所有的方法特征签名都是在运行时提取出来的。这是由Java的反射机制来提供足够的支持。在得到这个类的Class对象后,我们就可以反射来构造对象,进而得到这个类的所有的信息。
public static Class<?> forName(String className)
throws ClassNotFoundException {
Class<?> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}
Java里的Class
类与java.lang.reflect
类库一起对反射进行支持,该类库包含了Field
,Method
,Constructor
类(每个类都实现了Member
接口),这些类型的对象是在JVM在运行时创建的,用以表示未知类里对应的成员。这样我们就可以使用Constructor
创建新的对象,用get()
,set()
方法修改与Field对象关联的字段,用invoke()
方法调用与Method
对象关联的方法。(摘自《Java编程思想》第四版)
下面简要介绍利用反射实现的动态代理;
动态代理
步骤:
- 新建委托类,实现动态代理要求委托类必须实现某个接口;
- 新建中间类,用来连接代理类和委托类,这个中间必须实现
InvocationHandler
接口,这个接口只有一个invoke()
方法; - 通过
Proxy
类新建代理类对象;
举例:
interface Operate{
void method1();
void method2();
void method3();
}
/**
* 委托类
* @author wood
*
*/
class Entrust implements Operate{
@Override
public void method1() {
// TODO Auto-generated method stub
System.out.println("*method1");
}
@Override
public void method2() {
// TODO Auto-generated method stub
System.out.println("*method2");
}
@Override
public void method3() {
// TODO Auto-generated method stub
System.out.println("*method3");
}
}
/**
* 连接委托类与代理类的中间类;
* @author wood
*
*/
class DynamecProxyHandler implements InvocationHandler{
private Object proxied;//委托类对象
public DynamecProxyHandler(){
}
public DynamecProxyHandler(Object object){
this.proxied=object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] arg2)
throws Throwable {
// TODO Auto-generated method stub
Object object=method.invoke(proxied, arg2);
System.out.println(method.getName());
return object;
}
}
//***********************
DynamecProxyHandler dymaProxy=new DynamecProxyHandler(new Entrust());
//通过Proxy类的静态函数生成代理对象;
Operate operate=(Operate)Proxy.newProxyInstance(Operate.class.getClassLoader(), new Class[]{Operate.class}, dymaProxy);
operate.method1();
operate.method2();
operate.method3();
我们通过Procy.newProcyInstance
函数新建了一个代理对象,实际的代理类就是在这时候动态生成了,我们调用该代理对象的函数就会调用到中间类的invoke
函数,而invoke
函数实现调用委托类的对应函数;
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
loader
是类加载器;
interfaces
是委托类的接口,生成代理需要实现这个接口;
实际上Java的动态代理就是两层的静态代理:开发者提供一个委托类A,程序动态生成了一个代理类B,开发者还需要提供一个实现了InvocationHandler
的接口C,用类C来连接委托类A和委托类B,类C是代理类B的委托类,是类A的代理类;用户直接调用代理类B,B将调用转发给委托类C,C再将调用转发给委托类A;
参考:
《Java编程思想》第四版
公共技术点之 Java 动态代理
Java多态与反射的更多相关文章
- Java中的反射机制和动态代理
一.反射概述 反射机制指的是Java在运行时候有一种自观的能力,能够了解自身的情况为下一步做准备,其想表达的意思就是:在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法:对于任意一个对象 ...
- 在java中有关于反射的皮毛----自己的简略认知
白首为功名.旧山松竹老,阻归程.欲将心事付瑶琴.知音少,弦断有谁听? 反射(reflection): 当我们在看到这个名词首先会想到的是,我们在上高中时学的物理,那么在java开发中,反射这个名词是怎 ...
- java中的反射(二)
java中的反射(一):https://www.cnblogs.com/KeleLLXin/p/14060555.html 目录 一.反射 1.class类 2.访问字段 3.调用方法 4.调用构造方 ...
- Java中的反射和注解
前言 在Java中,反射机制和注解机制一直是一个很重要的概念,那么他们其中的原理是怎么样呢,我们不仅仅需要会使用,更要知其然而之所以然. 目录 反射机制 反射如何使用 注解定义 注解机制原理 注解如何 ...
- java中的反射机制在Android开发中的用处
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反 ...
- Java里面,反射父类里面数字类型字段,怎么set值
Java里面,反射父类里面数字类型字段,怎么set值,我的做法是这样: /** * TODO 直接设置对象属性值, 忽略private/protected 修饰符, 也不经过setter * @aut ...
- Java 多态——与C++的比较
学习了Java和C++之后,由于长期不使用C++,而java的基础知识掌握不牢,现在已经搞不清java多态了.现在先来谈谈java多态,稍后有时间再更新C++的多态,并进行比较~ 一. Java的多态 ...
- C++和java多态的区别
C++和java多态的区别 分类: Java2015-06-04 21:38 2人阅读 评论(0) 收藏 举报 转载自:http://www.cnblogs.com/plmnko/archive ...
- java 27 - 2 反射之 反射的概述以及获取Class文件对象的方式
反射: JAVA语言的反射机制: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法: 对于任意一个对象,都能够调用它的任意一个方法和属性: 这种动态获取的信息以及动态调 ...
随机推荐
- 第18章 集合框架(2)-Set接口
第18章 集合框架(2)-Set接口 Set是Collection子接口,模拟了数学上的集的概念 Set集合存储特点 1.不允许元素重复 2.不会记录元素的先后添加顺序 Set只包含从Collecti ...
- 微博公众平台(二)-- Token验证代码
Token,验证逻辑:1.将Token.timestamp.nonce放入数组 2.将数组从小到大排列 3.将数组按顺序拼装成一个字符串 4.对生成的字符串进行SHA1加密 5.将密文转换为小写 6. ...
- MySQL 常用的sql语句小结(待续)
mysql 常用的sql语句 1.查看数据库各个表中的记录数 USE information_schema; SELECT table_name,table_rows FROM tables WHER ...
- 【swift学习笔记】三.使用xib自定义UITableViewCell
使用xib自定义tableviewCell看一下效果图 1.自定义列 新建一个xib文件 carTblCell,拖放一个UITableViewCell,再拖放一个图片和一个文本框到tableviewc ...
- C#软件设计——小话设计模式原则之:依赖倒置原则DIP
前言:很久之前就想动笔总结下关于软件设计的一些原则,或者说是设计模式的一些原则,奈何被各种bootstrap组件所吸引,一直抽不开身.群里面有朋友问博主是否改行做前端了,呵呵,其实博主是想做“全战”, ...
- 查看SQL Server被锁的表以及如何解锁
锁定数据库的一个表的区别 SELECT * FROM table WITH (HOLDLOCK) 其他事务可以读取表,但不能更新删除 SELECT * FROM table WITH (TABLOCK ...
- 大图居中,以1920px为例
<div style="overflow: hidden; position: relative;"> <img src="img.jpg" ...
- ob_start()
ob_start()函数用于打开缓冲区 1.用于header()之前 ob_start(); //打开缓冲区 echo "Hellon"; //输出 header("lo ...
- 江太公:javascript count(a)(b)(c)(d)运行过程思考
昨天,我弟抛给我一个js的题,使用类似标题那样的调用方法计算a*b*c*d以致无穷的实现方法.思考了半天,终于理清了它的运行过程,记录于下: 函数体: <!DOCTYPE html> &l ...
- PostgreSQL Apt Repository
PostgreSQL Apt Repository If the version included in your version of Ubuntu is not the one you want, ...