6.6 变量处理和方法处理
一、Java 9增强的MethodHandle类
MethodHandle为Java增加了方法引用功能,方法引用概念有点类似于C的“函数指针”。这种方法引用是一种轻量级的引用方式,他不会检查方法的访问权限,也不管方法所属的类、实例方法、静态方法,MethodHandle就是简单代表特定的方法,并通过MethodHandle来调用方法。
使用MethodHandle类还涉及几个类:
1、MethodHandles:MethodHandle的工厂类,它提供一些列的静态方法来获取MethodHandle。
2、MethodHandles.Lookup:Lookup静态类也是MethodHandle、VarHandle的工厂类,专门用于获取MethodHandle、VarHandle。
3、MethodType:代表一个方法的类型。MethodType根据方法的形参、返回值类型来确定方法类型。
下面示范MethodHandle的用法
1 import java.lang.invoke.*; 2 public class MethodHandleTest 3 { 4 // 定义一个private的类方法 5 private static void hello() 6 { 7 System.out.println("Hello world!"); 8 } 9 // 定义一个private的实例方法 10 private String hello(String name) 11 { 12 System.out.println("执行带参数的hello" + name); 13 return name + ",您好"; 14 } 15 public static void main(String[] args) throws Throwable 16 { 17 //引用静态方法名 18 // 定义一个返回值为void、不带形参的方法类型 19 var type = MethodType.methodType(void.class); 20 // 使用MethodHandles.Lookup的findStatic获取类方法 21 var mtd = MethodHandles.lookup() 22 .findStatic(MethodHandleTest.class, "hello", type); 23 // 通过MethodHandle执行方法 24 mtd.invoke(); 25 26 // 使用MethodHandles.Lookup的findVirtual获取实例方法 27 var mtd2 = MethodHandles.lookup() 28 .findVirtual(MethodHandleTest.class, "hello", 29 // 指定获取返回值为String, 形参为String的方法类型 30 MethodType.methodType(String.class, String.class)); 31 // 通过MethodHandle执行方法,传入主调对象和参数 32 System.out.println(mtd2.invoke(new MethodHandleTest(), "孙悟空")); 33 } 34 }
执行结果:
1 ---------- 运行Java捕获输出窗 ---------- 2 Hello world! 3 执行带参数的hello孙悟空 4 孙悟空,您好 5 6 输出完成 (耗时 0 秒) - 正常终止
二、Java 9增加的VarHandle
VarHandle主要用于动态操作数组的元素和对象的成员变量。VarHanbdle和MedthodHandle非常相似,他也需要MethodHandles来获取实例,接下来调用VarHandle的方法即可动态操作数组的元素和指定对象的成员变量。
1 import java.lang.invoke.*; 2 import java.util.Arrays; 3 class User 4 { 5 String name; 6 static int MAX_AGE; 7 } 8 public class VarHandleTest 9 { 10 public static void main(String[] args) throws Throwable 11 { 12 var sa = new String[] {"Java", "Kotlin", "Go"}; 13 // 获取一个String[]数组的VarHandle对象 14 var avh = MethodHandles.arrayElementVarHandle(String[].class); 15 // 比较并设置:如果第三个元素是Go,则该元素被设为Lua 16 var r = avh.compareAndSet(sa, 2, "Go", "Lua"); 17 // 输出比较结果 18 System.out.println(r); // 输出true 19 // 看到第三个元素被替换成Lua 20 System.out.println(Arrays.toString(sa)); 21 // 获取sa数组的第二个元素 22 System.out.println(avh.get(sa, 1)); // 输出Kotlin 23 // 获取并设置:返回第三个元素,并将第三个元素设为Swift 24 System.out.println(avh.getAndSet(sa, 2, "Swift")); 25 // 看到第三个元素被替换成Swift 26 System.out.println(Arrays.toString(sa)); 27 28 // 用findVarHandle方法获取User类中名为name, 29 // 类型为String的实例变量 30 var vh1 = MethodHandles.lookup().findVarHandle(User.class, 31 "name", String.class); 32 var user = new User(); 33 // 通过VarHandle获取实例变量的值,需要传入对象作为调用者 34 System.out.println(vh1.get(user)); // 输出null 35 // 通过VarHandle设置指定实例变量的值 36 vh1.set(user, "孙悟空"); 37 // 输出user的name实例变量的值 38 System.out.println(user.name); // 输出孙悟空 39 // 用findVarHandle方法获取User类中名为MAX_AGE, 40 // 类型为Integer的类变量 41 var vh2 = MethodHandles.lookup().findStaticVarHandle(User.class, 42 "MAX_AGE", int.class); 43 // 通过VarHandle获取指定类变量的值 44 System.out.println(vh2.get()); // 输出0 45 // 通过VarHandle设置指定类变量的值 46 vh2.set(100); 47 // 输出User的MAX_AGE类变量 48 System.out.println(User.MAX_AGE); // 输出100 49 } 50 }
从上面前两行的粗体代码可以看出,程序调用MethodHandles类的静态方法来获取操作数组的VarHandle对象,接下来程序可通过VarHandle对象来操作数组的方法,包括设置数组元素、获取并设置数组元素等,VarHandle的及具体方法参看API文档。
后面粗体代码示范了操作实例变量的情形,由于实例变量需要使用对象来访问,因此使用VarHandle操作实例变量时需要传入一个User对象。VarHandle既可以设置实例变量的值,也可以获取实例变量的值。
原文地址:https://www.cnblogs.com/weststar/p/12485721.html
- 解决后台无法进入提示DedeCMS Error: (PHP 5.3 and above) Please set 'request_order' ini value
- 一文教你实现skip-gram模型,训练并可视化词向量
- 如何将文章列表用<li>分两列显示
- 面试题之走楼梯问题
- 最长公共子序列与最长公共子串
- nodejs 的序列化与反序列化
- dedecms获取当前文章所在栏目URL
- highcharts 时间少8小时问题
- 【干货】python玩转微信:微信好友统计信息全掌握
- 使用Visual Studio 调试断点不起作用的问题解决办法 调试Revit CAD 不能进入断点
- openFileDialog的Filter属性设置
- dedecms调用当前栏目的子栏目怎么操作
- dedecms如何增加自定义字段
- dedecms如何快速删除跳转的文章(记得清空内容回收站)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- pytorch判断是否cuda 判断变量类型方式
- Keras搭建自编码器操作
- python程序如何进行保存
- Android Q之气泡弹窗的实现示例
- Python with语句用法原理详解
- pytorch 计算ConvTranspose1d输出特征大小方式
- Keras中 ImageDataGenerator函数的参数用法
- CI框架网页缓存简单用法分析
- 掌握PHP垃圾回收机制详解
- PHP基于面向对象封装的分页类示例
- PHP获取对象属性的三种方法实例分析
- PHP7内核之Reference详解
- PHP基于PDO扩展操作mysql数据库示例
- php实现的PDO异常处理操作分析
- PHP yield关键字功能与用法分析