Java有时可能非常棘手,特别是在API设计中。 让我们看一个非常有趣的展示柜。 jOOQ强烈地将API与实现分开。 所有API都在org.jooq包中,并且是公共的。 大多数实现都在org.jooq.impl包和package-private中。 只有工厂和一些专用的基础实现是公开的。 这允许非常强大的包级封装,几乎只向jOOQ用户公开接口。

包级封装的简化示例

大致来说,jOOQ如何建模SQL表。 (过于简化的)API:

package org.jooq;/*** A table in a database*/
public interface Table {/*** Join two tables*/Table join(Table table);
}

还有两个(过于简化的)实现类:

package org.jooq.impl;import org.jooq.Table;/*** Base implementation*/
abstract class AbstractTable implements Table {@Overridepublic Table join(Table table) {return null;}
}/*** Custom implementation, publicly exposed to client code*/
public class CustomTable extends AbstractTable {
}

内部API的公开方式

假设内部API在协方差方面有一些技巧:

abstract class AbstractTable implements Table, InteralStuff {// Note, this method returns AbstractTable, as it might// prove to be convenient to expose some internal API// facts within the internal API itself@Overridepublic AbstractTable join(Table table) {return null;}/*** Some internal API method, also package private*/void doThings() {}void doMoreThings() {// Use the internal APIjoin(this).doThings();}
}

乍一看,这看起来很安全,是吗? AbstractTable是包私有的,但是CustomTable对其进行了扩展并继承了其所有API,包括“ AbstractTable join(Table)”的协变方法重写。 这会导致什么? 查看以下客户代码

package org.jooq.test;import org.jooq.Table;
import org.jooq.impl.CustomTable;public class Test {public static void main(String[] args) {Table joined = new CustomTable();// This works, no knowledge of AbstractTable exposed to the compilerTable table1 = new CustomTable();Table join1 = table1.join(joined);// This works, even if join exposes AbstractTableCustomTable table2 = new CustomTable();Table join2 = table2.join(joined);// This doesn't work. The type AbstractTable is not visibleTable join3 = table2.join(joined).join(joined);//            ^^^^^^^^^^^^^^^^^^^ This cannot be dereferenced// ... so hide these implementation details again// The API flaw can be circumvented with castingTable join4 = ((Table) table2.join(joined)).join(joined);}
}

结论

篡改类层次结构中的可见性可能很危险。 注意以下事实:在接口中声明的API方法始终是公共的,而不管涉及非公共工件的任何协变实现。 如果API设计人员无法正确处理API用户,这可能会很烦人。

在下一版的jOOQ中已修复

参考: Java的深度:在JAVA,SQL和JOOQ博客中, JCG合作伙伴 Lukas Eder 通过协方差暴露了API泄漏 。

翻译自: https://www.javacodegeeks.com/2012/05/depths-of-java-api-leak-exposed-through.html

Java的深度:通过协方差暴露的API泄漏相关推荐

  1. java 计算协方差_Java的深度:通过协方差暴露的API泄漏

    java 计算协方差 Java有时可能非常棘手,特别是在API设计中. 让我们看一个非常有趣的展示柜. jOOQ强烈地将API与实现分开. 所有API都在org.jooq包中,并且是公共的. 大多数实 ...

  2. [转载] java 计算协方差_Java的深度:通过协方差暴露的API泄漏

    参考链接: 关于Java中null的有趣事实 java 计算协方差 Java有时可能非常棘手,特别是在API设计中. 让我们看一个非常有趣的展示柜. jOOQ强烈地将API与实现分开. 所有API都在 ...

  3. 用 Java 训练深度学习模型,原来这么简单

    作者 | DJL-Keerthan&Lanking 来源 | HelloGitHub 头图 | CSDN下载自东方IC 前言 很长时间以来,Java 都是一个很受企业欢迎的编程语言.得益于丰富 ...

  4. Java培训深度学习都要学什么

    java的知识点有很多,如果是有java基础的同学,进行深度学习是非常有必要的,比较职场技能更新迭代非常的快,那么java培训深度学习都要学什么呢?来看看下面的详细介绍. Java培训深度学习都要学什 ...

  5. 【深度学习】利用一些API进行图像数据增广

    [深度学习]利用一些API进行图像数据增广 文章目录 [深度学习]利用一些API进行图像数据增广 1 先送上一份最强的翻转代码(基于PIL) 2 Keras中的数据增强API种类概述 3 特征标准化 ...

  6. java.lang.NoSuchMethodError: org.apache.flink.table.api.TableColumn.isGenerated()Z

    完整报错如下: select * from dim_behavior; [ERROR] Could not execute SQL statement. Reason: java.lang.NoSuc ...

  7. Cannot resolve method ‘call(java.lang.String, org.apache.flink.table.api.ApiExpression)‘

    intellij提示: Cannot resolve method 'call(java.lang.String, org.apache.flink.table.api.ApiExpression)' ...

  8. java asm tree_使用ASM 4处理Java类文件–第二部分:Tree API

    java asm tree 什么是ASM树API: ASM树API是ASM的一部分,可让您创建/修改内存中的类. 该类被视为信息树. 像整个类一样,它是ClassNode的实例,其中包含FieldNo ...

  9. Java EE 7中的WebSocket客户端API

    在本文中,让我们探索谈论较少的Web Socket Client API,以及如何在Java EE 7容器本身中利用它. Web套接字服务器API规则 JSR 356的服务器端API(Java的Web ...

最新文章

  1. java swing 架构_Java Swing1 基本框架
  2. zlib 离线安装_黑板派Python扩展库安装与常见问题解决完整指南
  3. 如何配置php的ip地址吗,linux如何配置IP
  4. java技术简介英文_Java技术常见的英文缩写
  5. JavaScript -- DOM树
  6. Android源码kernel编译
  7. 找出区间偶数c语言,c语言实践输出某个区间中不是3的倍数的偶数
  8. linux:查看使用中的端口
  9. latex制作中英文简历(含模板代码)
  10. matlab将txt转成dat,将matlab中数据保存为txt或dat格式
  11. 比较 SVFI-RIFE 和 DAIN-APP 补针效果 施工中 ~
  12. 用HTML开发Windows桌面应用程序
  13. Eclipse的乱码问题是如何解决的
  14. android起始页面与导航页面
  15. 周期循环图像边界算法
  16. 如何快速准备面试中的算法,获得 Offer?
  17. 情感分析方法之nltk情感分析器和SVM分类器(二)
  18. 微信小程序之天气查询小案例
  19. 测试小白基于java的selenium自动化测试环境搭建
  20. UML画图工具-Graphviz和PlantUML

热门文章

  1. java安全——数字签名+代码签名
  2. 构建器设计模式_创新设计模式:构建器模式
  3. deprecated_@Deprecated新外观可能是什么?
  4. 工程模式和抽象工厂模式_功能工厂模式
  5. jboss 4.3.0_JBoss BPM Suite 6.0.3版本的5个实用技巧
  6. docker 部署java_使用Java EE 7,WildFly和Docker进行持续部署–(第1部分)
  7. Servlet和JSP之间的区别
  8. 如何在CircleCI上构建支持Graal的JDK8?
  9. spring预加载与懒加载_通过Spring将继承树加载到List中
  10. 雅加达EE:干净的板岩