Java中的构造函数引用和方法引用(java构造函数写法)
toyiye 2024-09-16 06:00 3 浏览 0 评论
JDK 8 见证了一个特殊特性的出现:构造函数引用和方法引用。在本文中, Adrian D. Finlay 探讨了开发人员如何释放构造函数引用的真正潜力。
方法引用的一些背景
如果你还不知道 Java 构造函数本身就是特殊的方法,那么阅读方法引用的基本示例将对读者有所帮助,通过了解这些内容,可以了解构造函数引用是什么。
「方法引用为已经有名称的方法提供易读的 lambda 表达式。」
「它们提供了一种无需执行就可以引用方法的简单方式。」
以上引自《Java 8 编程参考官方教程(第 9 版)》,作者:Herbert Schildt
方法引用可以引用静态方法和实例方法,两者是通用的。方法引用是函数式接口的实例。虽然 Lambda 表达式允许你动态创建方法实现,但通常情况下,一个方法最终会调用 Lambda 表达式中的另一个方法来完成我们想要完成的工作。更直接的方法是使用方法引用。当你已经有一个方法来实现这个函数式接口时,这是非常有用的。
让我们看一个使用静态方法及实例方法的示例。
//step #1 - Create a funnctional interface.
interface FuncInt {
//contains one and only abstract method
String answer(String x, boolean y);
}
//step #2 - Class providing method(s)that match FuncInt.answer()'s definition.
class Answer {
static String ans_math_static(String x, Boolean y) {
return "\"" + x + "\"" + "\t = \t" + y.toString().toUpperCase();
}
String ans_math_inst(String x, Boolean y) {
return "\"" + x + "\"" + "\t = \t" + y.toString().toUpperCase();
}
}
译注:以上代码的测试用例如下,因静态方法与实例方法结果相同,仅以静态方法为例。
Answer.ans_math_static("9 > 11 ?", false);
Answer.ans_math_static("987.6 < 1.1 ?", false);
Answer.ans_math_static("1 > 0.9 ?", true);
Answer.ans_math_static("T/F: Is Chengdu in Sichuan?", true);
Answer.ans_math_static("-1 % 0.2=0 ?", false);
Answer.ans_math_static("T/F: Does Dwyne Wade play for the Knicks?", false);
得到与原文举例相同的输出结果:
"9 > 11 ?" = FALSE
"987.6 < 1.1 ?" = FALSE
"1 > 0.9 ?" = TRUE
"T/F: Is Chengdu in Sichuan?" = TRUE
"-1 % 0.2=0 ?" = FALSE
"T/F: Does Dwyne Wade play for the Knicks?" = FALSE
使用方法引用的主要步骤有:
- 定义一个函数式接口
- 定义一个满足函数式接口抽象方法要求的方法
- 使用对步骤2中定义的 (x :: y ) 方法引用实例化函数式接口的实例。
- 译注:静态方法的方法引用格式为 类名 :: 方法名 ;实例方法的方法引用格式为 对象实例名 :: 方法名 。
- 使用函数式接口实例调用方法: Instance.AbstractMethod();
这提供了一种创建方法实现的可插拔方式。Lambda 表达式和方法引用为 Java 编程带来了一个功能方面的提升。
构造函数的方法引用
让我们开始详细讨论吧。
构造函数和其他方法一样是方法。对吗?错。它们有点特殊,它们是对象初始化方法。尽管如此,它们仍然是一个方法,没有什么能阻止我们像其他方法引用一样创建构造函数的方法引用。
//step #1 - Create a funnctional interface.
interface FuncInt {
//contains one and only abstract method
Automobile auto(String make, String model, short year);
}
//step #2 - Class providing method(s)that match FuncInt.answer()'s definition.
class Automobile {
//Trunk Member Variables
private String make;
private String model;
private short year;
//Automobile Constructor
public Automobile(String make, String model, short year) {
this.make = make;
this.model = model;
this.year = year;
}
protected void what() {
System.out.println("This Automobile is a" + year + " " + make + " " + model + ".");
}
}
//Step #3 - Class making use of method reference
public class ConstrRef {
static void createInstance() {
}
public static void main(String[] args) {
System.out.println();
//Remember, a Method Reference is an instance of a Functional Interface. Therefore....
FuncInt auto = Automobile::new;//We really don't gain much from this example
//Example #1
Automobile honda = auto.auto("honda", "Accord", (short) 2006);
honda.what();
//Example #1
Automobile bmw = auto.auto("BMW", "530i", (short) 2006);
bmw.what();
System.out.println();
}
}
输出结果
This Automobile is a2006 honda Accord.
This Automobile is a2006 BMW 530i.
说明
用户应该清楚的第一件事是这个基本示例没有那么实用。这是一种相当迂回的创建对象实例的方式。实际上,几乎可以肯定,你不会经历所有这些麻烦来创建一个 Automobile 实例,但是为了概念的完整性,还是要提及。
使用构造函数的方法引用的主要步骤有:
- 定义一个只有抽象方法的函数式接口,该方法的返回类型与你打算使用该对象进行构造函数引用的对象相同。
- 创建一个类,该类的构造函数与函数式接口的抽象方法匹配。
- 使用对步骤 #2 中定义的构造函数的方法引用,实例化函数式接口的实例。
- 译注:构造函数的方法引用格式为 类名 :: new
- 在步骤 #2 中使用构造函数引用实例化类的实例,例如 MyClass x = ConstructorReference.AbstractMethod (x, y, z…)
构造函数引用与泛型一起使用的时候变得更有用。通过使用泛型工厂方法,可以创建各种类型的对象。
让我们看一看。
//step #1 - Create a funnctional interface.
interface FuncInt<Ob, X, Y, Z> {
//contains one and only abstract method
Ob func(X make, Y model, Z year);
}
//step #2 - Create a Generic class providing a constructor compatible with FunInt.func()'s definition
class Automobile<X, Y, Z> {
//Automobile Member Variables
private X make;
private Y model;
private Z year;
//Automobile Constructor
public Automobile(X make, Y model, Z year) {
this.make = make;
this.model = model;
this.year = year;
}
protected void what() {
System.out.println("This Automobile is a " + year + " " + make + " " + model + ".");
}
}
//step #3 - Create a Non-Generic class providing a constructor compatible with FunInt.func()'s definition
class Plane {
//Automobile Member Variables
private String make;
private String model;
private int year;
//Plane Constructor
public Plane(String make, String model, int year) {
this.make = make;
this.model = model;
this.year = year;//Automatic unboxing
}
protected void what() {
System.out.println("This Plane is a " + year + " " + make + " " + model + ".");
}
}
//Step #3 - Class making use of method reference with generics
public class ConstrRefGen {
//Here is where the magic happens
static <Ob, X, Y, Z> Ob factory(FuncInt<Ob, X, Y, Z> obj, X p1, Y p2, Z p3) {
return obj.func(p1, p2, p3);
}
public static void main(String[] args) {
System.out.println();
//Example #1
FuncInt<Automobile<String, String, Integer>, String, String, Integer> auto_cons = Automobile<String, String, Integer>::new;
Automobile<String, String, Integer> honda = factory(auto_cons, "Honda", "Accord", 2006);
honda.what();
//Example #2
FuncInt<Plane, String, String, Integer> plane_cons = Plane::new;
Plane cessna = factory(plane_cons, "Cessna", "Skyhawk", 172);
cessna.what();
System.out.println();
}
}
输出结果
This Automobile is a 2006 Honda Accord.
This Plane is a 172 Cessna Skyhawk.
说明
这里有很多东西需要消化。事实上,如果你以前从未深入研究过泛型,那么这些代码看上去可能相当晦涩。让我们分解一下。
我们做的第一件事是创建一个通用的函数式接口。注意细节。我们有四个泛型类型参数:Ob、X、Y、Z。
- Ob 代表要引用其构造函数的类。
- X,Y,Z 代表该类的构造函数的参数。
如果我们替换泛型方法占位符,抽象方法可能是这样的: SomeClass func (String make, String model, int year)。注意,由于我们使接口具有了泛型,所以可以指定任何返回类型或我们希望返回的类实例。这释放了构造函数引用的真正潜力。
接下来的两个部分相对简单,我们创建了相同的类,一个泛型类和一个非泛型类,以演示它们与在公共类中定义的工厂方法的互操作性。注意,这些类的构造函数与 FuncInt.func() 的方法签名是兼容的。
进入公共类的文件。这个方法就是奇迹发生的地方。
//Here is where the magic happens
static <Ob, X, Y, Z> Ob factory(FuncInt<Ob, X, Y, Z> obj, X p1, Y p2, Z p3) {
return obj.func(p1, p2, p3);
}
我们将该方法标记为静态的,所以我们可以不使用 ConstRefGen 实例,毕竟它是一个工厂方法。注意,factory 方法具有与函数式接口相同的泛型类型参数。注意,方法的返回类型是 Ob,它可以是由我们决定的任何类。当然,X、Y、Z是 Ob 中方法的方法参数。请注意,该函数以 FuncInt 的一个实例作为参数(类类型和方法参数作为类型参数),同时也接受 Ob 类型的类作为方法的参数。
在方法体中,它调用方法引用并将在 factory() 中传递的参数提供给它。
我们的第一个任务是创建一个符合 FuncInt<> 的方法引用。
这里我们分别引用 Automobile 类和 Plane 类的构造函数。
我们的下一个任务是创建一个带有方法引用的对象。
为此,我们调用 factory() 并将它需要的构造函数引用以及 factory() 定义的有关构造函数的参数提供给它。factory() 可以灵活地创建对各种方法的构造函数引用,因为它是通用的。因为 Plane 类和 Automobile 类的构造函数匹配 FuncInt.func() 的方法签名,所以它们可作为 FuncInt.func() 的方法引用使用。factory() 通过调用 obj.func(x,y,z) 返回类的一个实例,这是一个构造函数方法引用,当求值时,它将为你提供指定为其参数的类的一个实例。
斟酌这个问题一段时间,会发现它是Java的一个非常有用的补充 ;)
相关推荐
- 为何越来越多的编程语言使用JSON(为什么编程)
-
JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...
- 何时在数据库中使用 JSON(数据库用json格式存储)
-
在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...
- MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)
-
前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...
- JSON对象花样进阶(json格式对象)
-
一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...
- 深入理解 JSON 和 Form-data(json和formdata提交区别)
-
在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...
- JSON 语法(json 语法 priority)
-
JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...
- JSON语法详解(json的语法规则)
-
JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...
- MySQL JSON数据类型操作(mysql的json)
-
概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...
- JSON的数据模式(json数据格式示例)
-
像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...
- 前端学习——JSON格式详解(后端json格式)
-
JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...
- 什么是 JSON:详解 JSON 及其优势(什么叫json)
-
现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...
- PostgreSQL JSON 类型:处理结构化数据
-
PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...
- JavaScript:JSON、三种包装类(javascript 包)
-
JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...
- Python数据分析 只要1分钟 教你玩转JSON 全程干货
-
Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...
- 比较一下JSON与XML两种数据格式?(json和xml哪个好)
-
JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- r语言矩阵 (127)
- browsererror (114)
- exportexcel (119)
- cv2.bitwise_not (137)
- dump命令 (128)
- es6concat (126)
- heapify (127)
- java.security.egd (130)
- javax.annotation (117)
- jsstringsplit (117)
- js数字 (115)
- maven编译 (132)
- mysqlleft (128)
- nodejsbuffer (149)
- org.apache.commons.httpclient (126)
- org.jsoup (141)
- org.springframework.web (128)
- robotframework-ride (115)
- setnocounton (141)
- socket.gethostbyname (122)
- sqlmid (121)
- time.strptime (133)
- vscode格式化 (125)
- win32con (129)
- window.localstorage (126)