Scala中有一个概念,叫做“视界”。所谓“视界”是指,我不care这个对象具体是什么类型,但我可以把它“视作”某种类型加以利用。
比如说,有如下的函数定义:
def quick[T <% Ordered[T]](list: List[T]): List[T] = {
list match {
case Nil => Nil
case x::xs =>
val (before,after) = xs partition (_ < x)
quick(before) ++ (x :: quick(after))
}
}
OK,这是我从别的地方抄来的快速排序算法实现。重点不在算法这里。在“<%”这个符号上。这个符号说明了,对于T这个类型,只要符合与Ordered[T]的调用方式,甚至可以不是Ordered[T]的子类,都可以放到这个函数中使用。举例来说:
trait Ordered[T] {
def < (x: T): Boolean
}
Ordered特质定义了“<”这个函数。而Int类也定义了相同签名的函数,只是Int类并不继承于Ordered特质(这里继承的说法可能欠妥,Java习惯性思维,见谅)。因此,前面的快速排序使用了“<%”符号说明,只要能把对象“视作”某种类型,就可以用这个函数来排序。
那么,Java中是否可以用同样的思想做些什么事情呢?举例如下:
我们知道,连接数据库有三种常见对象,分别是Connection,Statement,以及ResultSet。这三种对象都有关闭方法,且签名一致。
public interface Connection {
//...
/**
* @exception SQLException if a database access error occurs
*/
void close() throws SQLException;
//...
}
public interface ResultSet {
//...
/**
* @exception SQLException if a database access error occurs
*/
void close() throws SQLException;
//...
}
public interface Statement {
//...
/**
* @exception SQLException if a database access error occurs
*/
void close() throws SQLException;
//...
}
为了聚集问题,摘抄的是JDK1.5的代码,因此可能与你看到的源代码不尽一致。
我们可以发现,三个对象源于三个接口,虽然方法签名一致,但接口不一样,因此无法作为同一类对象发给释放资源的函数。从而为了安全地释放三个对象,你需要这样写代码:
private void recycle(Connection conn, Statement stmt, ResultSet rs)
{
if (rs != null) {
try {
rs.close();
} catch (SQLException ex) {
// no-op
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException ex) {
// no-op
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException ex) {
// no-op
}
}
}
一般来讲,应该是这个样子的吧?每个对象的SQLException都必须单独catch住,并且什么都不做,然后执行下一个对象的释放。当然这里做的有点儿绝对,你可以考虑仅释放conn即可,我只是拿来做例子。
这里我们看到的是,三个对象的接口类型都包含了public void close() throws SQLException;方法,但它们不是同一个类型的对象。那么有什么办法把它们“视作”同一个对象吗?
以下的作法是错误的。
interface Resource
{
void close() throws SQLException;
}
//...
private void close(Resource res)
{
if (res != null) {
try {
res.close();
} catch (SQLException ex) {
// no-op
}
}
}
private void recycle(Connection conn, Statement stmt, ResultSet rs)
{
close((Resource) rs);
close((Resource) stmt);
close((Resource) conn);
}
//...
因为对象不能被造型为非父类或父接口的类型。
不过以上的方法启发了我们,我们需要的就是类似于“视界”效果的一种操作,或者说是辅助方法。因为Java内部没有建立“%>”机制,所以我们需要自己做。
以下是使用Java的Proxy实现的辅助方法,可以把任何对象造型为另一种类型的对象。不过造型之前会首先检查是否合法。目前仅检查函数名与参数列表,若细致一些还可以增加对访问修饰符和抛出异常的检查。
final class ViewBoundHelper
{
private ViewBoundHelper() { /* no-op */ }
private static final class Handler implements InvocationHandler
{
private final Object target;
public Handler(Object t)
{
target = t;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
return getDeclaredMethod(method).invoke(target, args);
}
Method getDeclaredMethod(Method m)
{
Class<?> cls = target.getClass();
while (true) {
try {
m = cls.getDeclaredMethod(m.getName(), m.getParameterTypes());
break;
} catch (NoSuchMethodException ex) {
cls = cls.getSuperclass();
if (cls == null) {
return null;
}
}
}
return m;
}
}
public static Object asIs(Object o, Class<?> intf)
{
Handler handler = new Handler(o);
for (Method method : intf.getDeclaredMethods()) {
if (handler.getDeclaredMethod(method) == null) {
throw new ClassCastException(o.getClass() + "can't be viewed as " + intf.getName());
}
}
return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[] {
intf
}, handler);
}
}
使用方式如下:
public static void main(String[] args) throws SQLException
{
Connection conn = new FakeConn();
Resource res = (Resource) ViewBoundHelper.asIs(conn, Resource.class);
res.close();
System.out.println(res);
}
分享到:
相关推荐
SpringBoot + SpringData Jpa + Scala + Mysql(java+Scala混编)
基于java、scala、python、spark实现的图书推荐系统源码+项目说明.zip基于java、scala、python、spark实现的图书推荐系统源码+项目说明.zip基于java、scala、python、spark实现的图书推荐系统源码+项目说明.zip基于...
博客配套文件,详细演示了在maven中如何混合编译java和scala共存的代码。
Master the fundamentals of Scala and understand its emphasis on functional programming that sets it apart from Java. This book will help you translate what you already know in Java to Scala to start ...
本资源提供了一套基于Java、Scala和Spark的数据处理与分析设计源码,包含1381个文件,其中包括634个CRC文件,316个BK文件,35个Class字节码文件,20个XML配置文件,15个Java源代码文件,13个JAR打包文件,8个...
Java 和 Scala 并发性基础
JAVA+Scala语言开发基于机器学习的商品类目预测源码+文档说明.zip本资源中的源码都是经过本地编译过可运行的,评审分达到95分以上。资源项目的难度比较适中,内容都是经过助教老师审定过的能够满足学习、使用需求,...
面向Java开发人员的Scala指南 面向Java开发人员的Scala指南
功能:实现google的PageRank算法,带完整的测试数据和结果,java、scala语言版本 ********************************************************* 版本: scala2.10.4 spark 1.6.1 Scala IDE Build id: 4.4.1-vfinal...
Scala到Java 用Scala编写的简单工具,揭示了Scala编译器的奥秘。 从StdIn读取scala代码,并将其反编译的Java版本写入StdOut。 用法 确保您已安装Java 1.8和Maven 检出项目 在项目目录中调用mvn clean package 。 ...
Java中的函数式编程_Java_Scala_下载.zip
主要介绍了Java 和 Scala 如何调用变参,帮助大家更好的理解和学习Java与Scala,感兴趣的朋友可以了解下
Java电商大数据项目-推荐系统(java和scala语言) Bump spark.version from 2.1.0 to 2.4.7 in /MySparkProject dependencies #6 by dependabot bot was merged 4 minutes ago Bump junit from 3.8.1 to 4.13.1 in /...
1、资源内容:java电商大数据项目-推荐系统(java和scala语言) 2、适用人群:计算机,电子信息工程、数学等专业的学习者,作为java实战项目,课程设计,毕业设计“参考资料”参考学习使用。 3、解压说明:本资源需要...
赠送jar包:scala-java8-compat_2.11-0.7.0.jar; 赠送原API文档:scala-java8-compat_2.11-0.7.0-javadoc.jar; 赠送源代码:scala-java8-compat_2.11-0.7.0-sources.jar; 赠送Maven依赖信息文件:scala-java8-...
一个基于Spring Boot的Spark开发手脚架(Java+Scala),开箱即用!模拟了1个WordCount
本项目是一个基于Java和Scala语言开发的Spark基础教程配套源码,包含55个文件,主要文件类型包括Java源代码、Scala源代码、XML配置文件、日志文件、Git忽略文件、LICENSE文件和Idea配置文件。系统设计旨在为学习...
基于SpringBoot/WebFlux+Shiro+JPA+Java/Scala,实现的数据库细粒度动态权限管理系统(源码),项目经过严格测试,确保可以运行! 环境 SpringBoot 2.0.3.RELEASE SpringBoot WebFlux SpringBoot Data Jpa Apache ...
在CentOS7 环境下,基于 Proj7 + Geos3.8.2 + GDAL3.2.3 + 依赖编译的 点云处理工具PDAL 2.3.0的Java/Scala开发依赖包
面向Java开发人员Scala指南,Scala和servlet的比较 以及一些网上资料的整理,给大家分享分享!!!